blob: 912e3f2a952be6c75bc1171038f8dbef3abd9ace [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package vdl
import (
"fmt"
"reflect"
"sync"
"testing"
"unsafe"
)
// Tests of TypeFromReflect success.
type rtTest struct {
rt reflect.Type
t *Type
}
// rtKeyTests contains types that may be used as map keys.
var rtKeyTests = []rtTest{
// Unnamed scalars
{reflect.TypeOf(bool(false)), BoolType},
{reflect.TypeOf(byte(0)), ByteType},
{reflect.TypeOf(uint16(0)), Uint16Type},
{reflect.TypeOf(uint32(0)), Uint32Type},
{reflect.TypeOf(uint64(0)), Uint64Type},
{reflect.TypeOf(uint(0)), testUintType()},
{reflect.TypeOf(uintptr(0)), testUintptrType()},
{reflect.TypeOf(int8(0)), Int8Type},
{reflect.TypeOf(int16(0)), Int16Type},
{reflect.TypeOf(int32(0)), Int32Type},
{reflect.TypeOf(int64(0)), Int64Type},
{reflect.TypeOf(int(0)), testIntType()},
{reflect.TypeOf(float32(0)), Float32Type},
{reflect.TypeOf(float64(0)), Float64Type},
{reflect.TypeOf(string("")), StringType},
// Named scalars
{reflect.TypeOf(NBool(false)), NameN("Bool", BoolType)},
{reflect.TypeOf(NByte(0)), NameN("Byte", ByteType)},
{reflect.TypeOf(NUint16(0)), NameN("Uint16", Uint16Type)},
{reflect.TypeOf(NUint32(0)), NameN("Uint32", Uint32Type)},
{reflect.TypeOf(NUint64(0)), NameN("Uint64", Uint64Type)},
{reflect.TypeOf(NUint(0)), NameN("Uint", testUintType())},
{reflect.TypeOf(NUintptr(0)), NameN("Uintptr", testUintptrType())},
{reflect.TypeOf(NInt8(0)), NameN("Int8", Int8Type)},
{reflect.TypeOf(NInt16(0)), NameN("Int16", Int16Type)},
{reflect.TypeOf(NInt32(0)), NameN("Int32", Int32Type)},
{reflect.TypeOf(NInt64(0)), NameN("Int64", Int64Type)},
{reflect.TypeOf(NInt(0)), NameN("Int", testIntType())},
{reflect.TypeOf(NFloat32(0)), NameN("Float32", Float32Type)},
{reflect.TypeOf(NFloat64(0)), NameN("Float64", Float64Type)},
{reflect.TypeOf(NString("")), NameN("String", StringType)},
// Unnamed arrays
{reflect.TypeOf([3]bool{}), ArrayType(3, BoolType)},
{reflect.TypeOf([3]byte{}), ArrayType(3, ByteType)},
{reflect.TypeOf([3]uint16{}), ArrayType(3, Uint16Type)},
{reflect.TypeOf([3]uint32{}), ArrayType(3, Uint32Type)},
{reflect.TypeOf([3]uint64{}), ArrayType(3, Uint64Type)},
{reflect.TypeOf([3]uint{}), ArrayType(3, testUintType())},
{reflect.TypeOf([3]uintptr{}), ArrayType(3, testUintptrType())},
{reflect.TypeOf([3]int8{}), ArrayType(3, Int8Type)},
{reflect.TypeOf([3]int16{}), ArrayType(3, Int16Type)},
{reflect.TypeOf([3]int32{}), ArrayType(3, Int32Type)},
{reflect.TypeOf([3]int64{}), ArrayType(3, Int64Type)},
{reflect.TypeOf([3]int{}), ArrayType(3, testIntType())},
{reflect.TypeOf([3]float32{}), ArrayType(3, Float32Type)},
{reflect.TypeOf([3]float64{}), ArrayType(3, Float64Type)},
{reflect.TypeOf([3]string{}), ArrayType(3, StringType)},
// Named arrays
{reflect.TypeOf(NArray3Bool{}), NameNArray("Bool", BoolType)},
{reflect.TypeOf(NArray3Byte{}), NameNArray("Byte", ByteType)},
{reflect.TypeOf(NArray3Uint16{}), NameNArray("Uint16", Uint16Type)},
{reflect.TypeOf(NArray3Uint32{}), NameNArray("Uint32", Uint32Type)},
{reflect.TypeOf(NArray3Uint64{}), NameNArray("Uint64", Uint64Type)},
{reflect.TypeOf(NArray3Uint{}), NameNArray("Uint", testUintType())},
{reflect.TypeOf(NArray3Uintptr{}), NameNArray("Uintptr", testUintptrType())},
{reflect.TypeOf(NArray3Int8{}), NameNArray("Int8", Int8Type)},
{reflect.TypeOf(NArray3Int16{}), NameNArray("Int16", Int16Type)},
{reflect.TypeOf(NArray3Int32{}), NameNArray("Int32", Int32Type)},
{reflect.TypeOf(NArray3Int64{}), NameNArray("Int64", Int64Type)},
{reflect.TypeOf(NArray3Int{}), NameNArray("Int", testIntType())},
{reflect.TypeOf(NArray3Float32{}), NameNArray("Float32", Float32Type)},
{reflect.TypeOf(NArray3Float64{}), NameNArray("Float64", Float64Type)},
{reflect.TypeOf(NArray3String{}), NameNArray("String", StringType)},
// Unnamed structs
{reflect.TypeOf(struct{ X bool }{}), StructType(Field{"X", BoolType})},
{reflect.TypeOf(struct{ X byte }{}), StructType(Field{"X", ByteType})},
{reflect.TypeOf(struct{ X uint16 }{}), StructType(Field{"X", Uint16Type})},
{reflect.TypeOf(struct{ X uint32 }{}), StructType(Field{"X", Uint32Type})},
{reflect.TypeOf(struct{ X uint64 }{}), StructType(Field{"X", Uint64Type})},
{reflect.TypeOf(struct{ X uint }{}), StructType(Field{"X", testUintType()})},
{reflect.TypeOf(struct{ X uintptr }{}), StructType(Field{"X", testUintptrType()})},
{reflect.TypeOf(struct{ X int8 }{}), StructType(Field{"X", Int8Type})},
{reflect.TypeOf(struct{ X int16 }{}), StructType(Field{"X", Int16Type})},
{reflect.TypeOf(struct{ X int32 }{}), StructType(Field{"X", Int32Type})},
{reflect.TypeOf(struct{ X int64 }{}), StructType(Field{"X", Int64Type})},
{reflect.TypeOf(struct{ X int }{}), StructType(Field{"X", testIntType()})},
{reflect.TypeOf(struct{ X float32 }{}), StructType(Field{"X", Float32Type})},
{reflect.TypeOf(struct{ X float64 }{}), StructType(Field{"X", Float64Type})},
{reflect.TypeOf(struct{ X string }{}), StructType(Field{"X", StringType})},
// Named structs
{reflect.TypeOf(NStructBool{}), NameNStruct("Bool", BoolType)},
{reflect.TypeOf(NStructByte{}), NameNStruct("Byte", ByteType)},
{reflect.TypeOf(NStructUint16{}), NameNStruct("Uint16", Uint16Type)},
{reflect.TypeOf(NStructUint32{}), NameNStruct("Uint32", Uint32Type)},
{reflect.TypeOf(NStructUint64{}), NameNStruct("Uint64", Uint64Type)},
{reflect.TypeOf(NStructUint{}), NameNStruct("Uint", testUintType())},
{reflect.TypeOf(NStructUintptr{}), NameNStruct("Uintptr", testUintptrType())},
{reflect.TypeOf(NStructInt8{}), NameNStruct("Int8", Int8Type)},
{reflect.TypeOf(NStructInt16{}), NameNStruct("Int16", Int16Type)},
{reflect.TypeOf(NStructInt32{}), NameNStruct("Int32", Int32Type)},
{reflect.TypeOf(NStructInt64{}), NameNStruct("Int64", Int64Type)},
{reflect.TypeOf(NStructInt{}), NameNStruct("Int", testIntType())},
{reflect.TypeOf(NStructFloat32{}), NameNStruct("Float32", Float32Type)},
{reflect.TypeOf(NStructFloat64{}), NameNStruct("Float64", Float64Type)},
{reflect.TypeOf(NStructString{}), NameNStruct("String", StringType)},
// Special-case types
{reflect.TypeOf(NEnum(0)), NameN("Enum", EnumType("A", "B", "C", "ABC"))},
{reflect.TypeOf((*NUnionABC)(nil)).Elem(), UnionABCTypeN},
{reflect.TypeOf(NUnionABCA{}), UnionABCTypeN},
{reflect.TypeOf(NUnionABCB{}), UnionABCTypeN},
{reflect.TypeOf(NUnionABCC{}), UnionABCTypeN},
{reflect.TypeOf(NNative(0)), WireTypeN},
{reflect.TypeOf(NWire{}), WireTypeN},
}
var (
nonPtrError error = NonPtrError{}
ptrError error = &PtrError{}
)
// rtNonKeyTests contains types that may not be used as map keys.
var rtNonKeyTests = []rtTest{
// Unnamed scalars
{reflect.Type(nil), AnyType},
{reflect.TypeOf((*interface{})(nil)), AnyType},
{reflect.TypeOf((*interface{})(nil)).Elem(), AnyType},
{reflect.TypeOf((*error)(nil)), ErrorType},
{reflect.TypeOf((*error)(nil)).Elem(), ErrorType},
{reflect.TypeOf(&nonPtrError), ErrorType},
{reflect.TypeOf(&ptrError), ErrorType},
{reflect.TypeOf((*Type)(nil)), TypeObjectType},
// Named scalars (we cannot detect the error type if it is named)
{reflect.TypeOf((*NInterface)(nil)), AnyType},
{reflect.TypeOf((*NInterface)(nil)).Elem(), AnyType},
// Unnamed arrays
{reflect.TypeOf([3]interface{}{}), ArrayType(3, AnyType)},
{reflect.TypeOf([3]error{}), ArrayType(3, ErrorType)},
{reflect.TypeOf([3]*Type{}), ArrayType(3, TypeObjectType)},
// Named arrays
{reflect.TypeOf(NArray3Interface{}), NameNArray("Interface", AnyType)},
{reflect.TypeOf(NArray3TypeObject{}), NameNArray("TypeObject", TypeObjectType)},
// Unnamed structs
{reflect.TypeOf(struct{ X interface{} }{}), StructType(Field{"X", AnyType})},
{reflect.TypeOf(struct{ X error }{}), StructType(Field{"X", ErrorType})},
{reflect.TypeOf(struct{ X *Type }{}), StructType(Field{"X", TypeObjectType})},
// Named structs
{reflect.TypeOf(NStructInterface{}), NameNStruct("Interface", AnyType)},
{reflect.TypeOf(NStructTypeObject{}), NameNStruct("TypeObject", TypeObjectType)},
// Unnamed slices
{reflect.TypeOf([]interface{}{}), ListType(AnyType)},
{reflect.TypeOf([]error{}), ListType(ErrorType)},
{reflect.TypeOf([]*Type{}), ListType(TypeObjectType)},
{reflect.TypeOf([]bool{}), ListType(BoolType)},
{reflect.TypeOf([]byte{}), ListType(ByteType)},
{reflect.TypeOf([]uint16{}), ListType(Uint16Type)},
{reflect.TypeOf([]uint32{}), ListType(Uint32Type)},
{reflect.TypeOf([]uint64{}), ListType(Uint64Type)},
{reflect.TypeOf([]uint{}), ListType(testUintType())},
{reflect.TypeOf([]uintptr{}), ListType(testUintptrType())},
{reflect.TypeOf([]int8{}), ListType(Int8Type)},
{reflect.TypeOf([]int16{}), ListType(Int16Type)},
{reflect.TypeOf([]int32{}), ListType(Int32Type)},
{reflect.TypeOf([]int64{}), ListType(Int64Type)},
{reflect.TypeOf([]int{}), ListType(testIntType())},
{reflect.TypeOf([]float32{}), ListType(Float32Type)},
{reflect.TypeOf([]float64{}), ListType(Float64Type)},
{reflect.TypeOf([]string{}), ListType(StringType)},
// Named slices
{reflect.TypeOf(NSliceInterface{}), NameNSlice("Interface", AnyType)},
{reflect.TypeOf(NSliceTypeObject{}), NameNSlice("TypeObject", TypeObjectType)},
{reflect.TypeOf(NSliceBool{}), NameNSlice("Bool", BoolType)},
{reflect.TypeOf(NSliceByte{}), NameNSlice("Byte", ByteType)},
{reflect.TypeOf(NSliceUint16{}), NameNSlice("Uint16", Uint16Type)},
{reflect.TypeOf(NSliceUint32{}), NameNSlice("Uint32", Uint32Type)},
{reflect.TypeOf(NSliceUint64{}), NameNSlice("Uint64", Uint64Type)},
{reflect.TypeOf(NSliceUint{}), NameNSlice("Uint", testUintType())},
{reflect.TypeOf(NSliceUintptr{}), NameNSlice("Uintptr", testUintptrType())},
{reflect.TypeOf(NSliceInt8{}), NameNSlice("Int8", Int8Type)},
{reflect.TypeOf(NSliceInt16{}), NameNSlice("Int16", Int16Type)},
{reflect.TypeOf(NSliceInt32{}), NameNSlice("Int32", Int32Type)},
{reflect.TypeOf(NSliceInt64{}), NameNSlice("Int64", Int64Type)},
{reflect.TypeOf(NSliceInt{}), NameNSlice("Int", testIntType())},
{reflect.TypeOf(NSliceFloat32{}), NameNSlice("Float32", Float32Type)},
{reflect.TypeOf(NSliceFloat64{}), NameNSlice("Float64", Float64Type)},
{reflect.TypeOf(NSliceString{}), NameNSlice("String", StringType)},
// Unnamed sets
{reflect.TypeOf(map[bool]struct{}{}), rtSet(BoolType)},
{reflect.TypeOf(map[byte]struct{}{}), rtSet(ByteType)},
{reflect.TypeOf(map[uint16]struct{}{}), rtSet(Uint16Type)},
{reflect.TypeOf(map[uint32]struct{}{}), rtSet(Uint32Type)},
{reflect.TypeOf(map[uint64]struct{}{}), rtSet(Uint64Type)},
{reflect.TypeOf(map[uint]struct{}{}), rtSet(testUintType())},
{reflect.TypeOf(map[uintptr]struct{}{}), rtSet(testUintptrType())},
{reflect.TypeOf(map[int8]struct{}{}), rtSet(Int8Type)},
{reflect.TypeOf(map[int16]struct{}{}), rtSet(Int16Type)},
{reflect.TypeOf(map[int32]struct{}{}), rtSet(Int32Type)},
{reflect.TypeOf(map[int64]struct{}{}), rtSet(Int64Type)},
{reflect.TypeOf(map[int]struct{}{}), rtSet(testIntType())},
{reflect.TypeOf(map[float32]struct{}{}), rtSet(Float32Type)},
{reflect.TypeOf(map[float64]struct{}{}), rtSet(Float64Type)},
{reflect.TypeOf(map[string]struct{}{}), rtSet(StringType)},
// Named sets
{reflect.TypeOf(NSetBool{}), NameNSet("Bool", BoolType)},
{reflect.TypeOf(NSetByte{}), NameNSet("Byte", ByteType)},
{reflect.TypeOf(NSetUint16{}), NameNSet("Uint16", Uint16Type)},
{reflect.TypeOf(NSetUint32{}), NameNSet("Uint32", Uint32Type)},
{reflect.TypeOf(NSetUint64{}), NameNSet("Uint64", Uint64Type)},
{reflect.TypeOf(NSetUint{}), NameNSet("Uint", testUintType())},
{reflect.TypeOf(NSetUintptr{}), NameNSet("Uintptr", testUintptrType())},
{reflect.TypeOf(NSetInt8{}), NameNSet("Int8", Int8Type)},
{reflect.TypeOf(NSetInt16{}), NameNSet("Int16", Int16Type)},
{reflect.TypeOf(NSetInt32{}), NameNSet("Int32", Int32Type)},
{reflect.TypeOf(NSetInt64{}), NameNSet("Int64", Int64Type)},
{reflect.TypeOf(NSetInt{}), NameNSet("Int", testIntType())},
{reflect.TypeOf(NSetFloat32{}), NameNSet("Float32", Float32Type)},
{reflect.TypeOf(NSetFloat64{}), NameNSet("Float64", Float64Type)},
{reflect.TypeOf(NSetString{}), NameNSet("String", StringType)},
// Unnamed maps
{reflect.TypeOf(map[bool]bool{}), rtMap(BoolType)},
{reflect.TypeOf(map[byte]byte{}), rtMap(ByteType)},
{reflect.TypeOf(map[uint16]uint16{}), rtMap(Uint16Type)},
{reflect.TypeOf(map[uint32]uint32{}), rtMap(Uint32Type)},
{reflect.TypeOf(map[uint64]uint64{}), rtMap(Uint64Type)},
{reflect.TypeOf(map[uint]uint{}), rtMap(testUintType())},
{reflect.TypeOf(map[uintptr]uintptr{}), rtMap(testUintptrType())},
{reflect.TypeOf(map[int8]int8{}), rtMap(Int8Type)},
{reflect.TypeOf(map[int16]int16{}), rtMap(Int16Type)},
{reflect.TypeOf(map[int32]int32{}), rtMap(Int32Type)},
{reflect.TypeOf(map[int64]int64{}), rtMap(Int64Type)},
{reflect.TypeOf(map[int]int{}), rtMap(testIntType())},
{reflect.TypeOf(map[float32]float32{}), rtMap(Float32Type)},
{reflect.TypeOf(map[float64]float64{}), rtMap(Float64Type)},
{reflect.TypeOf(map[string]string{}), rtMap(StringType)},
// Named maps
{reflect.TypeOf(NMapBool{}), NameNMap("Bool", BoolType)},
{reflect.TypeOf(NMapByte{}), NameNMap("Byte", ByteType)},
{reflect.TypeOf(NMapUint16{}), NameNMap("Uint16", Uint16Type)},
{reflect.TypeOf(NMapUint32{}), NameNMap("Uint32", Uint32Type)},
{reflect.TypeOf(NMapUint64{}), NameNMap("Uint64", Uint64Type)},
{reflect.TypeOf(NMapUint{}), NameNMap("Uint", testUintType())},
{reflect.TypeOf(NMapUintptr{}), NameNMap("Uintptr", testUintptrType())},
{reflect.TypeOf(NMapInt8{}), NameNMap("Int8", Int8Type)},
{reflect.TypeOf(NMapInt16{}), NameNMap("Int16", Int16Type)},
{reflect.TypeOf(NMapInt32{}), NameNMap("Int32", Int32Type)},
{reflect.TypeOf(NMapInt64{}), NameNMap("Int64", Int64Type)},
{reflect.TypeOf(NMapInt{}), NameNMap("Int", testIntType())},
{reflect.TypeOf(NMapFloat32{}), NameNMap("Float32", Float32Type)},
{reflect.TypeOf(NMapFloat64{}), NameNMap("Float64", Float64Type)},
{reflect.TypeOf(NMapString{}), NameNMap("String", StringType)},
// Recursive types
{reflect.TypeOf(NRecurseSelf{}), RecurseSelfType()},
{reflect.TypeOf(NRecurseA{}), RecurseAType()},
{reflect.TypeOf(NRecurseB{}), RecurseBType()},
}
func testUintType() *Type {
switch bitlen := 8 * unsafe.Sizeof(uint(0)); bitlen {
case 32:
return Uint32Type
case 64:
return Uint64Type
default:
panic(fmt.Errorf("testUintType unhandled bitlen %d", bitlen))
}
}
func testUintptrType() *Type {
switch bitlen := 8 * unsafe.Sizeof(uintptr(0)); bitlen {
case 32:
return Uint32Type
case 64:
return Uint64Type
default:
panic(fmt.Errorf("testUintptrType unhandled bitlen %d", bitlen))
}
}
func testIntType() *Type {
switch bitlen := 8 * unsafe.Sizeof(int(0)); bitlen {
case 32:
return Int32Type
case 64:
return Int64Type
default:
panic(fmt.Errorf("testIntType unhandled bitlen %d", bitlen))
}
}
func allTests() []rtTest {
// Start with all keys and non keys
tests := make([]rtTest, len(rtKeyTests)+len(rtNonKeyTests))
n := copy(tests, rtKeyTests)
copy(tests[n:], rtNonKeyTests)
// Add all types we can generate via reflect.
for _, test := range rtKeyTests {
if test.t.CanBeOptional() {
tests = append(tests, rtTest{reflect.PtrTo(test.rt), OptionalType(test.t)})
} else {
tests = append(tests, rtTest{reflect.PtrTo(test.rt), test.t})
}
tests = append(tests, rtTest{reflect.SliceOf(test.rt), ListType(test.t)})
tests = append(tests, rtTest{reflect.MapOf(test.rt, test.rt), MapType(test.t, test.t)})
}
// Now generate types from everything we have so far, for more complicated subtypes.
for _, test := range tests {
if test.rt == nil {
continue
}
if test.t.CanBeOptional() {
tests = append(tests, rtTest{reflect.PtrTo(test.rt), OptionalType(test.t)})
} else {
tests = append(tests, rtTest{reflect.PtrTo(test.rt), test.t})
}
tests = append(tests, rtTest{reflect.SliceOf(test.rt), ListType(test.t)})
for _, key := range rtKeyTests {
// Only generate maps with valid keys.
tests = append(tests, rtTest{reflect.MapOf(key.rt, reflect.SliceOf(test.rt)), MapType(key.t, ListType(test.t))})
}
}
return tests
}
func TestTypeFromReflect(t *testing.T) {
// Make sure we can create all types without the cache.
rtCacheEnabled = false
testTypeFromReflect(t, "no cache")
// Enable the cache, and make multiple goroutines update the same types
// concurrently. This should expose locking issues in the cache.
rtCacheEnabled = true
var done sync.WaitGroup
for i := 0; i < 3; i++ {
done.Add(1)
go func(i int) {
testTypeFromReflect(t, fmt.Sprintf("cache%d", i))
done.Done()
}(i)
}
done.Wait()
// Final test with all types already cached.
testTypeFromReflect(t, "all cached")
}
func testTypeFromReflect(t *testing.T, prefix string) {
for _, test := range allTests() {
got, err := TypeFromReflect(test.rt)
ExpectErr(t, err, "", "%s TypeFromReflect(%v)", prefix, test.rt)
if want := test.t; got != want {
t.Errorf("%s TypeFromReflect(%v) got type %v, want %v", prefix, test.rt, got, want)
}
// Make sure that the type is automatically registered, if it is named.
if test.rt != nil && test.t.Name() != "" {
if rt := TypeToReflect(test.t); rt == nil {
t.Errorf("%s TypeFromReflect(%v) got TypeToReflect nil, want non-nil", prefix, test.rt)
}
}
}
}
var rtErrorTests = []rtErrorTest{
{reflect.TypeOf(make(chan int64)), `type "chan int64" not supported`},
{reflect.TypeOf(func() {}), `type "func()" not supported`},
{reflect.TypeOf(unsafe.Pointer(nil)), `type "unsafe.Pointer" not supported`},
{reflect.TypeOf(map[*int64]string{}), `invalid key "*int64" in "map[*int64]string"`},
{reflect.TypeOf(struct{ a int64 }{}), `type "struct { a int64 }" only has unexported fields`},
}
func rtErrorTestsAll() []rtErrorTest {
// Start with base error tests
tests := make([]rtErrorTest, len(rtErrorTests))
copy(tests, rtErrorTests)
tests = append(tests, reflectInfoErrorTests...)
// Add some types we can generate via reflect
for _, test := range tests {
if test.rt != nil {
tests = append(tests, rtErrorTest{reflect.PtrTo(test.rt), test.errstr})
tests = append(tests, rtErrorTest{reflect.SliceOf(test.rt), test.errstr})
}
}
// Now generate types from everything we have so far, for more complicated subtypes.
for _, test := range tests {
if test.rt != nil {
tests = append(tests, rtErrorTest{reflect.PtrTo(reflect.PtrTo(test.rt)), test.errstr})
tests = append(tests, rtErrorTest{reflect.SliceOf(reflect.SliceOf(test.rt)), test.errstr})
}
}
return tests
}
func TestTypeFromReflectError(t *testing.T) {
for _, test := range rtErrorTestsAll() {
got, err := TypeFromReflect(test.rt)
ExpectErr(t, err, test.errstr, "TypeFromReflect(%v)", test.rt)
if got != nil {
t.Errorf("TypeFromReflect(%v) got type %v, want nil", test.rt, got)
}
}
}
type simpleNamedType struct {
X int16
}
// BenchmarkRepeatedVdlTypeOf determines the time for a repeated
// vdl.TypeOf, i.e. skipping the initial vdl.Type of that builds
// the type.
func BenchmarkRepeatedVdlTypeOf(b *testing.B) {
val := &simpleNamedType{}
TypeOf(val)
for i := 0; i < b.N; i++ {
TypeOf(val)
}
}
// BenchmarkRepeatedReflectTypeOf is the reflect analog of
// BenchmarkRepeatedVdlTypeOf, for comparison purposes.
func BenchmarkRepeatedReflectTypeOf(b *testing.B) {
reflect.TypeOf(&simpleNamedType{})
for i := 0; i < b.N; i++ {
reflect.TypeOf(&simpleNamedType{})
}
}