| // 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_test |
| |
| // This test is in the vdl_test package to avoid a cyclic dependency with the |
| // "v.io/v23/verror" package. We need to import the verror package in |
| // order to test error conversions. |
| // |
| // TODO(toddw): test values of recursive types. |
| |
| import ( |
| "fmt" |
| "math" |
| "reflect" |
| "testing" |
| |
| "v.io/v23/vdl" |
| "v.io/v23/vdl/vdltest" |
| "v.io/v23/verror" |
| ) |
| |
| func errorValue(e verror.E) *vdl.Value { |
| verr := vdl.NonNilZeroValue(vdl.ErrorType) |
| vv := verr.Elem() |
| vv.StructField(0).AssignString(string(e.ID)) |
| vv.StructField(1).AssignEnumLabel(retryFromAction(e.Action)) |
| vv.StructField(2).AssignString(e.Msg) |
| vv.StructField(3).AssignLen(len(e.ParamList)) |
| for ix, p := range e.ParamList { |
| vv.StructField(3).Index(ix).Assign(vdl.ValueOf(p)) |
| } |
| return verr |
| } |
| |
| func retryFromAction(action verror.ActionCode) string { |
| switch action.RetryAction() { |
| case verror.NoRetry: |
| return vdl.WireRetryCodeNoRetry.String() |
| case verror.RetryConnection: |
| return vdl.WireRetryCodeRetryConnection.String() |
| case verror.RetryRefetch: |
| return vdl.WireRetryCodeRetryRefetch.String() |
| case verror.RetryBackoff: |
| return vdl.WireRetryCodeRetryBackoff.String() |
| } |
| // Default to NoRetry. |
| return vdl.WireRetryCodeNoRetry.String() |
| } |
| |
| // Each group of values in vvNAME and rvNAME are all mutually convertible. |
| var ( |
| rvError1 = verror.E{ |
| ID: verror.ID("id1"), |
| Action: verror.NoRetry, |
| Msg: "msg1", |
| ParamList: nil, |
| } |
| rvError2 = verror.E{ |
| ID: verror.ID("id2"), |
| Action: verror.RetryConnection, |
| Msg: "msg2", |
| ParamList: []interface{}{"abc", int32(123)}, |
| } |
| rvError3 = verror.E{ |
| ID: verror.ID("id3"), |
| Action: verror.RetryBackoff, |
| Msg: "msg3", |
| ParamList: []interface{}{rvError1, &rvError2}, |
| } |
| |
| vvBoolTrue = []*vdl.Value{ |
| vdl.BoolValue(nil, true), vdl.BoolValue(vdl.BoolTypeN, true), |
| } |
| vvStrABC = []*vdl.Value{ |
| vdl.StringValue(nil, "ABC"), vdl.StringValue(vdl.StringTypeN, "ABC"), |
| vdl.EnumValue(vdl.EnumTypeN, 3), |
| } |
| vvTypeObjectBool = []*vdl.Value{ |
| vdl.TypeObjectValue(vdl.BoolType), |
| } |
| vvSeq123 = []*vdl.Value{ |
| vdl.SeqNumValue(vdl.Array3ByteType, 1, 2, 3), |
| vdl.SeqNumValue(vdl.Array3ByteTypeN, 1, 2, 3), |
| vdl.SeqNumValue(vdl.Array3Uint64Type, 1, 2, 3), |
| vdl.SeqNumValue(vdl.Array3Uint64TypeN, 1, 2, 3), |
| vdl.SeqNumValue(vdl.Array3Int64Type, 1, 2, 3), |
| vdl.SeqNumValue(vdl.Array3Int64TypeN, 1, 2, 3), |
| vdl.SeqNumValue(vdl.Array3Float64Type, 1, 2, 3), |
| vdl.SeqNumValue(vdl.Array3Float64TypeN, 1, 2, 3), |
| vdl.SeqNumValue(vdl.ListByteType, 1, 2, 3), |
| vdl.SeqNumValue(vdl.ListByteTypeN, 1, 2, 3), |
| vdl.SeqNumValue(vdl.ListUint64Type, 1, 2, 3), |
| vdl.SeqNumValue(vdl.ListUint64TypeN, 1, 2, 3), |
| vdl.SeqNumValue(vdl.ListInt64Type, 1, 2, 3), |
| vdl.SeqNumValue(vdl.ListInt64TypeN, 1, 2, 3), |
| vdl.SeqNumValue(vdl.ListFloat64Type, 1, 2, 3), |
| vdl.SeqNumValue(vdl.ListFloat64TypeN, 1, 2, 3), |
| } |
| vvSet123 = []*vdl.Value{ |
| vdl.SetNumValue(vdl.SetByteType, 1, 2, 3), |
| vdl.SetNumValue(vdl.SetByteTypeN, 1, 2, 3), |
| vdl.SetNumValue(vdl.SetUint64Type, 1, 2, 3), |
| vdl.SetNumValue(vdl.SetUint64TypeN, 1, 2, 3), |
| vdl.SetNumValue(vdl.SetInt64Type, 1, 2, 3), |
| vdl.SetNumValue(vdl.SetInt64TypeN, 1, 2, 3), |
| vdl.SetNumValue(vdl.SetFloat64Type, 1, 2, 3), |
| vdl.SetNumValue(vdl.SetFloat64TypeN, 1, 2, 3), |
| } |
| vvMap123True = []*vdl.Value{ |
| vdl.MapNumBoolValue(vdl.MapByteBoolType, vdl.NB{1, true}, vdl.NB{2, true}, vdl.NB{3, true}), |
| vdl.MapNumBoolValue(vdl.MapByteBoolTypeN, vdl.NB{1, true}, vdl.NB{2, true}, vdl.NB{3, true}), |
| vdl.MapNumBoolValue(vdl.MapUint64BoolType, vdl.NB{1, true}, vdl.NB{2, true}, vdl.NB{3, true}), |
| vdl.MapNumBoolValue(vdl.MapUint64BoolTypeN, vdl.NB{1, true}, vdl.NB{2, true}, vdl.NB{3, true}), |
| vdl.MapNumBoolValue(vdl.MapInt64BoolType, vdl.NB{1, true}, vdl.NB{2, true}, vdl.NB{3, true}), |
| vdl.MapNumBoolValue(vdl.MapInt64BoolTypeN, vdl.NB{1, true}, vdl.NB{2, true}, vdl.NB{3, true}), |
| vdl.MapNumBoolValue(vdl.MapFloat64BoolType, vdl.NB{1, true}, vdl.NB{2, true}, vdl.NB{3, true}), |
| vdl.MapNumBoolValue(vdl.MapFloat64BoolTypeN, vdl.NB{1, true}, vdl.NB{2, true}, vdl.NB{3, true}), |
| } |
| vvMap123FalseTrue = []*vdl.Value{ |
| vdl.MapNumBoolValue(vdl.MapByteBoolType, vdl.NB{1, false}, vdl.NB{2, true}, vdl.NB{3, false}), |
| vdl.MapNumBoolValue(vdl.MapByteBoolTypeN, vdl.NB{1, false}, vdl.NB{2, true}, vdl.NB{3, false}), |
| vdl.MapNumBoolValue(vdl.MapUint64BoolType, vdl.NB{1, false}, vdl.NB{2, true}, vdl.NB{3, false}), |
| vdl.MapNumBoolValue(vdl.MapUint64BoolTypeN, vdl.NB{1, false}, vdl.NB{2, true}, vdl.NB{3, false}), |
| vdl.MapNumBoolValue(vdl.MapInt64BoolType, vdl.NB{1, false}, vdl.NB{2, true}, vdl.NB{3, false}), |
| vdl.MapNumBoolValue(vdl.MapInt64BoolTypeN, vdl.NB{1, false}, vdl.NB{2, true}, vdl.NB{3, false}), |
| vdl.MapNumBoolValue(vdl.MapFloat64BoolType, vdl.NB{1, false}, vdl.NB{2, true}, vdl.NB{3, false}), |
| vdl.MapNumBoolValue(vdl.MapFloat64BoolTypeN, vdl.NB{1, false}, vdl.NB{2, true}, vdl.NB{3, false}), |
| } |
| vvSetXYZ = []*vdl.Value{ |
| vdl.SetStringValue(vdl.SetStringType, "X", "Y", "Z"), |
| vdl.SetStringValue(vdl.SetStringTypeN, "X", "Y", "Z"), |
| } |
| vvMapXYZTrue = []*vdl.Value{ |
| vdl.MapStringBoolValue(vdl.MapStringBoolType, vdl.SB{"X", true}, vdl.SB{"Y", true}, vdl.SB{"Z", true}), |
| vdl.MapStringBoolValue(vdl.MapStringBoolTypeN, vdl.SB{"X", true}, vdl.SB{"Y", true}, vdl.SB{"Z", true}), |
| } |
| vvStructXYZTrue = []*vdl.Value{ |
| vdl.StructBoolValue(vdl.StructXYZBoolType, vdl.SB{"X", true}, vdl.SB{"Y", true}, vdl.SB{"Z", true}), |
| vdl.StructBoolValue(vdl.StructXYZBoolTypeN, vdl.SB{"X", true}, vdl.SB{"Y", true}, vdl.SB{"Z", true}), |
| } |
| vvMapXYZFalseTrue = []*vdl.Value{ |
| vdl.MapStringBoolValue(vdl.MapStringBoolType, vdl.SB{"X", false}, vdl.SB{"Y", true}, vdl.SB{"Z", false}), |
| vdl.MapStringBoolValue(vdl.MapStringBoolTypeN, vdl.SB{"X", false}, vdl.SB{"Y", true}, vdl.SB{"Z", false}), |
| } |
| vvMapStructXYZEmpty = []*vdl.Value{ |
| vdl.MapStringEmptyValue(vdl.MapStringEmptyType, "X", "Y", "Z"), |
| vdl.MapStringEmptyValue(vdl.MapStringEmptyTypeN, "X", "Y", "Z"), |
| vdl.ZeroValue(vdl.StructXYZEmptyType), vdl.ZeroValue(vdl.StructXYZEmptyTypeN), |
| } |
| vvStructWXFalseTrue = []*vdl.Value{ |
| vdl.StructBoolValue(vdl.StructWXBoolType, vdl.SB{"W", false}, vdl.SB{"X", true}), |
| vdl.StructBoolValue(vdl.StructWXBoolTypeN, vdl.SB{"W", false}, vdl.SB{"X", true}), |
| } |
| vvMapVWX123 = []*vdl.Value{ |
| vdl.MapStringNumValue(vdl.MapStringByteType, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| vdl.MapStringNumValue(vdl.MapStringByteTypeN, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| vdl.MapStringNumValue(vdl.MapStringUint64Type, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| vdl.MapStringNumValue(vdl.MapStringUint64TypeN, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| vdl.MapStringNumValue(vdl.MapStringInt64Type, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| vdl.MapStringNumValue(vdl.MapStringInt64TypeN, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| vdl.MapStringNumValue(vdl.MapStringFloat64Type, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| vdl.MapStringNumValue(vdl.MapStringFloat64TypeN, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| } |
| vvStructVWX123 = []*vdl.Value{ |
| vdl.StructNumValue(vdl.StructVWXByteType, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| vdl.StructNumValue(vdl.StructVWXByteTypeN, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| vdl.StructNumValue(vdl.StructVWXUint64Type, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| vdl.StructNumValue(vdl.StructVWXUint64TypeN, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| vdl.StructNumValue(vdl.StructVWXInt64Type, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| vdl.StructNumValue(vdl.StructVWXInt64TypeN, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| vdl.StructNumValue(vdl.StructVWXFloat64Type, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| vdl.StructNumValue(vdl.StructVWXFloat64TypeN, vdl.SN{"V", 1}, vdl.SN{"W", 2}, vdl.SN{"X", 3}), |
| } |
| vvStructUV01 = []*vdl.Value{ |
| vdl.StructNumValue(vdl.StructUVByteType, vdl.SN{"U", 0}, vdl.SN{"V", 1}), |
| vdl.StructNumValue(vdl.StructUVByteTypeN, vdl.SN{"U", 0}, vdl.SN{"V", 1}), |
| vdl.StructNumValue(vdl.StructUVUint64Type, vdl.SN{"U", 0}, vdl.SN{"V", 1}), |
| vdl.StructNumValue(vdl.StructUVUint64TypeN, vdl.SN{"U", 0}, vdl.SN{"V", 1}), |
| vdl.StructNumValue(vdl.StructUVInt64Type, vdl.SN{"U", 0}, vdl.SN{"V", 1}), |
| vdl.StructNumValue(vdl.StructUVInt64TypeN, vdl.SN{"U", 0}, vdl.SN{"V", 1}), |
| vdl.StructNumValue(vdl.StructUVFloat64Type, vdl.SN{"U", 0}, vdl.SN{"V", 1}), |
| vdl.StructNumValue(vdl.StructUVFloat64TypeN, vdl.SN{"U", 0}, vdl.SN{"V", 1}), |
| } |
| |
| rvBoolTrue = []interface{}{ |
| bool(true), vdl.NBool(true), |
| } |
| rvStrABC = []interface{}{ |
| string("ABC"), vdl.NString("ABC"), vdl.NEnumABC, |
| } |
| rvTypeObjectBool = []interface{}{ |
| vdl.BoolType, |
| } |
| rvSeq123 = []interface{}{ |
| [3]byte{1, 2, 3}, []byte{1, 2, 3}, vdl.NArray3Byte{1, 2, 3}, vdl.NSliceByte{1, 2, 3}, |
| [3]uint64{1, 2, 3}, []uint64{1, 2, 3}, vdl.NArray3Uint64{1, 2, 3}, vdl.NSliceUint64{1, 2, 3}, |
| [3]int64{1, 2, 3}, []int64{1, 2, 3}, vdl.NArray3Int64{1, 2, 3}, vdl.NSliceInt64{1, 2, 3}, |
| [3]float64{1, 2, 3}, []float64{1, 2, 3}, vdl.NArray3Float64{1, 2, 3}, vdl.NSliceFloat64{1, 2, 3}, |
| } |
| rvSet123 = []interface{}{ |
| map[byte]struct{}{1: struct{}{}, 2: struct{}{}, 3: struct{}{}}, |
| map[uint64]struct{}{1: struct{}{}, 2: struct{}{}, 3: struct{}{}}, |
| map[int64]struct{}{1: struct{}{}, 2: struct{}{}, 3: struct{}{}}, |
| map[float64]struct{}{1: struct{}{}, 2: struct{}{}, 3: struct{}{}}, |
| vdl.NMapByteEmpty{1: struct{}{}, 2: struct{}{}, 3: struct{}{}}, |
| vdl.NMapUint64Empty{1: struct{}{}, 2: struct{}{}, 3: struct{}{}}, |
| vdl.NMapInt64Empty{1: struct{}{}, 2: struct{}{}, 3: struct{}{}}, |
| vdl.NMapFloat64Empty{1: struct{}{}, 2: struct{}{}, 3: struct{}{}}, |
| } |
| rvMap123True = []interface{}{ |
| map[byte]bool{1: true, 2: true, 3: true}, |
| map[uint64]bool{1: true, 2: true, 3: true}, |
| map[int64]bool{1: true, 2: true, 3: true}, |
| map[float64]bool{1: true, 2: true, 3: true}, |
| vdl.NMapByteBool{1: true, 2: true, 3: true}, |
| vdl.NMapUint64Bool{1: true, 2: true, 3: true}, |
| vdl.NMapInt64Bool{1: true, 2: true, 3: true}, |
| vdl.NMapFloat64Bool{1: true, 2: true, 3: true}, |
| } |
| rvMap123FalseTrue = []interface{}{ |
| map[byte]bool{1: false, 2: true, 3: false}, |
| map[uint64]bool{1: false, 2: true, 3: false}, |
| map[int64]bool{1: false, 2: true, 3: false}, |
| map[float64]bool{1: false, 2: true, 3: false}, |
| vdl.NMapByteBool{1: false, 2: true, 3: false}, |
| vdl.NMapUint64Bool{1: false, 2: true, 3: false}, |
| vdl.NMapInt64Bool{1: false, 2: true, 3: false}, |
| vdl.NMapFloat64Bool{1: false, 2: true, 3: false}, |
| } |
| rvSetXYZ = []interface{}{ |
| map[string]struct{}{"X": struct{}{}, "Y": struct{}{}, "Z": struct{}{}}, |
| vdl.NMapStringEmpty{"X": struct{}{}, "Y": struct{}{}, "Z": struct{}{}}, |
| } |
| rvMapXYZTrue = []interface{}{ |
| map[string]bool{"X": true, "Y": true, "Z": true}, |
| vdl.NMapStringBool{"X": true, "Y": true, "Z": true}, |
| } |
| rvStructXYZTrue = []interface{}{ |
| struct{ X, Y, Z bool }{X: true, Y: true, Z: true}, |
| struct{ a, X, b, Y, c, Z, d bool }{X: true, Y: true, Z: true}, |
| vdl.NStructXYZBool{X: true, Y: true, Z: true}, |
| vdl.NStructXYZBoolUnexported{X: true, Y: true, Z: true}, |
| } |
| rvMapXYZFalseTrue = []interface{}{ |
| map[string]bool{"X": false, "Y": true, "Z": false}, |
| vdl.NMapStringBool{"X": false, "Y": true, "Z": false}, |
| } |
| rvStructXYZEmpty = []interface{}{ |
| vdl.NStructXYZEmpty{}, vdl.NStructXYZNEmpty{}, |
| } |
| rvMapXYZEmpty = []interface{}{ |
| map[string]vdl.NEmpty{"X": vdl.NEmpty{}, "Y": vdl.NEmpty{}, "Z": vdl.NEmpty{}}, |
| vdl.NMapStringNEmpty{"X": vdl.NEmpty{}, "Y": vdl.NEmpty{}, "Z": vdl.NEmpty{}}, |
| } |
| rvStructWXFalseTrue = []interface{}{ |
| struct{ W, X bool }{W: false, X: true}, |
| vdl.NStructWXBool{W: false, X: true}, |
| } |
| rvMapVWX123 = []interface{}{ |
| map[string]byte{"V": 1, "W": 2, "X": 3}, |
| map[string]uint64{"V": 1, "W": 2, "X": 3}, |
| map[string]int64{"V": 1, "W": 2, "X": 3}, |
| map[string]float64{"V": 1, "W": 2, "X": 3}, |
| vdl.NMapStringByte{"V": 1, "W": 2, "X": 3}, |
| vdl.NMapStringUint64{"V": 1, "W": 2, "X": 3}, |
| vdl.NMapStringInt64{"V": 1, "W": 2, "X": 3}, |
| vdl.NMapStringFloat64{"V": 1, "W": 2, "X": 3}, |
| } |
| rvStructVWX123 = []interface{}{ |
| struct{ V, W, X byte }{V: 1, W: 2, X: 3}, |
| struct{ V, W, X uint64 }{V: 1, W: 2, X: 3}, |
| struct{ V, W, X int64 }{V: 1, W: 2, X: 3}, |
| struct{ V, W, X float64 }{V: 1, W: 2, X: 3}, |
| struct { |
| // Interleave unexported fields, which are ignored. |
| a bool |
| V int64 |
| b string |
| W float64 |
| X float32 |
| c []byte |
| d interface{} |
| }{V: 1, W: 2, X: 3}, |
| vdl.NStructVWXByte{V: 1, W: 2, X: 3}, |
| vdl.NStructVWXUint64{V: 1, W: 2, X: 3}, |
| vdl.NStructVWXInt64{V: 1, W: 2, X: 3}, |
| vdl.NStructVWXFloat64{V: 1, W: 2, X: 3}, |
| vdl.NStructVWXMixed{V: 1, W: 2, X: 3}, |
| } |
| rvStructUV01 = []interface{}{ |
| struct{ U, V byte }{U: 0, V: 1}, |
| struct{ U, V uint64 }{U: 0, V: 1}, |
| struct{ U, V int64 }{U: 0, V: 1}, |
| struct{ U, V float64 }{U: 0, V: 1}, |
| struct { |
| // Interleave unexported fields, which are ignored. |
| a bool |
| U int64 |
| b string |
| V float64 |
| c []byte |
| }{U: 0, V: 1}, |
| vdl.NStructUVByte{U: 0, V: 1}, |
| vdl.NStructUVUint64{U: 0, V: 1}, |
| vdl.NStructUVInt64{U: 0, V: 1}, |
| vdl.NStructUVFloat64{U: 0, V: 1}, |
| vdl.NStructUVMixed{U: 0, V: 1}, |
| } |
| rvEmptyStruct = []interface{}{struct{}{}, vdl.NEmpty{}} |
| |
| ttBools = ttTypes(vvBoolTrue) |
| ttStrs = ttTypes(vvStrABC) |
| ttTypeObjects = ttTypes(vvTypeObjectBool) |
| ttSeq123 = ttTypes(vvSeq123) |
| ttSet123 = ttTypes(vvSet123) |
| ttMap123 = ttTypes(vvMap123True) |
| ttSetXYZ = ttTypes(vvSetXYZ) |
| ttMapXYZBool = ttTypes(vvMapXYZTrue) |
| ttStructXYZBool = ttTypes(vvStructXYZTrue) |
| ttStructWXBool = ttTypes(vvStructWXFalseTrue) |
| ttMapVWXNum = ttTypes(vvMapVWX123) |
| ttStructVWXNum = ttTypes(vvStructVWX123) |
| ttStructUVNum = ttTypes(vvStructUV01) |
| ttUints = []*vdl.Type{ |
| vdl.ByteType, vdl.ByteTypeN, |
| vdl.Uint16Type, vdl.Uint16TypeN, |
| vdl.Uint32Type, vdl.Uint32TypeN, |
| vdl.Uint64Type, vdl.Uint64TypeN, |
| } |
| ttInts = []*vdl.Type{ |
| vdl.Int8Type, vdl.Int8TypeN, |
| vdl.Int16Type, vdl.Int16TypeN, |
| vdl.Int32Type, vdl.Int32TypeN, |
| vdl.Int64Type, vdl.Int64TypeN, |
| } |
| ttFloat32s = []*vdl.Type{vdl.Float32Type, vdl.Float32TypeN} |
| ttFloat64s = []*vdl.Type{vdl.Float64Type, vdl.Float64TypeN} |
| ttFloats = ttJoin(ttFloat32s, ttFloat64s) |
| ttIntegers = ttJoin(ttUints, ttInts) |
| ttNumbers = ttJoin(ttIntegers, ttFloats) |
| ttAllTypes = ttJoin(ttBools, ttStrs, ttTypeObjects, ttNumbers, ttSeq123, ttSet123, ttMap123, ttSetXYZ, ttMapXYZBool, ttStructXYZBool, ttMapVWXNum, ttStructVWXNum) |
| |
| rtBools = rtTypes(rvBoolTrue) |
| rtStrs = rtTypes(rvStrABC) |
| rtTypeObjects = rtTypes(rvTypeObjectBool) |
| rtSeq123 = rtTypes(rvSeq123) |
| rtSet123 = rtTypes(rvSet123) |
| rtMap123 = rtTypes(rvMap123True) |
| rtSetXYZ = rtTypes(rvSetXYZ) |
| rtMapXYZBool = rtTypes(rvMapXYZTrue) |
| rtStructXYZBool = rtTypes(rvStructXYZTrue) |
| rtStructWXBool = rtTypes(rvStructWXFalseTrue) |
| rtMapVWXNum = rtTypes(rvMapVWX123) |
| rtStructVWXNum = rtTypes(rvStructVWX123) |
| rtStructUVNum = rtTypes(rvStructUV01) |
| rtUints = []reflect.Type{ |
| reflect.TypeOf(byte(0)), reflect.TypeOf(vdl.NByte(0)), |
| reflect.TypeOf(uint16(0)), reflect.TypeOf(vdl.NUint16(0)), |
| reflect.TypeOf(uint32(0)), reflect.TypeOf(vdl.NUint32(0)), |
| reflect.TypeOf(uint64(0)), reflect.TypeOf(vdl.NUint64(0)), |
| } |
| rtInts = []reflect.Type{ |
| reflect.TypeOf(int8(0)), reflect.TypeOf(vdl.NInt8(0)), |
| reflect.TypeOf(int16(0)), reflect.TypeOf(vdl.NInt16(0)), |
| reflect.TypeOf(int32(0)), reflect.TypeOf(vdl.NInt32(0)), |
| reflect.TypeOf(int64(0)), reflect.TypeOf(vdl.NInt64(0)), |
| } |
| rtFloat32s = []reflect.Type{ |
| reflect.TypeOf(float32(0)), reflect.TypeOf(vdl.NFloat32(0)), |
| } |
| rtFloat64s = []reflect.Type{ |
| reflect.TypeOf(float64(0)), reflect.TypeOf(vdl.NFloat64(0)), |
| } |
| rtFloats = rtJoin(rtFloat32s, rtFloat64s) |
| rtIntegers = rtJoin(rtUints, rtInts) |
| rtNumbers = rtJoin(rtIntegers, rtFloats) |
| rtAllTypes = rtJoin(rtBools, rtStrs, rtTypeObjects, rtNumbers, rtSeq123, rtSet123, rtMap123, rtSetXYZ, rtMapXYZBool, rtStructXYZBool, rtMapVWXNum, rtStructVWXNum) |
| |
| rtInterface = reflect.TypeOf((*interface{})(nil)).Elem() |
| rtPtrToType = reflect.TypeOf((*vdl.Type)(nil)) |
| ) |
| |
| // Helpers to manipulate slices of *Type |
| func ttSetToSlice(set map[*vdl.Type]bool) (result []*vdl.Type) { |
| for tt, _ := range set { |
| result = append(result, tt) |
| } |
| return |
| } |
| func ttTypes(values []*vdl.Value) []*vdl.Type { |
| uniq := make(map[*vdl.Type]bool) |
| for _, v := range values { |
| uniq[v.Type()] = true |
| } |
| return ttSetToSlice(uniq) |
| } |
| func ttJoin(types ...[]*vdl.Type) []*vdl.Type { |
| uniq := make(map[*vdl.Type]bool) |
| for _, ttSlice := range types { |
| for _, tt := range ttSlice { |
| uniq[tt] = true |
| } |
| } |
| return ttSetToSlice(uniq) |
| } |
| |
| // ttOtherThan returns all types from types that aren't represented in other. |
| func ttOtherThan(types []*vdl.Type, other ...[]*vdl.Type) (result []*vdl.Type) { |
| otherMap := make(map[*vdl.Type]bool) |
| for _, oo := range other { |
| for _, o := range oo { |
| otherMap[o] = true |
| } |
| } |
| for _, t := range types { |
| if !otherMap[t] { |
| result = append(result, t) |
| } |
| } |
| return |
| } |
| |
| // Helpers to manipulate slices of reflect.Type |
| func rtSetToSlice(set map[reflect.Type]bool) (result []reflect.Type) { |
| for rt, _ := range set { |
| result = append(result, rt) |
| } |
| return |
| } |
| func rtTypes(values []interface{}) []reflect.Type { |
| uniq := make(map[reflect.Type]bool) |
| for _, v := range values { |
| uniq[reflect.TypeOf(v)] = true |
| } |
| return rtSetToSlice(uniq) |
| } |
| func rtJoin(types ...[]reflect.Type) (result []reflect.Type) { |
| uniq := make(map[reflect.Type]bool) |
| for _, rtSlice := range types { |
| for _, rt := range rtSlice { |
| uniq[rt] = true |
| } |
| } |
| return rtSetToSlice(uniq) |
| } |
| |
| // rtOtherThan returns all types from types that aren't represented in other. |
| func rtOtherThan(types []reflect.Type, other ...[]reflect.Type) (result []reflect.Type) { |
| otherMap := make(map[reflect.Type]bool) |
| for _, oo := range other { |
| for _, o := range oo { |
| otherMap[o] = true |
| } |
| } |
| for _, t := range types { |
| if !otherMap[t] { |
| result = append(result, t) |
| } |
| } |
| return |
| } |
| |
| // vvOnlyFrom returns all values from values that are represented in from. |
| func vvOnlyFrom(values []*vdl.Value, from []*vdl.Type) (result []*vdl.Value) { |
| fromMap := make(map[*vdl.Type]bool) |
| for _, f := range from { |
| fromMap[f] = true |
| } |
| for _, v := range values { |
| if fromMap[v.Type()] { |
| result = append(result, v) |
| } |
| } |
| return |
| } |
| |
| // rvOnlyFrom returns all values from values that are represented in from. |
| func rvOnlyFrom(values []interface{}, from []reflect.Type) (result []interface{}) { |
| fromMap := make(map[reflect.Type]bool) |
| for _, f := range from { |
| fromMap[f] = true |
| } |
| for _, v := range values { |
| if fromMap[reflect.TypeOf(v)] { |
| result = append(result, v) |
| } |
| } |
| return |
| } |
| |
| // vvFromUint returns all *Values that can represent u without loss of precision. |
| func vvFromUint(u uint64) (result []*vdl.Value) { |
| i, f := int64(u), float64(u) |
| switch { |
| case u <= math.MaxInt8: |
| result = append(result, |
| vdl.IntValue(vdl.Int8Type, i), |
| vdl.IntValue(vdl.Int8TypeN, i)) |
| fallthrough |
| case u <= math.MaxUint8: |
| result = append(result, |
| vdl.UintValue(vdl.ByteType, u), |
| vdl.UintValue(vdl.ByteTypeN, u)) |
| fallthrough |
| case u <= math.MaxInt16: |
| result = append(result, |
| vdl.IntValue(vdl.Int16Type, i), |
| vdl.IntValue(vdl.Int16TypeN, i)) |
| fallthrough |
| case u <= math.MaxUint16: |
| result = append(result, |
| vdl.UintValue(vdl.Uint16Type, u), |
| vdl.UintValue(vdl.Uint16TypeN, u)) |
| fallthrough |
| case u <= 1<<24: |
| result = append(result, |
| vdl.FloatValue(vdl.Float32Type, f), |
| vdl.FloatValue(vdl.Float32TypeN, f)) |
| fallthrough |
| case u <= math.MaxInt32: |
| result = append(result, |
| vdl.IntValue(vdl.Int32Type, i), |
| vdl.IntValue(vdl.Int32TypeN, i)) |
| fallthrough |
| case u <= math.MaxUint32: |
| result = append(result, |
| vdl.UintValue(vdl.Uint32Type, u), |
| vdl.UintValue(vdl.Uint32TypeN, u)) |
| fallthrough |
| case u <= 1<<53: |
| result = append(result, |
| vdl.FloatValue(vdl.Float64Type, f), |
| vdl.FloatValue(vdl.Float64TypeN, f)) |
| fallthrough |
| case u <= math.MaxInt64: |
| result = append(result, |
| vdl.IntValue(vdl.Int64Type, i), |
| vdl.IntValue(vdl.Int64TypeN, i)) |
| fallthrough |
| default: |
| result = append(result, |
| vdl.UintValue(vdl.Uint64Type, u), |
| vdl.UintValue(vdl.Uint64TypeN, u)) |
| } |
| return result |
| } |
| |
| // rvFromUint returns all values that can represent u without loss of precision. |
| func rvFromUint(u uint64) (result []interface{}) { |
| switch { |
| case u <= math.MaxInt8: |
| result = append(result, int8(u), vdl.NInt8(u)) |
| fallthrough |
| case u <= math.MaxUint8: |
| result = append(result, byte(u), vdl.NByte(u)) |
| fallthrough |
| case u <= math.MaxInt16: |
| result = append(result, int16(u), vdl.NInt16(u)) |
| fallthrough |
| case u <= math.MaxUint16: |
| result = append(result, uint16(u), vdl.NUint16(u)) |
| fallthrough |
| case u <= 1<<24: |
| result = append(result, float32(u), vdl.NFloat32(u)) |
| fallthrough |
| case u <= math.MaxInt32: |
| result = append(result, int32(u), vdl.NInt32(u)) |
| fallthrough |
| case u <= math.MaxUint32: |
| result = append(result, uint32(u), vdl.NUint32(u)) |
| fallthrough |
| case u <= 1<<53: |
| result = append(result, float64(u), vdl.NFloat64(u)) |
| fallthrough |
| case u <= math.MaxInt64: |
| result = append(result, int64(u), vdl.NInt64(u)) |
| fallthrough |
| default: |
| result = append(result, uint64(u), vdl.NUint64(u)) |
| } |
| return result |
| } |
| |
| // vvFromInt returns all *Values that can represent i without loss of precision. |
| func vvFromInt(i int64) (result []*vdl.Value) { |
| u, f := uint64(i), float64(i) |
| switch { |
| case math.MinInt8 <= i && i <= math.MaxInt8: |
| result = append(result, |
| vdl.IntValue(vdl.Int8Type, i), |
| vdl.IntValue(vdl.Int8TypeN, i)) |
| fallthrough |
| case math.MinInt16 <= i && i <= math.MaxInt16: |
| result = append(result, |
| vdl.IntValue(vdl.Int16Type, i), |
| vdl.IntValue(vdl.Int16TypeN, i)) |
| fallthrough |
| case -1<<24 <= i && i <= 1<<24: |
| result = append(result, |
| vdl.FloatValue(vdl.Float32Type, f), |
| vdl.FloatValue(vdl.Float32TypeN, f)) |
| fallthrough |
| case math.MinInt32 <= i && i <= math.MaxInt32: |
| result = append(result, |
| vdl.IntValue(vdl.Int32Type, i), |
| vdl.IntValue(vdl.Int32TypeN, i)) |
| fallthrough |
| case -1<<53 <= i && i <= 1<<53: |
| result = append(result, |
| vdl.FloatValue(vdl.Float64Type, f), |
| vdl.FloatValue(vdl.Float64TypeN, f)) |
| fallthrough |
| default: |
| result = append(result, |
| vdl.IntValue(vdl.Int64Type, i), |
| vdl.IntValue(vdl.Int64TypeN, i)) |
| } |
| if i < 0 { |
| return |
| } |
| switch { |
| case i <= math.MaxUint8: |
| result = append(result, |
| vdl.UintValue(vdl.ByteType, u), |
| vdl.UintValue(vdl.ByteTypeN, u)) |
| fallthrough |
| case i <= math.MaxUint16: |
| result = append(result, |
| vdl.UintValue(vdl.Uint16Type, u), |
| vdl.UintValue(vdl.Uint16TypeN, u)) |
| fallthrough |
| case i <= math.MaxUint32: |
| result = append(result, |
| vdl.UintValue(vdl.Uint32Type, u), |
| vdl.UintValue(vdl.Uint32TypeN, u)) |
| fallthrough |
| default: |
| result = append(result, |
| vdl.UintValue(vdl.Uint64Type, u), |
| vdl.UintValue(vdl.Uint64TypeN, u)) |
| } |
| return |
| } |
| |
| // rvFromInt returns all values that can represent i without loss of precision. |
| func rvFromInt(i int64) (result []interface{}) { |
| switch { |
| case math.MinInt8 <= i && i <= math.MaxInt8: |
| result = append(result, int8(i), vdl.NInt8(i)) |
| fallthrough |
| case math.MinInt16 <= i && i <= math.MaxInt16: |
| result = append(result, int16(i), vdl.NInt16(i)) |
| fallthrough |
| case -1<<24 <= i && i <= 1<<24: |
| result = append(result, float32(i), vdl.NFloat32(i)) |
| fallthrough |
| case math.MinInt32 <= i && i <= math.MaxInt32: |
| result = append(result, int32(i), vdl.NInt32(i)) |
| fallthrough |
| case -1<<53 <= i && i <= 1<<53: |
| result = append(result, float64(i), vdl.NFloat64(i)) |
| fallthrough |
| default: |
| result = append(result, int64(i), vdl.NInt64(i)) |
| } |
| if i < 0 { |
| return |
| } |
| switch { |
| case i <= math.MaxUint8: |
| result = append(result, byte(i), vdl.NByte(i)) |
| fallthrough |
| case i <= math.MaxUint16: |
| result = append(result, uint16(i), vdl.NUint16(i)) |
| fallthrough |
| case i <= math.MaxUint32: |
| result = append(result, uint32(i), vdl.NUint32(i)) |
| fallthrough |
| default: |
| result = append(result, uint64(i), vdl.NUint64(i)) |
| } |
| return |
| } |
| |
| func vvFloat(f float64) []*vdl.Value { |
| return []*vdl.Value{ |
| vdl.FloatValue(vdl.Float32Type, f), |
| vdl.FloatValue(vdl.Float32TypeN, f), |
| vdl.FloatValue(vdl.Float64Type, f), |
| vdl.FloatValue(vdl.Float64TypeN, f), |
| } |
| } |
| |
| func rvFloat(f float64) []interface{} { |
| return []interface{}{ |
| float32(f), vdl.NFloat32(f), |
| float64(f), vdl.NFloat64(f), |
| } |
| } |
| |
| // Test successful conversions. Each test contains a set of values and |
| // interfaces that are all equivalent and convertible to each other. |
| func TestConverter(t *testing.T) { |
| tests := []struct { |
| vv []*vdl.Value |
| rv []interface{} |
| }{ |
| // TODO(bprosnitz) Convert needs to be switched to the new reader for this to work. |
| // There is currently a bug where Convert will incorrectly return "error" typed value |
| // when "?error" is correct. |
| /*{[]*vdl.Value{vvError1}, []interface{}{rvError1}}, |
| {[]*vdl.Value{vvError2}, []interface{}{rvError2}}, |
| {[]*vdl.Value{vvError3}, []interface{}{rvError3}},*/ |
| {vvBoolTrue, rvBoolTrue}, |
| {vvStrABC, rvStrABC}, |
| {vvFromUint(math.MaxUint8), rvFromUint(math.MaxUint8)}, |
| {vvFromUint(math.MaxUint16), rvFromUint(math.MaxUint16)}, |
| {vvFromUint(math.MaxUint32), rvFromUint(math.MaxUint32)}, |
| {vvFromUint(math.MaxUint64), rvFromUint(math.MaxUint64)}, |
| {vvFromInt(math.MaxInt8), rvFromInt(math.MaxInt8)}, |
| {vvFromInt(math.MaxInt16), rvFromInt(math.MaxInt16)}, |
| {vvFromInt(math.MaxInt32), rvFromInt(math.MaxInt32)}, |
| {vvFromInt(math.MaxInt64), rvFromInt(math.MaxInt64)}, |
| {vvFromInt(math.MinInt8), rvFromInt(math.MinInt8)}, |
| {vvFromInt(math.MinInt16), rvFromInt(math.MinInt16)}, |
| {vvFromInt(math.MinInt32), rvFromInt(math.MinInt32)}, |
| {vvFromInt(math.MinInt64), rvFromInt(math.MinInt64)}, |
| {vvFromInt(vdl.Float32MaxInt), rvFromInt(vdl.Float32MaxInt)}, |
| {vvFromInt(vdl.Float64MaxInt), rvFromInt(vdl.Float64MaxInt)}, |
| {vvFromInt(vdl.Float32MinInt), rvFromInt(vdl.Float32MinInt)}, |
| {vvFromInt(vdl.Float64MinInt), rvFromInt(vdl.Float64MinInt)}, |
| {vvTypeObjectBool, rvTypeObjectBool}, |
| {vvSeq123, rvSeq123}, |
| {vvSet123, rvSet123}, |
| {vvMap123True, rvMap123True}, |
| {vvSetXYZ, rvSetXYZ}, |
| {vvMapXYZTrue, rvMapXYZTrue}, |
| {vvStructXYZTrue, rvStructXYZTrue}, |
| {vvMapVWX123, rvMapVWX123}, |
| {vvStructVWX123, rvStructVWX123}, |
| {vvStructUV01, rvStructUV01}, |
| {nil, []interface{}{vdl.NNative(0)}}, |
| {nil, []interface{}{vdl.NNative(1)}}, |
| {nil, []interface{}{vdl.NNative(-(1 << 63))}}, |
| {nil, []interface{}{vdl.NNative((1 << 63) - 1)}}, |
| {nil, []interface{}{vdl.NUnionNative("A=false")}}, |
| {nil, []interface{}{vdl.NUnionNative("A=true")}}, |
| {nil, []interface{}{vdl.NUnionNative("B=123")}}, |
| {nil, []interface{}{vdl.NUnionNative("B=-123")}}, |
| } |
| for _, test := range tests { |
| testConverterWantSrc(t, vvrv{test.vv, test.rv}, vvrv{test.vv, test.rv}) |
| } |
| } |
| |
| // Test successful conversions that drop and ignore fields in the dst struct. |
| func TestConverterStructDropIgnore(t *testing.T) { |
| tests := []struct { |
| vvWant []*vdl.Value |
| rvWant []interface{} |
| vvSrc []*vdl.Value |
| rvSrc []interface{} |
| }{ |
| {vvStructWXFalseTrue, rvStructWXFalseTrue, vvStructXYZTrue, rvStructXYZTrue}, |
| {vvStructUV01, rvStructUV01, vvStructVWX123, rvStructVWX123}, |
| } |
| for _, test := range tests { |
| testConverterWantSrc(t, vvrv{test.vvWant, test.rvWant}, vvrv{test.vvSrc, test.rvSrc}) |
| } |
| } |
| |
| // Test successful conversions to and from union values. |
| func TestConverterUnion(t *testing.T) { |
| // values for union component types |
| vvTrue := vdl.BoolValue(nil, true) |
| vv123 := vdl.IntValue(vdl.Int64Type, 123) |
| vvAbc := vdl.StringValue(nil, "Abc") |
| vvStruct123 := vdl.ZeroValue(vdl.StructInt64TypeN) |
| vvStruct123.StructField(0).Assign(vv123) |
| rvTrue := bool(true) |
| rv123 := int64(123) |
| rvAbc := string("Abc") |
| rvStruct123 := vdl.NStructInt64{123} |
| // values for union{A bool;B string;C struct} |
| vvTrueABC := vdl.UnionValue(vdl.UnionABCTypeN, 0, vvTrue) |
| vvAbcABC := vdl.UnionValue(vdl.UnionABCTypeN, 1, vvAbc) |
| vvStruct123ABC := vdl.UnionValue(vdl.UnionABCTypeN, 2, vvStruct123) |
| rvTrueABC := vdl.NUnionABCA{rvTrue} |
| rvAbcABC := vdl.NUnionABCB{rvAbc} |
| rvStruct123ABC := vdl.NUnionABCC{rvStruct123} |
| rvTrueABCi := vdl.NUnionABC(rvTrueABC) |
| rvAbcABCi := vdl.NUnionABC(rvAbcABC) |
| rvStruct123ABCi := vdl.NUnionABC(rvStruct123ABC) |
| // values for union{B string;C struct;D int64} |
| vvAbcBCD := vdl.UnionValue(vdl.UnionBCDTypeN, 0, vvAbc) |
| vvStruct123BCD := vdl.UnionValue(vdl.UnionBCDTypeN, 1, vvStruct123) |
| vv123BCD := vdl.UnionValue(vdl.UnionBCDTypeN, 2, vv123) |
| rvAbcBCD := vdl.NUnionBCDB{rvAbc} |
| rvStruct123BCD := vdl.NUnionBCDC{rvStruct123} |
| rv123BCD := vdl.NUnionBCDD{rv123} |
| rvAbcBCDi := vdl.NUnionBCD(rvAbcBCD) |
| rvStruct123BCDi := vdl.NUnionBCD(rvStruct123BCD) |
| rv123BCDi := vdl.NUnionBCD(rv123BCD) |
| // values for union{X string;Y struct}, which has no Go equivalent. |
| vvAbcXY := vdl.UnionValue(vdl.UnionXYTypeN, 0, vvAbc) |
| vvStruct123XY := vdl.UnionValue(vdl.UnionXYTypeN, 1, vvStruct123) |
| |
| tests := []struct { |
| vvWant *vdl.Value |
| rvWant interface{} |
| vvSrc *vdl.Value |
| rvSrc interface{} |
| }{ |
| // Convert source and target same union. |
| {vvTrueABC, rvTrueABC, vvTrueABC, rvTrueABC}, |
| {vv123BCD, rv123BCD, vv123BCD, rv123BCD}, |
| {vvAbcABC, rvAbcABC, vvAbcABC, rvAbcABC}, |
| {vvAbcBCD, rvAbcBCD, vvAbcBCD, rvAbcBCD}, |
| {vvStruct123ABC, rvStruct123ABC, vvStruct123ABC, rvStruct123ABC}, |
| {vvStruct123BCD, rvStruct123BCD, vvStruct123BCD, rvStruct123BCD}, |
| // Same thing, but with pointers to the interface type. |
| {vvTrueABC, &rvTrueABCi, vvTrueABC, &rvTrueABCi}, |
| {vv123BCD, &rv123BCDi, vv123BCD, &rv123BCD}, |
| {vvAbcABC, &rvAbcABCi, vvAbcABC, &rvAbcABC}, |
| {vvAbcBCD, &rvAbcBCDi, vvAbcBCD, &rvAbcBCD}, |
| {vvStruct123ABC, &rvStruct123ABCi, vvStruct123ABC, &rvStruct123ABCi}, |
| {vvStruct123BCD, &rvStruct123BCDi, vvStruct123BCD, &rvStruct123BCDi}, |
| |
| // Convert source and target different union. |
| {vvAbcABC, rvAbcABC, vvAbcBCD, rvAbcBCD}, |
| {vvAbcBCD, rvAbcBCD, vvAbcABC, rvAbcABC}, |
| {vvStruct123ABC, rvStruct123ABC, vvStruct123BCD, rvStruct123BCD}, |
| {vvStruct123BCD, rvStruct123BCD, vvStruct123ABC, rvStruct123ABC}, |
| // Same thing, but with pointers to the interface type. |
| {vvAbcABC, &rvAbcABCi, vvAbcBCD, &rvAbcBCDi}, |
| {vvAbcBCD, &rvAbcBCDi, vvAbcABC, &rvAbcABCi}, |
| {vvStruct123ABC, &rvStruct123ABCi, vvStruct123BCD, &rvStruct123BCDi}, |
| {vvStruct123BCD, &rvStruct123BCDi, vvStruct123ABC, &rvStruct123ABCi}, |
| |
| // Test unions that have no Go equivalent. |
| {vvAbcXY, nil, vvAbcXY, nil}, |
| {vvStruct123XY, nil, vvStruct123XY, nil}, |
| } |
| for _, test := range tests { |
| testConverterWantSrc(t, |
| vvrv{vvSlice(test.vvWant), rvSlice(test.rvWant)}, |
| vvrv{vvSlice(test.vvSrc), rvSlice(test.rvSrc)}) |
| } |
| } |
| |
| func vvSlice(v *vdl.Value) []*vdl.Value { |
| if v != nil { |
| return []*vdl.Value{v} |
| } |
| return nil |
| } |
| |
| func rvSlice(v interface{}) []interface{} { |
| if v != nil { |
| return []interface{}{v} |
| } |
| return nil |
| } |
| |
| // Test successful conversions to and from nil values. |
| func TestConverterNil(t *testing.T) { |
| vvNil := vdl.ZeroValue(vdl.AnyType) |
| rvNil := new(interface{}) |
| vvNilError := vdl.ZeroValue(vdl.ErrorType) |
| rvNilError := new(error) |
| vvNilPtrStruct := vdl.ZeroValue(vdl.TypeOf((*vdl.NStructInt)(nil))) |
| rvNilPtrStruct := (*vdl.NStructInt)(nil) |
| vvStructNilStructField := vdl.ZeroValue(vdl.TypeOf(vdl.NStructOptionalStruct{})) |
| rvStructNilStructField := vdl.NStructOptionalStruct{X: nil} |
| vvStructNilAnyField := vdl.ZeroValue(vdl.TypeOf(vdl.NStructOptionalAny{})) |
| rvStructNilAnyField := vdl.NStructOptionalAny{X: nil} |
| tests := []struct { |
| vvWant *vdl.Value |
| rvWant interface{} |
| vvSrc *vdl.Value |
| rvSrc interface{} |
| }{ |
| // Conversion source and target are the same. |
| {vvNil, rvNil, vvNil, rvNil}, |
| {vvNilError, rvNilError, vvNilError, rvNilError}, |
| {vvNilPtrStruct, rvNilPtrStruct, vvNilPtrStruct, rvNilPtrStruct}, |
| {vvStructNilStructField, rvStructNilStructField, vvStructNilStructField, rvStructNilStructField}, |
| {vvStructNilAnyField, rvStructNilAnyField, vvStructNilAnyField, rvStructNilAnyField}, |
| // All typed nil targets may be converted from any(nil). |
| {vvNilError, rvNilError, vvNil, rvNil}, |
| {vvNilPtrStruct, rvNilPtrStruct, vvNil, rvNil}, |
| {vvStructNilStructField, rvStructNilStructField, vvStructNilAnyField, rvStructNilAnyField}, |
| } |
| for _, test := range tests { |
| testConverterWantSrc(t, |
| vvrv{[]*vdl.Value{test.vvWant}, []interface{}{test.rvWant}}, |
| vvrv{[]*vdl.Value{test.vvSrc}, []interface{}{test.rvSrc}}) |
| } |
| } |
| |
| type vvrv struct { |
| vv []*vdl.Value |
| rv []interface{} |
| } |
| |
| func testConverterWantSrc(t *testing.T, vvrvWant, vvrvSrc vvrv) { |
| // We run each testConvert helper twice; the first call tests filling in a |
| // zero dst, and the second call tests filling in a non-zero dst. |
| |
| // Tests of filling from *Value |
| for _, vvSrc := range vvrvSrc.vv { |
| for _, vvWant := range vvrvWant.vv { |
| // Test filling *Value from *Value |
| vvDst := vdl.ZeroValue(vvWant.Type()) |
| testConvert(t, "vv1", vvDst, vvSrc, vvWant, 0, false, "") |
| testConvert(t, "vv2", vvDst, vvSrc, vvWant, 0, false, "") |
| } |
| for _, want := range vvrvWant.rv { |
| // Test filling reflect.Value from *Value |
| dst := reflect.New(reflect.TypeOf(want)).Interface() |
| testConvert(t, "vv3", dst, vvSrc, want, 1, false, "") |
| testConvert(t, "vv4", dst, vvSrc, want, 1, false, "") |
| } |
| // Test filling Any from *Value |
| vvDst := vdl.ZeroValue(vdl.AnyType) |
| testConvert(t, "vv5", vvDst, vvSrc, vdl.ZeroValue(vdl.AnyType).Assign(vvSrc), 0, false, "") |
| testConvert(t, "vv6", vvDst, vvSrc, vdl.ZeroValue(vdl.AnyType).Assign(vvSrc), 0, false, "") |
| // Test filling Optional from *Value |
| if vvSrc.Type().CanBeOptional() { |
| ttNil := vdl.OptionalType(vvSrc.Type()) |
| vvNil := vdl.ZeroValue(ttNil) |
| vvOptWant := vdl.OptionalValue(vvSrc) |
| testConvert(t, "vv7", vvNil, vvSrc, vvOptWant, 0, false, "") |
| testConvert(t, "vv8", vvNil, vvSrc, vvOptWant, 0, false, "") |
| } |
| // Test filling **Value(nil) from *Value |
| var vvValue *vdl.Value |
| testConvert(t, "vv9", &vvValue, vvSrc, vvSrc, 1, false, "") |
| testConvert(t, "vv10", &vvValue, vvSrc, vvSrc, 1, false, "") |
| // Test filling interface{} from *Value |
| const useOldConverter = true |
| if !useOldConverter { |
| if !canCreateGoObject(vvSrc.Type()) { |
| // When an instance of a go object cannot be created, error. |
| var dst interface{} |
| testConvert(t, "vv11", &dst, vvSrc, vvSrc, 1, false, "not registered") |
| testConvert(t, "vv12", &dst, vvSrc, vvSrc, 1, false, "not registered") |
| } |
| } |
| if vvSrc.Kind() == vdl.Struct { |
| // Every struct may be converted to the empty struct |
| testConvert(t, "vv13", vdl.ZeroValue(vdl.EmptyType), vvSrc, vdl.ZeroValue(vdl.EmptyType), 0, false, "") |
| testConvert(t, "vv14", vdl.ZeroValue(vdl.EmptyTypeN), vvSrc, vdl.ZeroValue(vdl.EmptyTypeN), 0, false, "") |
| var empty struct{} |
| var emptyN vdl.NEmpty |
| testConvert(t, "vv15", &empty, vvSrc, struct{}{}, 1, false, "") |
| testConvert(t, "vv16", &emptyN, vvSrc, vdl.NEmpty{}, 1, false, "") |
| // The empty struct may be converted to the zero value of any struct |
| vvZeroSrc := vdl.ZeroValue(vvSrc.Type()) |
| testConvert(t, "vv17", vdl.ZeroValue(vvSrc.Type()), vdl.ZeroValue(vdl.EmptyType), vvZeroSrc, 0, false, "") |
| testConvert(t, "vv18", vdl.ZeroValue(vvSrc.Type()), vdl.ZeroValue(vdl.EmptyTypeN), vvZeroSrc, 0, false, "") |
| testConvert(t, "vv19", vdl.ZeroValue(vvSrc.Type()), struct{}{}, vvZeroSrc, 0, false, "") |
| testConvert(t, "vv20", vdl.ZeroValue(vvSrc.Type()), vdl.NEmpty{}, vvZeroSrc, 0, false, "") |
| } |
| } |
| |
| // Tests of filling from reflect.Value |
| for _, src := range vvrvSrc.rv { |
| rtSrc := reflect.TypeOf(src) |
| for _, vvWant := range vvrvWant.vv { |
| // Test filling *Value from reflect.Value |
| vvDst := vdl.ZeroValue(vvWant.Type()) |
| testConvert(t, "rv1", vvDst, src, vvWant, 0, false, "") |
| testConvert(t, "rv2", vvDst, src, vvWant, 0, false, "") |
| } |
| for _, want := range vvrvWant.rv { |
| // Test filling reflect.Value from reflect.Value |
| dst := reflect.New(reflect.TypeOf(want)).Interface() |
| testConvert(t, "rv3", dst, src, want, 1, false, "") |
| testConvert(t, "rv4", dst, src, want, 1, false, "") |
| } |
| vvWant := vdl.ValueOf(src) |
| // Test filling Any from reflect.Value |
| vvDst := vdl.ZeroValue(vdl.AnyType) |
| testConvert(t, "rv5", vvDst, src, vdl.ZeroValue(vdl.AnyType).Assign(vvWant), 0, true, "") |
| testConvert(t, "rv6", vvDst, src, vdl.ZeroValue(vdl.AnyType).Assign(vvWant), 0, true, "") |
| // Test filling **Value(nil) from reflect.Value |
| var vvValue *vdl.Value |
| testConvert(t, "rv7", &vvValue, src, vvWant, 1, false, "") |
| testConvert(t, "rv8", &vvValue, src, vvWant, 1, false, "") |
| // Test filling interface{} from reflect.Value |
| const useOldConverter = true |
| if !useOldConverter { |
| if !canCreateGoObject(vvWant.Type()) { |
| // When an instance of a go object cannot be created, error. |
| var dst interface{} |
| testConvert(t, "rv9", &dst, src, src, 1, false, "not registered") |
| testConvert(t, "rv10", &dst, src, src, 1, false, "not registered") |
| } |
| } |
| ttSrc, err := vdl.TypeFromReflect(rtSrc) |
| if err != nil { |
| t.Error(err) |
| continue |
| } |
| if rtSrc.Kind() == reflect.Struct && ttSrc.Kind() != vdl.Union { |
| // Every struct may be converted to the empty struct |
| testConvert(t, "rv11", vdl.ZeroValue(vdl.EmptyType), src, vdl.ZeroValue(vdl.EmptyType), 0, false, "") |
| testConvert(t, "rv12", vdl.ZeroValue(vdl.EmptyTypeN), src, vdl.ZeroValue(vdl.EmptyTypeN), 0, false, "") |
| var empty struct{} |
| var emptyN vdl.NEmpty |
| testConvert(t, "rv13", &empty, src, struct{}{}, 1, false, "") |
| testConvert(t, "rv14", &emptyN, src, vdl.NEmpty{}, 1, false, "") |
| // The empty struct may be converted to the zero value of any struct |
| rvZeroSrc := reflect.Zero(rtSrc).Interface() |
| testConvert(t, "rv15", reflect.New(rtSrc).Interface(), vdl.ZeroValue(vdl.EmptyType), rvZeroSrc, 1, false, "") |
| testConvert(t, "rv16", reflect.New(rtSrc).Interface(), vdl.ZeroValue(vdl.EmptyTypeN), rvZeroSrc, 1, false, "") |
| testConvert(t, "rv17", reflect.New(rtSrc).Interface(), struct{}{}, rvZeroSrc, 1, false, "") |
| testConvert(t, "rv18", reflect.New(rtSrc).Interface(), vdl.NEmpty{}, rvZeroSrc, 1, false, "") |
| } |
| } |
| } |
| |
| // canCreateGoObject returns true iff we can create a regular Go object from a |
| // value of type tt. We can create a real Go object if the Go type for tt has |
| // been registered, or if tt is the special-cased error type. |
| func canCreateGoObject(tt *vdl.Type) bool { |
| return tt == vdl.AnyType || vdl.TypeToReflect(tt) != nil || tt == vdl.ErrorType || tt == vdl.ErrorType.Elem() |
| } |
| |
| func testConvert(t *testing.T, prefix string, dst, src, want interface{}, deref int, optWant bool, expectedErr string) { |
| const ptrDepth = 3 |
| rvDst := reflect.ValueOf(dst) |
| for dstptrs := 0; dstptrs < ptrDepth; dstptrs++ { |
| rvSrc := reflect.ValueOf(src) |
| for srcptrs := 0; srcptrs < ptrDepth; srcptrs++ { |
| tname := fmt.Sprintf("%s Convert(%v, %v)", prefix, rvDst.Type(), rvSrc.Type()) |
| // This is tricky - if optWant is set, we might need to change the want |
| // value to become optional or non-optional. |
| eWant, rvWant, ttWant := want, reflect.ValueOf(want), vdl.TypeOf(want) |
| if optWant { |
| vvWant, wantIsVV := want.(*vdl.Value) |
| if srcptrs > 0 { |
| if wantIsVV { |
| switch { |
| case vvWant.Kind() == vdl.Any && !vvWant.IsNil() && vvWant.Elem().Type().CanBeOptional(): |
| // Turn any(struct{...}) into any(?struct{...}) |
| eWant = vdl.ZeroValue(vdl.AnyType).Assign(vdl.OptionalValue(vvWant.Elem())) |
| case vvWant.Type().CanBeOptional(): |
| // Turn struct{...} into ?struct{...} |
| eWant = vdl.OptionalValue(vvWant) |
| } |
| } else if (ttWant.Kind() == vdl.Optional || ttWant.CanBeOptional()) && rvWant.Kind() != reflect.Ptr { |
| // Add a pointer to non-pointers that can be optional. |
| rvPtrWant := reflect.New(rvWant.Type()) |
| rvPtrWant.Elem().Set(rvWant) |
| eWant = rvPtrWant.Interface() |
| } |
| } |
| if !wantIsVV && ttWant.Kind() != vdl.TypeObject && !ttWant.CanBeOptional() && rvWant.Kind() == reflect.Ptr && !rvWant.IsNil() { |
| // Remove a pointer from anything that can't be optional. |
| eWant = rvWant.Elem().Interface() |
| } |
| } |
| err := vdl.Convert(rvDst.Interface(), rvSrc.Interface()) |
| vdl.ExpectErr(t, err, expectedErr, tname) |
| if expectedErr == "" { |
| expectConvert(t, tname, dst, eWant, deref) |
| } |
| // Next iteration adds a pointer to src. |
| rvNewSrc := reflect.New(rvSrc.Type()) |
| rvNewSrc.Elem().Set(rvSrc) |
| rvSrc = rvNewSrc |
| } |
| // Next iteration adds a pointer to dst. |
| rvNewDst := reflect.New(rvDst.Type()) |
| rvNewDst.Elem().Set(rvDst) |
| rvDst = rvNewDst |
| } |
| } |
| |
| func expectConvert(t *testing.T, tname string, got, want interface{}, deref int) { |
| rvGot := reflect.ValueOf(got) |
| for d := 0; d < deref; d++ { |
| if rvGot.Kind() != reflect.Ptr || rvGot.IsNil() { |
| t.Errorf("%s can't deref %d %T %v", tname, deref, got, got) |
| return |
| } |
| rvGot = rvGot.Elem() |
| } |
| got = rvGot.Interface() |
| vvGot, ok1 := got.(*vdl.Value) |
| vvWant, ok2 := want.(*vdl.Value) |
| if ok1 && ok2 { |
| if !vdl.EqualValue(vvGot, vvWant) { |
| t.Errorf("%s\nGOT %v\nWANT %v", tname, vvGot, vvWant) |
| } |
| return |
| } |
| if !reflect.DeepEqual(got, want) { |
| t.Errorf("%s\nGOT %#v\nWANT %#v", tname, got, want) |
| } |
| } |
| |
| // Test failed conversions. |
| func TestConverterError(t *testing.T) { |
| tests := []struct { |
| ttDst []*vdl.Type |
| rtDst []reflect.Type |
| vvSrc []*vdl.Value |
| rvSrc []interface{} |
| }{ |
| {ttOtherThan(ttAllTypes, ttBools), rtOtherThan(rtAllTypes, rtBools), |
| vvBoolTrue, rvBoolTrue}, |
| {ttOtherThan(ttAllTypes, ttStrs), rtOtherThan(rtAllTypes, rtStrs), |
| vvStrABC, rvStrABC}, |
| {ttOtherThan(ttAllTypes, ttTypeObjects), rtOtherThan(rtAllTypes, rtTypeObjects), |
| vvTypeObjectBool, rvTypeObjectBool}, |
| {ttOtherThan(ttAllTypes, ttSeq123), rtOtherThan(rtAllTypes, rtSeq123), |
| vvSeq123, rvSeq123}, |
| // Test invalid conversions to set types |
| {ttSet123, rtSet123, vvMap123FalseTrue, rvMap123FalseTrue}, |
| {ttSetXYZ, rtSetXYZ, vvMapXYZFalseTrue, rvMapXYZFalseTrue}, |
| // Test invalid conversions to struct types: no fields in common |
| {ttStructWXBool, rtStructWXBool, vvStructUV01, rvStructUV01}, |
| {ttStructUVNum, rtStructUVNum, vvStructWXFalseTrue, rvStructWXFalseTrue}, |
| // Test uint values one past the max bound. |
| {ttOtherThan(ttIntegers, ttTypes(vvFromUint(math.MaxUint8))), |
| rtOtherThan(rtIntegers, rtTypes(rvFromUint(math.MaxUint8))), |
| vvFromUint(math.MaxUint8 + 1), |
| rvFromUint(math.MaxUint8 + 1)}, |
| {ttOtherThan(ttIntegers, ttTypes(vvFromUint(math.MaxUint16))), |
| rtOtherThan(rtIntegers, rtTypes(rvFromUint(math.MaxUint16))), |
| vvFromUint(math.MaxUint16 + 1), |
| rvFromUint(math.MaxUint16 + 1)}, |
| {ttOtherThan(ttIntegers, ttTypes(vvFromUint(math.MaxUint32))), |
| rtOtherThan(rtIntegers, rtTypes(rvFromUint(math.MaxUint32))), |
| vvFromUint(math.MaxUint32 + 1), |
| rvFromUint(math.MaxUint32 + 1)}, |
| // Test int values one past the max bound. |
| {ttOtherThan(ttIntegers, ttTypes(vvFromUint(math.MaxInt8))), |
| rtOtherThan(rtIntegers, rtTypes(rvFromUint(math.MaxInt8))), |
| vvFromUint(math.MaxInt8 + 1), |
| rvFromUint(math.MaxInt8 + 1)}, |
| {ttOtherThan(ttIntegers, ttTypes(vvFromUint(math.MaxInt16))), |
| rtOtherThan(rtIntegers, rtTypes(rvFromUint(math.MaxInt16))), |
| vvFromUint(math.MaxInt16 + 1), |
| rvFromUint(math.MaxInt16 + 1)}, |
| {ttOtherThan(ttIntegers, ttTypes(vvFromUint(math.MaxInt32))), |
| rtOtherThan(rtIntegers, rtTypes(rvFromUint(math.MaxInt32))), |
| vvFromUint(math.MaxInt32 + 1), |
| rvFromUint(math.MaxInt32 + 1)}, |
| {ttOtherThan(ttIntegers, ttTypes(vvFromUint(math.MaxInt64))), |
| rtOtherThan(rtIntegers, rtTypes(rvFromUint(math.MaxInt64))), |
| vvFromUint(math.MaxInt64 + 1), |
| rvFromUint(math.MaxInt64 + 1)}, |
| // Test int values one past the min bound. |
| {ttOtherThan(ttIntegers, ttTypes(vvFromInt(math.MinInt8))), |
| rtOtherThan(rtIntegers, rtTypes(rvFromInt(math.MinInt8))), |
| vvFromInt(math.MinInt8 - 1), |
| rvFromInt(math.MinInt8 - 1)}, |
| {ttOtherThan(ttIntegers, ttTypes(vvFromInt(math.MinInt16))), |
| rtOtherThan(rtIntegers, rtTypes(rvFromInt(math.MinInt16))), |
| vvFromInt(math.MinInt16 - 1), |
| rvFromInt(math.MinInt16 - 1)}, |
| {ttOtherThan(ttIntegers, ttTypes(vvFromInt(math.MinInt32))), |
| rtOtherThan(rtIntegers, rtTypes(rvFromInt(math.MinInt32))), |
| vvFromInt(math.MinInt32 - 1), |
| rvFromInt(math.MinInt32 - 1)}, |
| // Test int to float max bound. |
| {ttJoin(ttFloat32s), rtJoin(rtFloat32s), |
| vvOnlyFrom(vvFromInt(vdl.Float32MaxInt+1), ttIntegers), |
| rvOnlyFrom(rvFromInt(vdl.Float32MaxInt+1), rtIntegers)}, |
| {ttJoin(ttFloat64s), rtJoin(rtFloat64s), |
| vvOnlyFrom(vvFromInt(vdl.Float64MaxInt+1), ttIntegers), |
| rvOnlyFrom(rvFromInt(vdl.Float64MaxInt+1), rtIntegers)}, |
| // Test int to float min bound. |
| {ttJoin(ttFloat32s), rtJoin(rtFloat32s), |
| vvOnlyFrom(vvFromInt(vdl.Float32MinInt-1), ttIntegers), |
| rvOnlyFrom(rvFromInt(vdl.Float32MinInt-1), rtIntegers)}, |
| {ttJoin(ttFloat64s), rtJoin(rtFloat64s), |
| vvOnlyFrom(vvFromInt(vdl.Float64MinInt-1), ttIntegers), |
| rvOnlyFrom(rvFromInt(vdl.Float64MinInt-1), rtIntegers)}, |
| // Test negative uints, fractional integers. |
| {ttUints, rtUints, vvFromInt(-1), rvFromInt(-1)}, |
| {ttIntegers, rtIntegers, vvFloat(1.5), rvFloat(1.5)}, |
| } |
| for _, test := range tests { |
| for _, rtDst := range test.rtDst { |
| rvDst := reflect.New(rtDst) |
| got := rvDst.Elem().Interface() |
| for _, vvSrc := range test.vvSrc { |
| if err := vdl.ConvertReflect(rvDst, reflect.ValueOf(vvSrc)); err == nil { |
| t.Errorf("%s ConvertReflect(%v, %v), want error", rvDst.Type(), vvSrc.Type(), got) |
| } |
| } |
| for _, src := range test.rvSrc { |
| rvSrc := reflect.ValueOf(src) |
| if err := vdl.ConvertReflect(rvDst, rvSrc); err == nil { |
| t.Errorf("%s FromReflect(%v, %v), want error", rvDst.Type(), rvSrc.Type(), got) |
| } |
| } |
| } |
| } |
| } |
| |
| // Note: There are no other tests which cover these cases outside of a test in |
| // v.io/v23/security. |
| // These tests also can't be moved to TestConverter because it involves |
| // conversion to an interface which will resolve in a non-wiretype output. |
| func TestConverterToWiretype(t *testing.T) { |
| var nWire vdl.NWire |
| if err := vdl.Convert(&nWire, vdl.NWire{"100"}); err != nil { |
| t.Fatalf("unexpected error converting to wire type") |
| } |
| if got, want := nWire, (vdl.NWire{"100"}); got != want { |
| t.Errorf("got %#v, want %#v", got, want) |
| } |
| var nUnionWire vdl.NUnionWire |
| if err := vdl.Convert(&nUnionWire, vdl.NUnionNative("A=false")); err != nil { |
| t.Fatalf("unexpected error converting to wire type") |
| } |
| if got, want := nUnionWire, (vdl.NUnionWireA{false}); got != want { |
| t.Errorf("got %#v, want %#v", got, want) |
| } |
| } |
| |
| func TestConvertNew(t *testing.T) { |
| for _, entry := range vdltest.AllPass() { |
| rvTargetPtr := reflect.New(entry.Target.Type()) |
| if err := vdl.Convert(rvTargetPtr.Interface(), entry.Source.Interface()); err != nil { |
| t.Errorf("%s: Convert failed: %v", entry.Name(), err) |
| } |
| if got, want := rvTargetPtr.Elem(), entry.Target; !vdl.DeepEqualReflect(got, want) { |
| t.Errorf("%s\nGOT %v\nWANT %v", entry.Name(), got, want) |
| } |
| } |
| } |
| |
| func TestConvertFailNew(t *testing.T) { |
| for _, entry := range vdltest.AllFail() { |
| rvTargetPtr := reflect.New(entry.Target.Type()) |
| if err := vdl.Convert(rvTargetPtr.Interface(), entry.Source.Interface()); err == nil { |
| t.Errorf("%s: Convert passed, wanted failure", entry.Name()) |
| } |
| } |
| } |