blob: 2f9ce35972860cb023ea9f2157e85617ae37860f [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 opconst
// TODO(toddw): Merge with vdl/testutil_test.go.
import (
"fmt"
"strings"
"testing"
"v.io/v23/vdl"
)
// CallAndRecover calls the function f and returns the result of recover().
// This minimizes the scope of the deferred recover, to ensure f is actually the
// function that paniced.
func CallAndRecover(f func()) (result interface{}) {
defer func() {
result = recover()
}()
f()
return
}
func expectErr(t *testing.T, err error, wantstr string, format string, args ...interface{}) bool {
gotstr := fmt.Sprint(err)
msg := fmt.Sprintf(format, args...)
if wantstr != "" && !strings.Contains(gotstr, wantstr) {
t.Errorf(`%s got error %q, want substr %q`, msg, gotstr, wantstr)
return false
}
if wantstr == "" && err != nil {
t.Errorf(`%s got error %q, want nil`, msg, gotstr)
return false
}
return true
}
func expectPanic(t *testing.T, f func(), wantstr string, format string, args ...interface{}) {
got := CallAndRecover(f)
gotstr := fmt.Sprint(got)
msg := fmt.Sprintf(format, args...)
if wantstr != "" && !strings.Contains(gotstr, wantstr) {
t.Errorf(`%s got panic %q, want substr %q`, msg, gotstr, wantstr)
}
if wantstr == "" && got != nil {
t.Errorf(`%s got panic %q, want nil`, msg, gotstr)
}
}
func expectMismatchedKind(t *testing.T, f func()) {
expectPanic(t, f, "mismatched kind", "")
}
// Define a bunch of regular Go types used in tests.
type (
// Scalars
nInterface interface{}
nType *vdl.Type
nBool bool
nUint8 uint8
nUint16 uint16
nUint32 uint32
nUint64 uint64
nUint uint
nUintptr uintptr
nInt8 int8
nInt16 int16
nInt32 int32
nInt64 int64
nInt int
nFloat32 float32
nFloat64 float64
nString string
// Arrays
nArray3Interface [3]nInterface
nArray3TypeObject [3]*vdl.Type
nArray3Bool [3]bool
nArray3Uint8 [3]uint8
nArray3Uint16 [3]uint16
nArray3Uint32 [3]uint32
nArray3Uint64 [3]uint64
nArray3Uint [3]uint
nArray3Uintptr [3]uintptr
nArray3Int8 [3]int8
nArray3Int16 [3]int16
nArray3Int32 [3]int32
nArray3Int64 [3]int64
nArray3Int [3]int
nArray3Float32 [3]float32
nArray3Float64 [3]float64
nArray3String [3]string
// Structs
nStructInterface struct{ X nInterface }
nStructTypeObject struct{ X *vdl.Type }
nStructBool struct{ X bool }
nStructUint8 struct{ X uint8 }
nStructUint16 struct{ X uint16 }
nStructUint32 struct{ X uint32 }
nStructUint64 struct{ X uint64 }
nStructUint struct{ X uint }
nStructUintptr struct{ X uintptr }
nStructInt8 struct{ X int8 }
nStructInt16 struct{ X int16 }
nStructInt32 struct{ X int32 }
nStructInt64 struct{ X int64 }
nStructInt struct{ X int }
nStructFloat32 struct{ X float32 }
nStructFloat64 struct{ X float64 }
nStructString struct{ X string }
// Slices
nSliceInterface []nInterface
nSliceTypeObject []*vdl.Type
nSliceBool []bool
nSliceUint8 []uint8
nSliceUint16 []uint16
nSliceUint32 []uint32
nSliceUint64 []uint64
nSliceUint []uint
nSliceUintptr []uintptr
nSliceInt8 []int8
nSliceInt16 []int16
nSliceInt32 []int32
nSliceInt64 []int64
nSliceInt []int
nSliceFloat32 []float32
nSliceFloat64 []float64
nSliceString []string
// Sets
nSetInterface map[nInterface]struct{}
nSetTypeObject map[*vdl.Type]struct{}
nSetBool map[bool]struct{}
nSetUint8 map[uint8]struct{}
nSetUint16 map[uint16]struct{}
nSetUint32 map[uint32]struct{}
nSetUint64 map[uint64]struct{}
nSetUint map[uint]struct{}
nSetUintptr map[uintptr]struct{}
nSetInt8 map[int8]struct{}
nSetInt16 map[int16]struct{}
nSetInt32 map[int32]struct{}
nSetInt64 map[int64]struct{}
nSetInt map[int]struct{}
nSetFloat32 map[float32]struct{}
nSetFloat64 map[float64]struct{}
nSetString map[string]struct{}
// Maps
nMapInterface map[nInterface]nInterface
nMapTypeObject map[*vdl.Type]*vdl.Type
nMapBool map[bool]bool
nMapUint8 map[uint8]uint8
nMapUint16 map[uint16]uint16
nMapUint32 map[uint32]uint32
nMapUint64 map[uint64]uint64
nMapUint map[uint]uint
nMapUintptr map[uintptr]uintptr
nMapInt8 map[int8]int8
nMapInt16 map[int16]int16
nMapInt32 map[int32]int32
nMapInt64 map[int64]int64
nMapInt map[int]int
nMapFloat32 map[float32]float32
nMapFloat64 map[float64]float64
nMapString map[string]string
// Recursive types
nRecurseSelf struct{ X []nRecurseSelf }
nRecurseA struct{ B []nRecurseB }
nRecurseB struct{ A []nRecurseA }
// Composite types representing sets of numbers.
nMapUint64Empty map[nUint64]struct{}
nMapInt64Empty map[nUint64]struct{}
nMapFloat64Empty map[nUint64]struct{}
nMapUint64Bool map[nUint64]nBool
nMapInt64Bool map[nInt64]nBool
nMapFloat64Bool map[nFloat64]nBool
// Composite types representing sets of strings.
nMapStringEmpty map[nString]struct{}
nMapStringBool map[nString]nBool
nStructXYZBool struct{ X, Y, Z nBool }
nStructWXBool struct{ W, X nBool }
// Composite types representing maps of strings to numbers.
nMapStringUint64 map[nString]nUint64
nMapStringInt64 map[nString]nInt64
nMapStringFloat64 map[nString]nFloat64
nStructVWXUint64 struct{ V, W, X nUint64 }
nStructVWXInt64 struct{ V, W, X nInt64 }
nStructVWXFloat64 struct{ V, W, X nFloat64 }
nStructUVUint64 struct{ U, V nUint64 }
nStructUVInt64 struct{ U, V nInt64 }
nStructUVFloat64 struct{ U, V nFloat64 }
// Types that cannot be converted to sets. We represent sets as
// map[key]struct{} on the Go side, but don't allow map[key]nEmpty.
nEmpty struct{}
nMapStringnEmpty map[nString]nEmpty
nStructXYZEmpty struct{ X, Y, Z struct{} }
nStructXYZnEmpty struct{ X, Y, Z nEmpty }
)
func recurseSelfType() *vdl.Type {
var builder vdl.TypeBuilder
n := builder.Named("v.io/v23/vdl.nRecurseSelf")
n.AssignBase(builder.Struct().AppendField("X", builder.List().AssignElem(n)))
builder.Build()
t, err := n.Built()
if err != nil {
panic(err)
}
return t
}
func recurseABTypes() [2]*vdl.Type {
var builder vdl.TypeBuilder
a := builder.Named("v.io/v23/vdl.nRecurseA")
b := builder.Named("v.io/v23/vdl.nRecurseB")
a.AssignBase(builder.Struct().AppendField("B", builder.List().AssignElem(b)))
b.AssignBase(builder.Struct().AppendField("A", builder.List().AssignElem(a)))
builder.Build()
aT, err := a.Built()
if err != nil {
panic(err)
}
bT, err := b.Built()
if err != nil {
panic(err)
}
return [2]*vdl.Type{aT, bT}
}
func recurseAType() *vdl.Type { return recurseABTypes()[0] }
func recurseBType() *vdl.Type { return recurseABTypes()[1] }
// Define a bunch of *Type types used in tests.
var (
// Named scalar types
boolTypeN = vdl.NamedType("nBool", vdl.BoolType)
nByteType = vdl.NamedType("nByte", vdl.ByteType)
uint16TypeN = vdl.NamedType("nUint16", vdl.Uint16Type)
uint32TypeN = vdl.NamedType("nUint32", vdl.Uint32Type)
uint64TypeN = vdl.NamedType("nUint64", vdl.Uint64Type)
int16TypeN = vdl.NamedType("nInt16", vdl.Int16Type)
int32TypeN = vdl.NamedType("nInt32", vdl.Int32Type)
int64TypeN = vdl.NamedType("nInt64", vdl.Int64Type)
float32TypeN = vdl.NamedType("nFloat32", vdl.Float32Type)
float64TypeN = vdl.NamedType("nFloat64", vdl.Float64Type)
stringTypeN = vdl.NamedType("nString", vdl.StringType)
// Composite types representing strings and bytes.
bytesType = vdl.ListType(vdl.ByteType)
bytesTypeN = vdl.NamedType("nBytes", bytesType)
bytes3Type = vdl.ArrayType(3, vdl.ByteType)
bytes3TypeN = vdl.NamedType("nBytes3", bytes3Type)
// Composite types representing sequences of numbers.
array3Uint64Type = vdl.ArrayType(3, vdl.Uint64Type)
array3Uint64TypeN = vdl.NamedType("nArray3Uint64", vdl.ArrayType(3, uint64TypeN))
array3Int64Type = vdl.ArrayType(3, vdl.Int64Type)
array3Int64TypeN = vdl.NamedType("nArray3Int64", vdl.ArrayType(3, int64TypeN))
array3Float64Type = vdl.ArrayType(3, vdl.Float64Type)
array3Float64TypeN = vdl.NamedType("nArray3Float64", vdl.ArrayType(3, float64TypeN))
listUint64Type = vdl.ListType(vdl.Uint64Type)
listUint64TypeN = vdl.NamedType("nListUint64", vdl.ListType(uint64TypeN))
listInt64Type = vdl.ListType(vdl.Int64Type)
listInt64TypeN = vdl.NamedType("nListInt64", vdl.ListType(int64TypeN))
listFloat64Type = vdl.ListType(vdl.Float64Type)
listFloat64TypeN = vdl.NamedType("nListFloat64", vdl.ListType(float64TypeN))
// Composite types representing sets of numbers.
setUint64Type = vdl.SetType(vdl.Uint64Type)
setUint64TypeN = vdl.NamedType("nSetUint64", vdl.SetType(uint64TypeN))
setInt64Type = vdl.SetType(vdl.Int64Type)
setInt64TypeN = vdl.NamedType("nSetInt64", vdl.SetType(int64TypeN))
setFloat64Type = vdl.SetType(vdl.Float64Type)
setFloat64TypeN = vdl.NamedType("nSetFloat64", vdl.SetType(float64TypeN))
mapUint64BoolType = vdl.MapType(vdl.Uint64Type, vdl.BoolType)
mapUint64BoolTypeN = vdl.NamedType("nMapUint64Bool", vdl.MapType(uint64TypeN, boolTypeN))
mapInt64BoolType = vdl.MapType(vdl.Int64Type, vdl.BoolType)
mapInt64BoolTypeN = vdl.NamedType("nMapInt64Bool", vdl.MapType(int64TypeN, boolTypeN))
mapFloat64BoolType = vdl.MapType(vdl.Float64Type, vdl.BoolType)
mapFloat64BoolTypeN = vdl.NamedType("nMapFloat64Bool", vdl.MapType(float64TypeN, boolTypeN))
// Composite types representing sets of strings.
setStringType = vdl.SetType(vdl.StringType)
setStringTypeN = vdl.NamedType("nSetString", vdl.SetType(stringTypeN))
mapStringBoolType = vdl.MapType(vdl.StringType, vdl.BoolType)
mapStringBoolTypeN = vdl.NamedType("nMapStringBool", vdl.MapType(stringTypeN, boolTypeN))
structXYZBoolType = vdl.StructType(vdl.Field{Name: "X", Type: vdl.BoolType}, vdl.Field{Name: "Y", Type: vdl.BoolType}, vdl.Field{Name: "Z", Type: vdl.BoolType})
structXYZBoolTypeN = vdl.NamedType("nStructXYZBool", vdl.StructType(vdl.Field{Name: "X", Type: boolTypeN}, vdl.Field{Name: "Y", Type: boolTypeN}, vdl.Field{Name: "Z", Type: boolTypeN}))
structWXBoolType = vdl.StructType(vdl.Field{Name: "W", Type: vdl.BoolType}, vdl.Field{Name: "X", Type: vdl.BoolType})
structWXBoolTypeN = vdl.NamedType("nStructWXBool", vdl.StructType(vdl.Field{Name: "W", Type: boolTypeN}, vdl.Field{Name: "X", Type: boolTypeN}))
// Composite types representing maps of strings to numbers.
mapStringUint64Type = vdl.MapType(vdl.StringType, vdl.Uint64Type)
mapStringUint64TypeN = vdl.NamedType("nMapStringUint64", vdl.MapType(stringTypeN, uint64TypeN))
mapStringInt64Type = vdl.MapType(vdl.StringType, vdl.Int64Type)
mapStringInt64TypeN = vdl.NamedType("nMapStringInt64", vdl.MapType(stringTypeN, int64TypeN))
mapStringFloat64Type = vdl.MapType(vdl.StringType, vdl.Float64Type)
mapStringFloat64TypeN = vdl.NamedType("nMapStringFloat64", vdl.MapType(stringTypeN, float64TypeN))
structVWXUint64Type = vdl.StructType(vdl.Field{Name: "V", Type: vdl.Uint64Type}, vdl.Field{Name: "W", Type: vdl.Uint64Type}, vdl.Field{Name: "X", Type: vdl.Uint64Type})
structVWXUint64TypeN = vdl.NamedType("nStructVWXUint64", vdl.StructType(vdl.Field{Name: "V", Type: uint64TypeN}, vdl.Field{Name: "W", Type: uint64TypeN}, vdl.Field{Name: "X", Type: uint64TypeN}))
structVWXInt64Type = vdl.StructType(vdl.Field{Name: "V", Type: vdl.Int64Type}, vdl.Field{Name: "W", Type: vdl.Int64Type}, vdl.Field{Name: "X", Type: vdl.Int64Type})
structVWXInt64TypeN = vdl.NamedType("nStructVWXInt64", vdl.StructType(vdl.Field{Name: "V", Type: int64TypeN}, vdl.Field{Name: "W", Type: int64TypeN}, vdl.Field{Name: "X", Type: int64TypeN}))
structVWXFloat64Type = vdl.StructType(vdl.Field{Name: "V", Type: vdl.Float64Type}, vdl.Field{Name: "W", Type: vdl.Float64Type}, vdl.Field{Name: "X", Type: vdl.Float64Type})
structVWXFloat64TypeN = vdl.NamedType("nStructVWXFloat64", vdl.StructType(vdl.Field{Name: "V", Type: float64TypeN}, vdl.Field{Name: "W", Type: float64TypeN}, vdl.Field{Name: "X", Type: float64TypeN}))
structUVUint64Type = vdl.StructType(vdl.Field{Name: "U", Type: vdl.Uint64Type}, vdl.Field{Name: "V", Type: vdl.Uint64Type})
structUVUint64TypeN = vdl.NamedType("nStructUVUint64", vdl.StructType(vdl.Field{Name: "U", Type: uint64TypeN}, vdl.Field{Name: "V", Type: uint64TypeN}))
structUVInt64Type = vdl.StructType(vdl.Field{Name: "U", Type: vdl.Int64Type}, vdl.Field{Name: "V", Type: vdl.Int64Type})
structUVInt64TypeN = vdl.NamedType("nStructUVInt64", vdl.StructType(vdl.Field{Name: "U", Type: int64TypeN}, vdl.Field{Name: "V", Type: int64TypeN}))
structUVFloat64Type = vdl.StructType(vdl.Field{Name: "U", Type: vdl.Float64Type}, vdl.Field{Name: "V", Type: vdl.Float64Type})
structUVFloat64TypeN = vdl.NamedType("nStructUVFloat64", vdl.StructType(vdl.Field{Name: "U", Type: float64TypeN}, vdl.Field{Name: "V", Type: float64TypeN}))
structAIntType = vdl.StructType(vdl.Field{Name: "A", Type: vdl.Int64Type})
structAIntTypeN = vdl.NamedType("nStructA", structAIntType)
// Types that cannot be converted to sets. Although we represent sets as
// map[key]struct{} on the Go side, we don't allow these as general
// conversions for val.Value.
emptyType = vdl.StructType()
emptyTypeN = vdl.NamedType("nEmpty", vdl.StructType())
mapStringEmptyType = vdl.MapType(vdl.StringType, emptyType)
mapStringEmptyTypeN = vdl.NamedType("nMapStringEmpty", vdl.MapType(stringTypeN, emptyTypeN))
structXYZEmptyType = vdl.StructType(vdl.Field{Name: "X", Type: emptyType}, vdl.Field{Name: "Y", Type: emptyType}, vdl.Field{Name: "Z", Type: emptyType})
structXYZEmptyTypeN = vdl.NamedType("nStructXYZEmpty", vdl.StructType(vdl.Field{Name: "X", Type: emptyTypeN}, vdl.Field{Name: "Y", Type: emptyTypeN}, vdl.Field{Name: "Z", Type: emptyTypeN}))
)
func setStringValue(t *vdl.Type, x ...string) *vdl.Value {
res := vdl.ZeroValue(t)
for _, vx := range x {
key := vdl.StringValue(t.Key(), vx)
res.AssignSetKey(key)
}
return res
}
type sb struct {
s string
b bool
}
func mapStringBoolValue(t *vdl.Type, x ...sb) *vdl.Value {
res := vdl.ZeroValue(t)
for _, sb := range x {
key := vdl.StringValue(t.Key(), sb.s)
val := vdl.BoolValue(t.Elem(), sb.b)
res.AssignMapIndex(key, val)
}
return res
}
func mapStringEmptyValue(t *vdl.Type, x ...string) *vdl.Value {
res := vdl.ZeroValue(t)
for _, vx := range x {
key := vdl.StringValue(t.Key(), vx)
val := vdl.ZeroValue(t.Elem())
res.AssignMapIndex(key, val)
}
return res
}
func structBoolValue(t *vdl.Type, x ...sb) *vdl.Value {
res := vdl.ZeroValue(t)
for _, sb := range x {
_, index := t.FieldByName(sb.s)
res.StructField(index).AssignBool(sb.b)
}
return res
}
func assignNum(v *vdl.Value, num float64) *vdl.Value {
switch v.Kind() {
case vdl.Byte, vdl.Uint16, vdl.Uint32, vdl.Uint64:
v.AssignUint(uint64(num))
case vdl.Int8, vdl.Int16, vdl.Int32, vdl.Int64:
v.AssignInt(int64(num))
case vdl.Float32, vdl.Float64:
v.AssignFloat(num)
default:
panic(fmt.Errorf("val: assignNum unhandled %v", v.Type()))
}
return v
}
func seqNumValue(t *vdl.Type, x ...float64) *vdl.Value {
res := vdl.ZeroValue(t)
if t.Kind() == vdl.List {
res.AssignLen(len(x))
}
for index, n := range x {
assignNum(res.Index(index), n)
}
return res
}
func setNumValue(t *vdl.Type, x ...float64) *vdl.Value {
res := vdl.ZeroValue(t)
for _, n := range x {
res.AssignSetKey(assignNum(vdl.ZeroValue(t.Key()), n))
}
return res
}
type nb struct {
n float64
b bool
}
func mapNumBoolValue(t *vdl.Type, x ...nb) *vdl.Value {
res := vdl.ZeroValue(t)
for _, nb := range x {
key := assignNum(vdl.ZeroValue(t.Key()), nb.n)
val := vdl.BoolValue(t.Elem(), nb.b)
res.AssignMapIndex(key, val)
}
return res
}
type sn struct {
s string
n float64
}
func mapStringNumValue(t *vdl.Type, x ...sn) *vdl.Value {
res := vdl.ZeroValue(t)
for _, sn := range x {
key := vdl.StringValue(t.Key(), sn.s)
val := assignNum(vdl.ZeroValue(t.Elem()), sn.n)
res.AssignMapIndex(key, val)
}
return res
}
func structNumValue(t *vdl.Type, x ...sn) *vdl.Value {
res := vdl.ZeroValue(t)
for _, sn := range x {
_, index := t.FieldByName(sn.s)
assignNum(res.StructField(index), sn.n)
}
return res
}