// Copyright (c) Faye Amacker. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. package cbor import ( "bytes" "encoding/binary" "encoding/hex" "errors" "fmt" "io" "math" "math/big" "reflect" "strings" "testing" "time" ) var ( typeBool = reflect.TypeOf(true) typeUint8 = reflect.TypeOf(uint8(0)) typeUint16 = reflect.TypeOf(uint16(0)) typeUint32 = reflect.TypeOf(uint32(0)) typeUint64 = reflect.TypeOf(uint64(0)) typeInt8 = reflect.TypeOf(int8(0)) typeInt16 = reflect.TypeOf(int16(0)) typeInt32 = reflect.TypeOf(int32(0)) typeInt64 = reflect.TypeOf(int64(0)) typeFloat32 = reflect.TypeOf(float32(0)) typeFloat64 = reflect.TypeOf(float64(0)) typeString = reflect.TypeOf("") typeByteSlice = reflect.TypeOf([]byte(nil)) typeByteArray = reflect.TypeOf([5]byte{}) typeIntSlice = reflect.TypeOf([]int{}) typeStringSlice = reflect.TypeOf([]string{}) typeMapStringInt = reflect.TypeOf(map[string]int{}) typeMapStringString = reflect.TypeOf(map[string]string{}) typeMapStringIntf = reflect.TypeOf(map[string]interface{}{}) ) type unmarshalTest struct { cborData []byte emptyInterfaceValue interface{} values []interface{} wrongTypes []reflect.Type } var unmarshalTests = []unmarshalTest{ // CBOR test data are from https://tools.ietf.org/html/rfc7049#appendix-A. // positive integer { hexDecode("00"), uint64(0), []interface{}{uint8(0), uint16(0), uint32(0), uint64(0), uint(0), int8(0), int16(0), int32(0), int64(0), int(0), float32(0), float64(0), bigIntOrPanic("0")}, []reflect.Type{typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("01"), uint64(1), []interface{}{uint8(1), uint16(1), uint32(1), uint64(1), uint(1), int8(1), int16(1), int32(1), int64(1), int(1), float32(1), float64(1), bigIntOrPanic("1")}, []reflect.Type{typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("0a"), uint64(10), []interface{}{uint8(10), uint16(10), uint32(10), uint64(10), uint(10), int8(10), int16(10), int32(10), int64(10), int(10), float32(10), float64(10), bigIntOrPanic("10")}, []reflect.Type{typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("17"), uint64(23), []interface{}{uint8(23), uint16(23), uint32(23), uint64(23), uint(23), int8(23), int16(23), int32(23), int64(23), int(23), float32(23), float64(23), bigIntOrPanic("23")}, []reflect.Type{typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("1818"), uint64(24), []interface{}{uint8(24), uint16(24), uint32(24), uint64(24), uint(24), int8(24), int16(24), int32(24), int64(24), int(24), float32(24), float64(24), bigIntOrPanic("24")}, []reflect.Type{typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("1819"), uint64(25), []interface{}{uint8(25), uint16(25), uint32(25), uint64(25), uint(25), int8(25), int16(25), int32(25), int64(25), int(25), float32(25), float64(25), bigIntOrPanic("25")}, []reflect.Type{typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("1864"), uint64(100), []interface{}{uint8(100), uint16(100), uint32(100), uint64(100), uint(100), int8(100), int16(100), int32(100), int64(100), int(100), float32(100), float64(100), bigIntOrPanic("100")}, []reflect.Type{typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("1903e8"), uint64(1000), []interface{}{uint16(1000), uint32(1000), uint64(1000), uint(1000), int16(1000), int32(1000), int64(1000), int(1000), float32(1000), float64(1000), bigIntOrPanic("1000")}, []reflect.Type{typeUint8, typeInt8, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("1a000f4240"), uint64(1000000), []interface{}{uint32(1000000), uint64(1000000), uint(1000000), int32(1000000), int64(1000000), int(1000000), float32(1000000), float64(1000000), bigIntOrPanic("1000000")}, []reflect.Type{typeUint8, typeUint16, typeInt8, typeInt16, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("1b000000e8d4a51000"), uint64(1000000000000), []interface{}{uint64(1000000000000), uint(1000000000000), int64(1000000000000), int(1000000000000), float32(1000000000000), float64(1000000000000), bigIntOrPanic("1000000000000")}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeInt8, typeInt16, typeInt32, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("1bffffffffffffffff"), uint64(18446744073709551615), []interface{}{uint64(18446744073709551615), uint(18446744073709551615), float32(18446744073709551615), float64(18446744073709551615), bigIntOrPanic("18446744073709551615")}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeInt8, typeInt16, typeInt32, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, // negative integer { hexDecode("20"), int64(-1), []interface{}{int8(-1), int16(-1), int32(-1), int64(-1), int(-1), float32(-1), float64(-1), bigIntOrPanic("-1")}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("29"), int64(-10), []interface{}{int8(-10), int16(-10), int32(-10), int64(-10), int(-10), float32(-10), float64(-10), bigIntOrPanic("-10")}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("3863"), int64(-100), []interface{}{int8(-100), int16(-100), int32(-100), int64(-100), int(-100), float32(-100), float64(-100), bigIntOrPanic("-100")}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("3903e7"), int64(-1000), []interface{}{int16(-1000), int32(-1000), int64(-1000), int(-1000), float32(-1000), float64(-1000), bigIntOrPanic("-1000")}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("3bffffffffffffffff"), bigIntOrPanic("-18446744073709551616"), []interface{}{bigIntOrPanic("-18446744073709551616")}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, // CBOR value -18446744073709551616 overflows Go's int64, see TestNegIntOverflow // byte string { hexDecode("40"), []byte{}, []interface{}{[]byte{}, [0]byte{}, [1]byte{0}, [5]byte{0, 0, 0, 0, 0}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("4401020304"), []byte{1, 2, 3, 4}, []interface{}{[]byte{1, 2, 3, 4}, [0]byte{}, [1]byte{1}, [5]byte{1, 2, 3, 4, 0}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("5f42010243030405ff"), []byte{1, 2, 3, 4, 5}, []interface{}{[]byte{1, 2, 3, 4, 5}, [0]byte{}, [1]byte{1}, [5]byte{1, 2, 3, 4, 5}, [6]byte{1, 2, 3, 4, 5, 0}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, // text string { hexDecode("60"), "", []interface{}{""}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("6161"), "a", []interface{}{"a"}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("6449455446"), "IETF", []interface{}{"IETF"}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("62225c"), "\"\\", []interface{}{"\"\\"}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("62c3bc"), "ü", []interface{}{"ü"}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("63e6b0b4"), "水", []interface{}{"水"}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("64f0908591"), "𐅑", []interface{}{"𐅑"}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("7f657374726561646d696e67ff"), "streaming", []interface{}{"streaming"}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, // array { hexDecode("80"), []interface{}{}, []interface{}{[]interface{}{}, []byte{}, []string{}, []int{}, [0]int{}, [1]int{0}, [5]int{0}, []float32{}, []float64{}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("83010203"), []interface{}{uint64(1), uint64(2), uint64(3)}, []interface{}{[]interface{}{uint64(1), uint64(2), uint64(3)}, []byte{1, 2, 3}, []int{1, 2, 3}, []uint{1, 2, 3}, [0]int{}, [1]int{1}, [3]int{1, 2, 3}, [5]int{1, 2, 3, 0, 0}, []float32{1, 2, 3}, []float64{1, 2, 3}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag, typeBigInt}, }, { hexDecode("8301820203820405"), []interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}, []interface{}{[]interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}, [...]interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag, typeBigInt}, }, { hexDecode("83018202039f0405ff"), []interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}, []interface{}{[]interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}, [...]interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag, typeBigInt}, }, { hexDecode("83019f0203ff820405"), []interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}, []interface{}{[]interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}, [...]interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag, typeBigInt}, }, { hexDecode("98190102030405060708090a0b0c0d0e0f101112131415161718181819"), []interface{}{uint64(1), uint64(2), uint64(3), uint64(4), uint64(5), uint64(6), uint64(7), uint64(8), uint64(9), uint64(10), uint64(11), uint64(12), uint64(13), uint64(14), uint64(15), uint64(16), uint64(17), uint64(18), uint64(19), uint64(20), uint64(21), uint64(22), uint64(23), uint64(24), uint64(25)}, []interface{}{ []interface{}{uint64(1), uint64(2), uint64(3), uint64(4), uint64(5), uint64(6), uint64(7), uint64(8), uint64(9), uint64(10), uint64(11), uint64(12), uint64(13), uint64(14), uint64(15), uint64(16), uint64(17), uint64(18), uint64(19), uint64(20), uint64(21), uint64(22), uint64(23), uint64(24), uint64(25)}, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, []uint{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, [0]int{}, [1]int{1}, [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, [30]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0}, []float32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag, typeBigInt}, }, { hexDecode("9fff"), []interface{}{}, []interface{}{[]interface{}{}, []byte{}, []string{}, []int{}, [0]int{}, [1]int{0}, [5]int{0, 0, 0, 0, 0}, []float32{}, []float64{}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("9f018202039f0405ffff"), []interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}, []interface{}{[]interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}, [...]interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag, typeBigInt}, }, { hexDecode("9f01820203820405ff"), []interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}, []interface{}{[]interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}, [...]interface{}{uint64(1), []interface{}{uint64(2), uint64(3)}, []interface{}{uint64(4), uint64(5)}}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag, typeBigInt}, }, { hexDecode("9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff"), []interface{}{uint64(1), uint64(2), uint64(3), uint64(4), uint64(5), uint64(6), uint64(7), uint64(8), uint64(9), uint64(10), uint64(11), uint64(12), uint64(13), uint64(14), uint64(15), uint64(16), uint64(17), uint64(18), uint64(19), uint64(20), uint64(21), uint64(22), uint64(23), uint64(24), uint64(25)}, []interface{}{ []interface{}{uint64(1), uint64(2), uint64(3), uint64(4), uint64(5), uint64(6), uint64(7), uint64(8), uint64(9), uint64(10), uint64(11), uint64(12), uint64(13), uint64(14), uint64(15), uint64(16), uint64(17), uint64(18), uint64(19), uint64(20), uint64(21), uint64(22), uint64(23), uint64(24), uint64(25)}, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, []uint{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, [0]int{}, [1]int{1}, [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, [30]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0}, []float32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag, typeBigInt}, }, { hexDecode("826161a161626163"), []interface{}{"a", map[interface{}]interface{}{"b": "c"}}, []interface{}{[]interface{}{"a", map[interface{}]interface{}{"b": "c"}}, [...]interface{}{"a", map[interface{}]interface{}{"b": "c"}}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeByteArray, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag, typeBigInt}, }, { hexDecode("826161bf61626163ff"), []interface{}{"a", map[interface{}]interface{}{"b": "c"}}, []interface{}{[]interface{}{"a", map[interface{}]interface{}{"b": "c"}}, [...]interface{}{"a", map[interface{}]interface{}{"b": "c"}}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeByteArray, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag, typeBigInt}, }, // map { hexDecode("a0"), map[interface{}]interface{}{}, []interface{}{map[interface{}]interface{}{}, map[string]bool{}, map[string]int{}, map[int]string{}, map[int]bool{}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeTag, typeRawTag}, }, { hexDecode("a201020304"), map[interface{}]interface{}{uint64(1): uint64(2), uint64(3): uint64(4)}, []interface{}{map[interface{}]interface{}{uint64(1): uint64(2), uint64(3): uint64(4)}, map[uint]int{1: 2, 3: 4}, map[int]uint{1: 2, 3: 4}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("a26161016162820203"), map[interface{}]interface{}{"a": uint64(1), "b": []interface{}{uint64(2), uint64(3)}}, []interface{}{map[interface{}]interface{}{"a": uint64(1), "b": []interface{}{uint64(2), uint64(3)}}, map[string]interface{}{"a": uint64(1), "b": []interface{}{uint64(2), uint64(3)}}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("a56161614161626142616361436164614461656145"), map[interface{}]interface{}{"a": "A", "b": "B", "c": "C", "d": "D", "e": "E"}, []interface{}{map[interface{}]interface{}{"a": "A", "b": "B", "c": "C", "d": "D", "e": "E"}, map[string]interface{}{"a": "A", "b": "B", "c": "C", "d": "D", "e": "E"}, map[string]string{"a": "A", "b": "B", "c": "C", "d": "D", "e": "E"}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("bf61610161629f0203ffff"), map[interface{}]interface{}{"a": uint64(1), "b": []interface{}{uint64(2), uint64(3)}}, []interface{}{map[interface{}]interface{}{"a": uint64(1), "b": []interface{}{uint64(2), uint64(3)}}, map[string]interface{}{"a": uint64(1), "b": []interface{}{uint64(2), uint64(3)}}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("bf6346756ef563416d7421ff"), map[interface{}]interface{}{"Fun": true, "Amt": int64(-2)}, []interface{}{map[interface{}]interface{}{"Fun": true, "Amt": int64(-2)}, map[string]interface{}{"Fun": true, "Amt": int64(-2)}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, // tag { hexDecode("c074323031332d30332d32315432303a30343a30305a"), time.Date(2013, 3, 21, 20, 4, 0, 0, time.UTC), // 2013-03-21 20:04:00 +0000 UTC []interface{}{"2013-03-21T20:04:00Z", time.Date(2013, 3, 21, 20, 4, 0, 0, time.UTC), Tag{0, "2013-03-21T20:04:00Z"}, RawTag{0, hexDecode("74323031332d30332d32315432303a30343a30305a")}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeBigInt}, }, // 0: standard date/time { hexDecode("c11a514b67b0"), time.Date(2013, 3, 21, 20, 4, 0, 0, time.UTC), // 2013-03-21 20:04:00 +0000 UTC []interface{}{uint32(1363896240), uint64(1363896240), int32(1363896240), int64(1363896240), float32(1363896240), float64(1363896240), time.Date(2013, 3, 21, 20, 4, 0, 0, time.UTC), Tag{1, uint64(1363896240)}, RawTag{1, hexDecode("1a514b67b0")}}, []reflect.Type{typeUint8, typeUint16, typeInt8, typeInt16, typeByteSlice, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt}, }, // 1: epoch-based date/time { hexDecode("c249010000000000000000"), bigIntOrPanic("18446744073709551616"), []interface{}{ // Decode to byte slice []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Decode to array of various lengths [0]byte{}, [1]byte{0x01}, [3]byte{0x01, 0x00, 0x00}, [...]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, [10]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Decode to Tag and RawTag Tag{2, []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, RawTag{2, hexDecode("49010000000000000000")}, // Decode to big.Int bigIntOrPanic("18446744073709551616"), }, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt}, }, // 2: positive bignum: 18446744073709551616 { hexDecode("c349010000000000000000"), bigIntOrPanic("-18446744073709551617"), []interface{}{ // Decode to byte slice []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Decode to array of various lengths [0]byte{}, [1]byte{0x01}, [3]byte{0x01, 0x00, 0x00}, [...]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, [10]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Decode to Tag and RawTag Tag{3, []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, RawTag{3, hexDecode("49010000000000000000")}, // Decode to big.Int bigIntOrPanic("-18446744073709551617"), }, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt}, }, // 3: negative bignum: -18446744073709551617 { hexDecode("c1fb41d452d9ec200000"), time.Date(2013, 3, 21, 20, 4, 0, 500000000, time.UTC), // 2013-03-21 20:04:00.5 +0000 UTC []interface{}{float32(1363896240.5), float64(1363896240.5), time.Date(2013, 3, 21, 20, 4, 0, 500000000, time.UTC), Tag{1, float64(1363896240.5)}, RawTag{1, hexDecode("fb41d452d9ec200000")}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeMapStringInt, typeBigInt}, }, // 1: epoch-based date/time { hexDecode("d74401020304"), Tag{23, []byte{0x01, 0x02, 0x03, 0x04}}, []interface{}{[]byte{0x01, 0x02, 0x03, 0x04}, [0]byte{}, [1]byte{0x01}, [3]byte{0x01, 0x02, 0x03}, [...]byte{0x01, 0x02, 0x03, 0x04}, [5]byte{0x01, 0x02, 0x03, 0x04, 0x00}, Tag{23, []byte{0x01, 0x02, 0x03, 0x04}}, RawTag{23, hexDecode("4401020304")}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeBigInt}, }, // 23: expected conversion to base16 encoding { hexDecode("d818456449455446"), Tag{24, []byte{0x64, 0x49, 0x45, 0x54, 0x46}}, []interface{}{[]byte{0x64, 0x49, 0x45, 0x54, 0x46}, [0]byte{}, [1]byte{0x64}, [3]byte{0x64, 0x49, 0x45}, [...]byte{0x64, 0x49, 0x45, 0x54, 0x46}, [6]byte{0x64, 0x49, 0x45, 0x54, 0x46, 0x00}, Tag{24, []byte{0x64, 0x49, 0x45, 0x54, 0x46}}, RawTag{24, hexDecode("456449455446")}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeBigInt}, }, // 24: encoded cborBytes data item { hexDecode("d82076687474703a2f2f7777772e6578616d706c652e636f6d"), Tag{32, "http://www.example.com"}, []interface{}{"http://www.example.com", Tag{32, "http://www.example.com"}, RawTag{32, hexDecode("76687474703a2f2f7777772e6578616d706c652e636f6d")}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeBigInt}, }, // 32: URI // primitives { hexDecode("f4"), false, []interface{}{false}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteArray, typeByteSlice, typeString, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("f5"), true, []interface{}{true}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteArray, typeByteSlice, typeString, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("f6"), nil, []interface{}{false, uint(0), uint8(0), uint16(0), uint32(0), uint64(0), int(0), int8(0), int16(0), int32(0), int64(0), float32(0.0), float64(0.0), "", []byte(nil), []int(nil), []string(nil), map[string]int(nil), time.Time{}, bigIntOrPanic("0"), Tag{}, RawTag{}}, nil, }, { hexDecode("f7"), nil, []interface{}{false, uint(0), uint8(0), uint16(0), uint32(0), uint64(0), int(0), int8(0), int16(0), int32(0), int64(0), float32(0.0), float64(0.0), "", []byte(nil), []int(nil), []string(nil), map[string]int(nil), time.Time{}, bigIntOrPanic("0"), Tag{}, RawTag{}}, nil, }, { hexDecode("f0"), uint64(16), []interface{}{uint8(16), uint16(16), uint32(16), uint64(16), uint(16), int8(16), int16(16), int32(16), int64(16), int(16), float32(16), float64(16), bigIntOrPanic("16")}, []reflect.Type{typeByteSlice, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, // This example is not well-formed because Simple value (with 5-bit value 24) must be >= 32. // See RFC 7049 section 2.3 for details, instead of the incorrect example in RFC 7049 Appendex A. // I reported an errata to RFC 7049 and Carsten Bormann confirmed at https://github.com/fxamacker/cbor/issues/46 /* { hexDecode("f818"), uint64(24), []interface{}{uint8(24), uint16(24), uint32(24), uint64(24), uint(24), int8(24), int16(24), int32(24), int64(24), int(24), float32(24), float64(24)}, []reflect.Type{typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt}, }, */ { hexDecode("f820"), uint64(32), []interface{}{uint8(32), uint16(32), uint32(32), uint64(32), uint(32), int8(32), int16(32), int32(32), int64(32), int(32), float32(32), float64(32), bigIntOrPanic("32")}, []reflect.Type{typeByteSlice, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, { hexDecode("f8ff"), uint64(255), []interface{}{uint8(255), uint16(255), uint32(255), uint64(255), uint(255), int16(255), int32(255), int64(255), int(255), float32(255), float64(255), bigIntOrPanic("255")}, []reflect.Type{typeByteSlice, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, // More testcases not covered by https://tools.ietf.org/html/rfc7049#appendix-A. { hexDecode("5fff"), // empty indefinite length byte string []byte{}, []interface{}{[]byte{}, [0]byte{}, [1]byte{0x00}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("7fff"), // empty indefinite length text string "", []interface{}{""}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, }, { hexDecode("bfff"), // empty indefinite length map map[interface{}]interface{}{}, []interface{}{map[interface{}]interface{}{}, map[string]bool{}, map[string]int{}, map[int]string{}, map[int]bool{}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeTag, typeRawTag}, }, // More test data with tags { hexDecode("c13a0177f2cf"), // 1969-03-21T20:04:00Z, tag 1 with negative integer as epoch time time.Date(1969, 3, 21, 20, 4, 0, 0, time.UTC), []interface{}{int32(-24638160), int64(-24638160), int32(-24638160), int64(-24638160), float32(-24638160), float64(-24638160), time.Date(1969, 3, 21, 20, 4, 0, 0, time.UTC), Tag{1, int64(-24638160)}, RawTag{1, hexDecode("3a0177f2cf")}, bigIntOrPanic("-24638160")}, []reflect.Type{typeUint8, typeUint16, typeInt8, typeInt16, typeByteSlice, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt}, }, { hexDecode("d83dd183010203"), // 61(17([1, 2, 3])), nested tags 61 and 17 Tag{61, Tag{17, []interface{}{uint64(1), uint64(2), uint64(3)}}}, []interface{}{[]interface{}{uint64(1), uint64(2), uint64(3)}, []byte{1, 2, 3}, [0]byte{}, [1]byte{1}, [3]byte{1, 2, 3}, [5]byte{1, 2, 3, 0, 0}, []int{1, 2, 3}, []uint{1, 2, 3}, [...]int{1, 2, 3}, []float32{1, 2, 3}, []float64{1, 2, 3}, Tag{61, Tag{17, []interface{}{uint64(1), uint64(2), uint64(3)}}}, RawTag{61, hexDecode("d183010203")}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{})}, }, } type unmarshalFloatTest struct { cborData []byte emptyInterfaceValue interface{} values []interface{} wrongTypes []reflect.Type equalityThreshold float64 // Not used for +inf, -inf, and NaN. } // unmarshalFloatTests includes test values for float16, float32, and float64. // Note: the function for float16 to float32 conversion was tested with all // 65536 values, which is too many to include here. var unmarshalFloatTests = []unmarshalFloatTest{ // CBOR test data are from https://tools.ietf.org/html/rfc7049#appendix-A. // float16 { hexDecode("f90000"), float64(0.0), []interface{}{float32(0.0), float64(0.0)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("f98000"), float64(-0.0), []interface{}{float32(-0.0), float64(-0.0)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("f93c00"), float64(1.0), []interface{}{float32(1.0), float64(1.0)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("f93e00"), float64(1.5), []interface{}{float32(1.5), float64(1.5)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("f97bff"), float64(65504.0), []interface{}{float32(65504.0), float64(65504.0)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("f90001"), // float16 subnormal value float64(5.960464477539063e-08), []interface{}{float32(5.960464477539063e-08), float64(5.960464477539063e-08)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 1e-16, }, { hexDecode("f90400"), float64(6.103515625e-05), []interface{}{float32(6.103515625e-05), float64(6.103515625e-05)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 1e-16, }, { hexDecode("f9c400"), float64(-4.0), []interface{}{float32(-4.0), float64(-4.0)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("f97c00"), math.Inf(1), []interface{}{math.Float32frombits(0x7f800000), math.Inf(1)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("f97e00"), math.NaN(), []interface{}{math.Float32frombits(0x7fc00000), math.NaN()}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("f9fc00"), math.Inf(-1), []interface{}{math.Float32frombits(0xff800000), math.Inf(-1)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, // float32 { hexDecode("fa47c35000"), float64(100000.0), []interface{}{float32(100000.0), float64(100000.0)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("fa7f7fffff"), float64(3.4028234663852886e+38), []interface{}{float32(3.4028234663852886e+38), float64(3.4028234663852886e+38)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 1e-9, }, { hexDecode("fa7f800000"), math.Inf(1), []interface{}{math.Float32frombits(0x7f800000), math.Inf(1)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("fa7fc00000"), math.NaN(), []interface{}{math.Float32frombits(0x7fc00000), math.NaN()}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("faff800000"), math.Inf(-1), []interface{}{math.Float32frombits(0xff800000), math.Inf(-1)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, // float64 { hexDecode("fb3ff199999999999a"), float64(1.1), []interface{}{float32(1.1), float64(1.1)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 1e-9, }, { hexDecode("fb7e37e43c8800759c"), float64(1.0e+300), []interface{}{float64(1.0e+300)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 1e-9, }, { hexDecode("fbc010666666666666"), float64(-4.1), []interface{}{float32(-4.1), float64(-4.1)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 1e-9, }, { hexDecode("fb7ff0000000000000"), math.Inf(1), []interface{}{math.Float32frombits(0x7f800000), math.Inf(1)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("fb7ff8000000000000"), math.NaN(), []interface{}{math.Float32frombits(0x7fc00000), math.NaN()}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("fbfff0000000000000"), math.Inf(-1), []interface{}{math.Float32frombits(0xff800000), math.Inf(-1)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, // float16 test data from https://en.wikipedia.org/wiki/Half-precision_floating-point_format { hexDecode("f903ff"), float64(0.000060976), []interface{}{float32(0.000060976), float64(0.000060976)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 1e-9, }, { hexDecode("f93bff"), float64(0.999511719), []interface{}{float32(0.999511719), float64(0.999511719)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 1e-9, }, { hexDecode("f93c01"), float64(1.000976563), []interface{}{float32(1.000976563), float64(1.000976563)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 1e-9, }, { hexDecode("f93555"), float64(0.333251953125), []interface{}{float32(0.333251953125), float64(0.333251953125)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 1e-9, }, // CBOR test data "canonNums" are from https://github.com/cbor-wg/cbor-test-vectors { hexDecode("f9bd00"), float64(-1.25), []interface{}{float32(-1.25), float64(-1.25)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("f93e00"), float64(1.5), []interface{}{float32(1.5), float64(1.5)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("fb4024333333333333"), float64(10.1), []interface{}{float32(10.1), float64(10.1)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("f90001"), float64(5.960464477539063e-8), []interface{}{float32(5.960464477539063e-8), float64(5.960464477539063e-8)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("fa7f7fffff"), float64(3.4028234663852886e+38), []interface{}{float32(3.4028234663852886e+38), float64(3.4028234663852886e+38)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("f90400"), float64(0.00006103515625), []interface{}{float32(0.00006103515625), float64(0.00006103515625)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("f933ff"), float64(0.2498779296875), []interface{}{float32(0.2498779296875), float64(0.2498779296875)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("fa33000000"), float64(2.9802322387695312e-8), []interface{}{float32(2.9802322387695312e-8), float64(2.9802322387695312e-8)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("fa33333866"), float64(4.1727979294137185e-8), []interface{}{float32(4.1727979294137185e-8), float64(4.1727979294137185e-8)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, { hexDecode("fa37002000"), float64(0.000007636845111846924), []interface{}{float32(0.000007636845111846924), float64(0.000007636845111846924)}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, } const invalidUTF8ErrorMsg = "cbor: invalid UTF-8 string" func hexDecode(s string) []byte { data, err := hex.DecodeString(s) if err != nil { panic(err) } return data } func bigIntOrPanic(s string) big.Int { bi, ok := new(big.Int).SetString(s, 10) if !ok { panic("failed to convert " + s + " to big.Int") } return *bi } func TestUnmarshal(t *testing.T) { for _, tc := range unmarshalTests { // Test unmarshalling CBOR into empty interface. var v interface{} if err := Unmarshal(tc.cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } else { if tm, ok := tc.emptyInterfaceValue.(time.Time); ok { if vt, ok := v.(time.Time); !ok || !tm.Equal(vt) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborData, v, v, tc.emptyInterfaceValue, tc.emptyInterfaceValue) } } else if !reflect.DeepEqual(v, tc.emptyInterfaceValue) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborData, v, v, tc.emptyInterfaceValue, tc.emptyInterfaceValue) } } // Test unmarshalling CBOR into RawMessage. var r RawMessage if err := Unmarshal(tc.cborData, &r); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } else if !bytes.Equal(r, tc.cborData) { t.Errorf("Unmarshal(0x%x) returned RawMessage %v, want %v", tc.cborData, r, tc.cborData) } // Test unmarshalling CBOR into compatible data types. for _, value := range tc.values { v := reflect.New(reflect.TypeOf(value)) vPtr := v.Interface() if err := Unmarshal(tc.cborData, vPtr); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } else { if tm, ok := value.(time.Time); ok { if vt, ok := v.Elem().Interface().(time.Time); !ok || !tm.Equal(vt) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborData, v.Elem().Interface(), v.Elem().Interface(), value, value) } } else if !reflect.DeepEqual(v.Elem().Interface(), value) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborData, v.Elem().Interface(), v.Elem().Interface(), value, value) } } } // Test unmarshalling CBOR into incompatible data types. for _, typ := range tc.wrongTypes { v := reflect.New(typ) vPtr := v.Interface() if err := Unmarshal(tc.cborData, vPtr); err == nil { t.Errorf("Unmarshal(0x%x, %s) didn't return an error", tc.cborData, typ.String()) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", tc.cborData, err) } else if !strings.Contains(err.Error(), "cannot unmarshal") { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", tc.cborData, err.Error(), "cannot unmarshal") } } } } func TestUnmarshalFloat(t *testing.T) { for _, tc := range unmarshalFloatTests { // Test unmarshalling CBOR into empty interface. var v interface{} if err := Unmarshal(tc.cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } else { testFloat(t, tc.cborData, v, tc.emptyInterfaceValue, tc.equalityThreshold) } // Test unmarshalling CBOR into RawMessage. var r RawMessage if err := Unmarshal(tc.cborData, &r); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } else if !bytes.Equal(r, tc.cborData) { t.Errorf("Unmarshal(0x%x) returned RawMessage %v, want %v", tc.cborData, r, tc.cborData) } // Test unmarshalling CBOR into compatible data types. for _, value := range tc.values { v := reflect.New(reflect.TypeOf(value)) vPtr := v.Interface() if err := Unmarshal(tc.cborData, vPtr); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } else { testFloat(t, tc.cborData, v.Elem().Interface(), value, tc.equalityThreshold) } } // Test unmarshalling CBOR into incompatible data types. for _, typ := range tc.wrongTypes { v := reflect.New(typ) vPtr := v.Interface() if err := Unmarshal(tc.cborData, vPtr); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", tc.cborData) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", tc.cborData, err) } else if !strings.Contains(err.Error(), "cannot unmarshal") { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", tc.cborData, err.Error(), "cannot unmarshal") } } } } func testFloat(t *testing.T, cborData []byte, f interface{}, wantf interface{}, equalityThreshold float64) { switch wantf := wantf.(type) { case float32: f, ok := f.(float32) if !ok { t.Errorf("Unmarshal(0x%x) returned value of type %T, want float32", cborData, f) return } if math.IsNaN(float64(wantf)) { if !math.IsNaN(float64(f)) { t.Errorf("Unmarshal(0x%x) = %f, want NaN", cborData, f) } } else if math.IsInf(float64(wantf), 0) { if f != wantf { t.Errorf("Unmarshal(0x%x) = %f, want %f", cborData, f, wantf) } } else if math.Abs(float64(f-wantf)) > equalityThreshold { t.Errorf("Unmarshal(0x%x) = %.18f, want %.18f, diff %.18f > threshold %.18f", cborData, f, wantf, math.Abs(float64(f-wantf)), equalityThreshold) } case float64: f, ok := f.(float64) if !ok { t.Errorf("Unmarshal(0x%x) returned value of type %T, want float64", cborData, f) return } if math.IsNaN(wantf) { if !math.IsNaN(f) { t.Errorf("Unmarshal(0x%x) = %f, want NaN", cborData, f) } } else if math.IsInf(wantf, 0) { if f != wantf { t.Errorf("Unmarshal(0x%x) = %f, want %f", cborData, f, wantf) } } else if math.Abs(f-wantf) > equalityThreshold { t.Errorf("Unmarshal(0x%x) = %.18f, want %.18f, diff %.18f > threshold %.18f", cborData, f, wantf, math.Abs(f-wantf), equalityThreshold) } } } func TestNegIntOverflow(t *testing.T) { cborData := hexDecode("3bffffffffffffffff") // -18446744073709551616 // Decode CBOR neg int that overflows Go int64 to empty interface var v1 interface{} wantObj := bigIntOrPanic("-18446744073709551616") if err := Unmarshal(cborData, &v1); err != nil { t.Errorf("Unmarshal(0x%x) returned error %+v", cborData, err) } else if !reflect.DeepEqual(v1, wantObj) { t.Errorf("Unmarshal(0x%x) returned %v (%T), want %v (%T)", cborData, v1, v1, wantObj, wantObj) } // Decode CBOR neg int that overflows Go int64 to big.Int var v2 big.Int if err := Unmarshal(cborData, &v2); err != nil { t.Errorf("Unmarshal(0x%x) returned error %+v", cborData, err) } else if !reflect.DeepEqual(v2, wantObj) { t.Errorf("Unmarshal(0x%x) returned %v (%T), want %v (%T)", cborData, v2, v2, wantObj, wantObj) } // Decode CBOR neg int that overflows Go int64 to int64 var v3 int64 if err := Unmarshal(cborData, &v3); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", cborData, err) } else if !strings.Contains(err.Error(), "cannot unmarshal") { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), "cannot unmarshal") } } func TestUnmarshalIntoPtrPrimitives(t *testing.T) { cborDataInt := hexDecode("1818") // 24 cborDataString := hexDecode("7f657374726561646d696e67ff") // "streaming" const wantInt = 24 const wantString = "streaming" var p1 *int var p2 *string var p3 *RawMessage var i int pi := &i ppi := &pi var s string ps := &s pps := &ps var r RawMessage pr := &r ppr := &pr // Unmarshal CBOR integer into a non-nil pointer. if err := Unmarshal(cborDataInt, &ppi); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborDataInt, err) } else if i != wantInt { t.Errorf("Unmarshal(0x%x) = %v (%T), want %d", cborDataInt, i, i, wantInt) } // Unmarshal CBOR integer into a nil pointer. if err := Unmarshal(cborDataInt, &p1); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborDataInt, err) } else if *p1 != wantInt { t.Errorf("Unmarshal(0x%x) = %v (%T), want %d", cborDataInt, *pi, pi, wantInt) } // Unmarshal CBOR string into a non-nil pointer. if err := Unmarshal(cborDataString, &pps); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborDataString, err) } else if s != wantString { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v", cborDataString, s, s, wantString) } // Unmarshal CBOR string into a nil pointer. if err := Unmarshal(cborDataString, &p2); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborDataString, err) } else if *p2 != wantString { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v", cborDataString, *p2, p2, wantString) } // Unmarshal CBOR string into a non-nil RawMessage. if err := Unmarshal(cborDataString, &ppr); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborDataString, err) } else if !bytes.Equal(r, cborDataString) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v", cborDataString, r, r, cborDataString) } // Unmarshal CBOR string into a nil pointer to RawMessage. if err := Unmarshal(cborDataString, &p3); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborDataString, err) } else if !bytes.Equal(*p3, cborDataString) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v", cborDataString, *p3, p3, cborDataString) } } func TestUnmarshalIntoPtrArrayPtrElem(t *testing.T) { cborData := hexDecode("83010203") // []int{1, 2, 3} n1, n2, n3 := 1, 2, 3 wantArray := []*int{&n1, &n2, &n3} var p *[]*int var slc []*int pslc := &slc ppslc := &pslc // Unmarshal CBOR array into a non-nil pointer. if err := Unmarshal(cborData, &ppslc); err != nil { t.Errorf("Unmarshal(0x%x, %s) returned error %v", cborData, reflect.TypeOf(ppslc), err) } else if !reflect.DeepEqual(slc, wantArray) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v", cborData, slc, slc, wantArray) } // Unmarshal CBOR array into a nil pointer. if err := Unmarshal(cborData, &p); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if !reflect.DeepEqual(*p, wantArray) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v", cborData, *p, p, wantArray) } } func TestUnmarshalIntoPtrMapPtrElem(t *testing.T) { cborData := hexDecode("a201020304") // {1: 2, 3: 4} n1, n2, n3, n4 := 1, 2, 3, 4 wantMap := map[int]*int{n1: &n2, n3: &n4} var p *map[int]*int var m map[int]*int pm := &m ppm := &pm // Unmarshal CBOR map into a non-nil pointer. if err := Unmarshal(cborData, &ppm); err != nil { t.Errorf("Unmarshal(0x%x, %s) returned error %v", cborData, reflect.TypeOf(ppm), err) } else if !reflect.DeepEqual(m, wantMap) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v", cborData, m, m, wantMap) } // Unmarshal CBOR map into a nil pointer. if err := Unmarshal(cborData, &p); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if !reflect.DeepEqual(*p, wantMap) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v", cborData, *p, p, wantMap) } } func TestUnmarshalIntoPtrStructPtrElem(t *testing.T) { type s1 struct { A *string `cbor:"a"` B *string `cbor:"b"` C *string `cbor:"c"` D *string `cbor:"d"` E *string `cbor:"e"` } cborData := hexDecode("a56161614161626142616361436164614461656145") // map[string]string{"a": "A", "b": "B", "c": "C", "d": "D", "e": "E"} a, b, c, d, e := "A", "B", "C", "D", "E" wantObj := s1{A: &a, B: &b, C: &c, D: &d, E: &e} var p *s1 var s s1 ps := &s pps := &ps // Unmarshal CBOR map into a non-nil pointer. if err := Unmarshal(cborData, &pps); err != nil { t.Errorf("Unmarshal(0x%x, %s) returned error %v", cborData, reflect.TypeOf(pps), err) } else if !reflect.DeepEqual(s, wantObj) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v", cborData, s, s, wantObj) } // Unmarshal CBOR map into a nil pointer. if err := Unmarshal(cborData, &p); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if !reflect.DeepEqual(*p, wantObj) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v", cborData, *p, p, wantObj) } } func TestUnmarshalIntoArray(t *testing.T) { cborData := hexDecode("83010203") // []int{1, 2, 3} // Unmarshal CBOR array into Go array. var arr1 [3]int if err := Unmarshal(cborData, &arr1); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if arr1 != [3]int{1, 2, 3} { t.Errorf("Unmarshal(0x%x) = %v (%T), want [3]int{1, 2, 3}", cborData, arr1, arr1) } // Unmarshal CBOR array into Go array with more elements. var arr2 [5]int if err := Unmarshal(cborData, &arr2); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if arr2 != [5]int{1, 2, 3, 0, 0} { t.Errorf("Unmarshal(0x%x) = %v (%T), want [5]int{1, 2, 3, 0, 0}", cborData, arr2, arr2) } // Unmarshal CBOR array into Go array with less elements. var arr3 [1]int if err := Unmarshal(cborData, &arr3); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if arr3 != [1]int{1} { t.Errorf("Unmarshal(0x%x) = %v (%T), want [0]int{1}", cborData, arr3, arr3) } } type nilUnmarshaler string func (s *nilUnmarshaler) UnmarshalCBOR(data []byte) error { if len(data) == 1 && (data[0] == 0xf6 || data[0] == 0xf7) { *s = "null" } else { *s = nilUnmarshaler(data) } return nil } func TestUnmarshalNil(t *testing.T) { type T struct { I int } cborData := [][]byte{hexDecode("f6"), hexDecode("f7")} // CBOR null and undefined values testCases := []struct { name string value interface{} wantValue interface{} }{ // Unmarshalling CBOR null to the following types is a no-op. {"bool", true, true}, {"int", int(-1), int(-1)}, {"int8", int8(-2), int8(-2)}, {"int16", int16(-3), int16(-3)}, {"int32", int32(-4), int32(-4)}, {"int64", int64(-5), int64(-5)}, {"uint", uint(1), uint(1)}, {"uint8", uint8(2), uint8(2)}, {"uint16", uint16(3), uint16(3)}, {"uint32", uint32(4), uint32(4)}, {"uint64", uint64(5), uint64(5)}, {"float32", float32(1.23), float32(1.23)}, {"float64", float64(4.56), float64(4.56)}, {"string", "hello", "hello"}, {"array", [3]int{1, 2, 3}, [3]int{1, 2, 3}}, // Unmarshalling CBOR null to slice/map sets Go values to nil. {"[]byte", []byte{1, 2, 3}, []byte(nil)}, {"slice", []string{"hello", "world"}, []string(nil)}, {"map", map[string]bool{"hello": true, "goodbye": false}, map[string]bool(nil)}, // Unmarshalling CBOR null to time.Time is a no-op. {"time.Time", time.Date(2020, time.January, 2, 3, 4, 5, 6, time.UTC), time.Date(2020, time.January, 2, 3, 4, 5, 6, time.UTC)}, // Unmarshalling CBOR null to big.Int is a no-op. {"big.Int", bigIntOrPanic("123"), bigIntOrPanic("123")}, // Unmarshalling CBOR null to user defined struct types is a no-op. {"user defined struct", T{I: 123}, T{I: 123}}, // Unmarshalling CBOR null to cbor.Tag and cbor.RawTag is a no-op. {"cbor.RawTag", RawTag{123, []byte{4, 5, 6}}, RawTag{123, []byte{4, 5, 6}}}, {"cbor.Tag", Tag{123, "hello world"}, Tag{123, "hello world"}}, // Unmarshalling to cbor.RawMessage sets cbor.RawMessage to raw CBOR bytes (0xf6 or 0xf7). // It's tested in TestUnmarshal(). // Unmarshalling to types implementing cbor.BinaryUnmarshaler is a no-op. //{"cbor.BinaryUnmarshaler", nilBinaryUnmarshaler("hello world"), nilBinaryUnmarshaler("hello world")}, {"cbor.BinaryUnmarshaler", number(456), number(456)}, // When unmarshalling to types implementing cbor.Unmarshaler, // UnmarshalCBOR function receives raw CBOR bytes (0xf6 or 0xf7). {"cbor.Unmarshaler", nilUnmarshaler("hello world"), nilUnmarshaler("null")}, } // Unmarshalling to values of specified Go types. for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { for _, data := range cborData { v := reflect.New(reflect.TypeOf(tc.value)) v.Elem().Set(reflect.ValueOf(tc.value)) if err := Unmarshal(data, v.Interface()); err != nil { t.Errorf("Unmarshal(0x%x) to %T returned error %v", data, v.Elem().Interface(), err) } else if !reflect.DeepEqual(v.Elem().Interface(), tc.wantValue) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", data, v.Elem().Interface(), v.Elem().Interface(), tc.wantValue, tc.wantValue) } } }) } } var invalidUnmarshalTests = []struct { name string v interface{} wantErrorMsg string }{ {"unmarshal into nil interface{}", nil, "cbor: Unmarshal(nil)"}, {"unmarshal into non-pointer value", 5, "cbor: Unmarshal(non-pointer int)"}, {"unmarshal into nil pointer", (*int)(nil), "cbor: Unmarshal(nil *int)"}, } func TestInvalidUnmarshal(t *testing.T) { cborData := []byte{0x00} for _, tc := range invalidUnmarshalTests { t.Run(tc.name, func(t *testing.T) { err := Unmarshal(cborData, tc.v) if err == nil { t.Errorf("Unmarshal(0x%x, %v) didn't return an error", cborData, tc.v) } else if _, ok := err.(*InvalidUnmarshalError); !ok { t.Errorf("Unmarshal(0x%x, %v) error type %T, want *InvalidUnmarshalError", cborData, tc.v, err) } else if err.Error() != tc.wantErrorMsg { t.Errorf("Unmarshal(0x%x, %v) error %q, want %q", cborData, tc.v, err.Error(), tc.wantErrorMsg) } }) } } var invalidCBORUnmarshalTests = []struct { name string cborData []byte wantErrorMsg string errorMsgPartialMatch bool }{ {"Nil data", []byte(nil), "EOF", false}, {"Empty data", []byte{}, "EOF", false}, {"Tag number not followed by tag content", []byte{0xc0}, "unexpected EOF", false}, {"Definite length strings with tagged chunk", hexDecode("5fc64401020304ff"), "cbor: wrong element type tag for indefinite-length byte string", false}, {"Definite length strings with tagged chunk", hexDecode("7fc06161ff"), "cbor: wrong element type tag for indefinite-length UTF-8 text string", false}, {"Indefinite length strings with invalid head", hexDecode("7f61"), "unexpected EOF", false}, {"Invalid nested tag number", hexDecode("d864dc1a514b67b0"), "cbor: invalid additional information", true}, // Data from 7049bis G.1 // Premature end of the input {"End of input in a head", hexDecode("18"), "unexpected EOF", false}, {"End of input in a head", hexDecode("19"), "unexpected EOF", false}, {"End of input in a head", hexDecode("1a"), "unexpected EOF", false}, {"End of input in a head", hexDecode("1b"), "unexpected EOF", false}, {"End of input in a head", hexDecode("1901"), "unexpected EOF", false}, {"End of input in a head", hexDecode("1a0102"), "unexpected EOF", false}, {"End of input in a head", hexDecode("1b01020304050607"), "unexpected EOF", false}, {"End of input in a head", hexDecode("38"), "unexpected EOF", false}, {"End of input in a head", hexDecode("58"), "unexpected EOF", false}, {"End of input in a head", hexDecode("78"), "unexpected EOF", false}, {"End of input in a head", hexDecode("98"), "unexpected EOF", false}, {"End of input in a head", hexDecode("9a01ff00"), "unexpected EOF", false}, {"End of input in a head", hexDecode("b8"), "unexpected EOF", false}, {"End of input in a head", hexDecode("d8"), "unexpected EOF", false}, {"End of input in a head", hexDecode("f8"), "unexpected EOF", false}, {"End of input in a head", hexDecode("f900"), "unexpected EOF", false}, {"End of input in a head", hexDecode("fa0000"), "unexpected EOF", false}, {"End of input in a head", hexDecode("fb000000"), "unexpected EOF", false}, {"Definite length strings with short data", hexDecode("41"), "unexpected EOF", false}, {"Definite length strings with short data", hexDecode("61"), "unexpected EOF", false}, {"Definite length strings with short data", hexDecode("5affffffff00"), "unexpected EOF", false}, {"Definite length strings with short data", hexDecode("5bffffffffffffffff010203"), "cbor: byte string length 18446744073709551615 is too large, causing integer overflow", false}, {"Definite length strings with short data", hexDecode("7affffffff00"), "unexpected EOF", false}, {"Definite length strings with short data", hexDecode("7b7fffffffffffffff010203"), "unexpected EOF", false}, {"Definite length maps and arrays not closed with enough items", hexDecode("81"), "unexpected EOF", false}, {"Definite length maps and arrays not closed with enough items", hexDecode("818181818181818181"), "unexpected EOF", false}, {"Definite length maps and arrays not closed with enough items", hexDecode("8200"), "unexpected EOF", false}, {"Definite length maps and arrays not closed with enough items", hexDecode("a1"), "unexpected EOF", false}, {"Definite length maps and arrays not closed with enough items", hexDecode("a20102"), "unexpected EOF", false}, {"Definite length maps and arrays not closed with enough items", hexDecode("a100"), "unexpected EOF", false}, {"Definite length maps and arrays not closed with enough items", hexDecode("a2000000"), "unexpected EOF", false}, {"Indefinite length strings not closed by a break stop code", hexDecode("5f4100"), "unexpected EOF", false}, {"Indefinite length strings not closed by a break stop code", hexDecode("7f6100"), "unexpected EOF", false}, {"Indefinite length maps and arrays not closed by a break stop code", hexDecode("9f"), "unexpected EOF", false}, {"Indefinite length maps and arrays not closed by a break stop code", hexDecode("9f0102"), "unexpected EOF", false}, {"Indefinite length maps and arrays not closed by a break stop code", hexDecode("bf"), "unexpected EOF", false}, {"Indefinite length maps and arrays not closed by a break stop code", hexDecode("bf01020102"), "unexpected EOF", false}, {"Indefinite length maps and arrays not closed by a break stop code", hexDecode("819f"), "unexpected EOF", false}, {"Indefinite length maps and arrays not closed by a break stop code", hexDecode("9f8000"), "unexpected EOF", false}, {"Indefinite length maps and arrays not closed by a break stop code", hexDecode("9f9f9f9f9fffffffff"), "unexpected EOF", false}, {"Indefinite length maps and arrays not closed by a break stop code", hexDecode("9f819f819f9fffffff"), "unexpected EOF", false}, // Five subkinds of well-formedness error kind 3 (syntax error) {"Reserved additional information values", hexDecode("3e"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("5c"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("5d"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("5e"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("7c"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("7d"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("7e"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("9c"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("9d"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("9e"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("bc"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("bd"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("be"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("dc"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("dd"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("de"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("fc"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("fd"), "cbor: invalid additional information", true}, {"Reserved additional information values", hexDecode("fe"), "cbor: invalid additional information", true}, {"Reserved two-byte encodings of simple types", hexDecode("f800"), "cbor: invalid simple value 0 for type primitives", true}, {"Reserved two-byte encodings of simple types", hexDecode("f801"), "cbor: invalid simple value 1 for type primitives", true}, {"Reserved two-byte encodings of simple types", hexDecode("f818"), "cbor: invalid simple value 24 for type primitives", true}, {"Reserved two-byte encodings of simple types", hexDecode("f81f"), "cbor: invalid simple value 31 for type primitives", true}, {"Indefinite length string chunks not of the correct type", hexDecode("5f00ff"), "cbor: wrong element type positive integer for indefinite-length byte string", false}, {"Indefinite length string chunks not of the correct type", hexDecode("5f21ff"), "cbor: wrong element type negative integer for indefinite-length byte string", false}, {"Indefinite length string chunks not of the correct type", hexDecode("5f6100ff"), "cbor: wrong element type UTF-8 text string for indefinite-length byte string", false}, {"Indefinite length string chunks not of the correct type", hexDecode("5f80ff"), "cbor: wrong element type array for indefinite-length byte string", false}, {"Indefinite length string chunks not of the correct type", hexDecode("5fa0ff"), "cbor: wrong element type map for indefinite-length byte string", false}, {"Indefinite length string chunks not of the correct type", hexDecode("5fc000ff"), "cbor: wrong element type tag for indefinite-length byte string", false}, {"Indefinite length string chunks not of the correct type", hexDecode("5fe0ff"), "cbor: wrong element type primitives for indefinite-length byte string", false}, {"Indefinite length string chunks not of the correct type", hexDecode("7f4100ff"), "cbor: wrong element type byte string for indefinite-length UTF-8 text string", false}, {"Indefinite length string chunks not definite length", hexDecode("5f5f4100ffff"), "cbor: indefinite-length byte string chunk is not definite-length", false}, {"Indefinite length string chunks not definite length", hexDecode("7f7f6100ffff"), "cbor: indefinite-length UTF-8 text string chunk is not definite-length", false}, {"Break occurring on its own outside of an indefinite length item", hexDecode("ff"), "cbor: unexpected \"break\" code", true}, {"Break occurring in a definite length array or map or a tag", hexDecode("81ff"), "cbor: unexpected \"break\" code", true}, {"Break occurring in a definite length array or map or a tag", hexDecode("8200ff"), "cbor: unexpected \"break\" code", true}, {"Break occurring in a definite length array or map or a tag", hexDecode("a1ff"), "cbor: unexpected \"break\" code", true}, {"Break occurring in a definite length array or map or a tag", hexDecode("a1ff00"), "cbor: unexpected \"break\" code", true}, {"Break occurring in a definite length array or map or a tag", hexDecode("a100ff"), "cbor: unexpected \"break\" code", true}, {"Break occurring in a definite length array or map or a tag", hexDecode("a20000ff"), "cbor: unexpected \"break\" code", true}, {"Break occurring in a definite length array or map or a tag", hexDecode("9f81ff"), "cbor: unexpected \"break\" code", true}, {"Break occurring in a definite length array or map or a tag", hexDecode("9f829f819f9fffffffff"), "cbor: unexpected \"break\" code", true}, {"Break in indefinite length map would lead to odd number of items (break in a value position)", hexDecode("bf00ff"), "cbor: unexpected \"break\" code", true}, {"Break in indefinite length map would lead to odd number of items (break in a value position)", hexDecode("bf000000ff"), "cbor: unexpected \"break\" code", true}, {"Major type 0 with additional information 31", hexDecode("1f"), "cbor: invalid additional information 31 for type positive integer", true}, {"Major type 1 with additional information 31", hexDecode("3f"), "cbor: invalid additional information 31 for type negative integer", true}, {"Major type 6 with additional information 31", hexDecode("df"), "cbor: invalid additional information 31 for type tag", true}, } func TestInvalidCBORUnmarshal(t *testing.T) { for _, tc := range invalidCBORUnmarshalTests { t.Run(tc.name, func(t *testing.T) { var i interface{} err := Unmarshal(tc.cborData, &i) if err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", tc.cborData) } else if !tc.errorMsgPartialMatch && err.Error() != tc.wantErrorMsg { t.Errorf("Unmarshal(0x%x) error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } else if tc.errorMsgPartialMatch && !strings.Contains(err.Error(), tc.wantErrorMsg) { t.Errorf("Unmarshal(0x%x) error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } }) } } func TestInvalidUTF8TextString(t *testing.T) { invalidUTF8TextStringTests := []struct { name string cborData []byte wantErrorMsg string }{ {"definite length text string", hexDecode("61fe"), invalidUTF8ErrorMsg}, {"indefinite length text string", hexDecode("7f62e6b061b4ff"), invalidUTF8ErrorMsg}, } for _, tc := range invalidUTF8TextStringTests { t.Run(tc.name, func(t *testing.T) { var i interface{} if err := Unmarshal(tc.cborData, &i); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", tc.cborData) } else if err.Error() != tc.wantErrorMsg { t.Errorf("Unmarshal(0x%x) error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } var s string if err := Unmarshal(tc.cborData, &s); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", tc.cborData) } else if err.Error() != tc.wantErrorMsg { t.Errorf("Unmarshal(0x%x) error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } }) } // Test decoding of mixed invalid text string and valid text string cborData := hexDecode("7f62e6b061b4ff7f657374726561646d696e67ff") dec := NewDecoder(bytes.NewReader(cborData)) var s string if err := dec.Decode(&s); err == nil { t.Errorf("Decode() didn't return an error") } else if s != "" { t.Errorf("Decode() returned %q, want %q", s, "") } if err := dec.Decode(&s); err != nil { t.Errorf("Decode() returned error %v", err) } else if s != "streaming" { t.Errorf("Decode() returned %q, want %q", s, "streaming") } } func TestUnmarshalStruct(t *testing.T) { want := outer{ IntField: 123, FloatField: 100000.0, BoolField: true, StringField: "test", ByteStringField: []byte{1, 3, 5}, ArrayField: []string{"hello", "world"}, MapField: map[string]bool{"morning": true, "afternoon": false}, NestedStructField: &inner{X: 1000, Y: 1000000}, unexportedField: 0, } tests := []struct { name string cborData []byte want interface{} }{ {"case-insensitive field name match", hexDecode("a868696e746669656c64187b6a666c6f61746669656c64fa47c3500069626f6f6c6669656c64f56b537472696e674669656c6464746573746f42797465537472696e674669656c64430103056a41727261794669656c64826568656c6c6f65776f726c64684d61704669656c64a2676d6f726e696e67f56961667465726e6f6f6ef4714e65737465645374727563744669656c64a261581903e861591a000f4240"), want}, {"exact field name match", hexDecode("a868496e744669656c64187b6a466c6f61744669656c64fa47c3500069426f6f6c4669656c64f56b537472696e674669656c6464746573746f42797465537472696e674669656c64430103056a41727261794669656c64826568656c6c6f65776f726c64684d61704669656c64a2676d6f726e696e67f56961667465726e6f6f6ef4714e65737465645374727563744669656c64a261581903e861591a000f4240"), want}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { var v outer if err := Unmarshal(tc.cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } else if !reflect.DeepEqual(v, want) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborData, v, v, want, want) } }) } } func TestUnmarshalStructError1(t *testing.T) { type outer2 struct { IntField int FloatField float32 BoolField bool StringField string ByteStringField []byte ArrayField []int // wrong type MapField map[string]bool NestedStructField map[int]string // wrong type unexportedField int64 } want := outer2{ IntField: 123, FloatField: 100000.0, BoolField: true, StringField: "test", ByteStringField: []byte{1, 3, 5}, ArrayField: []int{0, 0}, MapField: map[string]bool{"morning": true, "afternoon": false}, NestedStructField: map[int]string{}, unexportedField: 0, } cborData := hexDecode("a868496e744669656c64187b6a466c6f61744669656c64fa47c3500069426f6f6c4669656c64f56b537472696e674669656c6464746573746f42797465537472696e674669656c64430103056a41727261794669656c64826568656c6c6f65776f726c64684d61704669656c64a2676d6f726e696e67f56961667465726e6f6f6ef4714e65737465645374727563744669656c64a261581903e861591a000f4240") wantCBORType := "UTF-8 text string" wantGoType := "int" wantStructFieldName := "cbor.outer2.ArrayField" wantErrorMsg := "cannot unmarshal UTF-8 text string into Go struct field cbor.outer2.ArrayField of type int" var v outer2 if err := Unmarshal(cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else { if typeError, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong type of error %T, want (*UnmarshalTypeError)", cborData, err) } else { if typeError.CBORType != wantCBORType { t.Errorf("Unmarshal(0x%x) returned (*UnmarshalTypeError).CBORType %s, want %s", cborData, typeError.CBORType, wantCBORType) } if typeError.GoType != wantGoType { t.Errorf("Unmarshal(0x%x) returned (*UnmarshalTypeError).GoType %s, want %s", cborData, typeError.GoType, wantGoType) } if typeError.StructFieldName != wantStructFieldName { t.Errorf("Unmarshal(0x%x) returned (*UnmarshalTypeError).StructFieldName %s, want %s", cborData, typeError.StructFieldName, wantStructFieldName) } if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } } } if !reflect.DeepEqual(v, want) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, want, want) } } func TestUnmarshalStructError2(t *testing.T) { // Unmarshal integer and invalid UTF8 string as field name into struct type strc struct { A string `cbor:"a"` B string `cbor:"b"` C string `cbor:"c"` } want := strc{ A: "A", } // Unmarshal returns first error encountered, which is *UnmarshalTypeError (failed to unmarshal int into Go string) cborData := hexDecode("a3fa47c35000026161614161fe6142") // {100000.0:2, "a":"A", 0xfe: B} wantCBORType := "primitives" wantGoType := "string" wantErrorMsg := "cannot unmarshal primitives into Go value of type string" v := strc{} if err := Unmarshal(cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else { if typeError, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong type of error %T, want (*UnmarshalTypeError)", cborData, err) } else { if typeError.CBORType != wantCBORType { t.Errorf("Unmarshal(0x%x) returned (*UnmarshalTypeError).CBORType %s, want %s", cborData, typeError.CBORType, wantCBORType) } if typeError.GoType != wantGoType { t.Errorf("Unmarshal(0x%x) returned (*UnmarshalTypeError).GoType %s, want %s", cborData, typeError.GoType, wantGoType) } if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } } } if !reflect.DeepEqual(v, want) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, want, want) } // Unmarshal returns first error encountered, which is *cbor.SemanticError (invalid UTF8 string) cborData = hexDecode("a361fe6142010261616141") // {0xfe: B, 1:2, "a":"A"} v = strc{} if err := Unmarshal(cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else { if _, ok := err.(*SemanticError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong type of error %T, want (*SemanticError)", cborData, err) } else if err.Error() != invalidUTF8ErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want error %q", cborData, err.Error(), invalidUTF8ErrorMsg) } } if !reflect.DeepEqual(v, want) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, want, want) } // Unmarshal returns first error encountered, which is *cbor.SemanticError (invalid UTF8 string) cborData = hexDecode("a3616261fe010261616141") // {"b": 0xfe, 1:2, "a":"A"} v = strc{} if err := Unmarshal(cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else { if _, ok := err.(*SemanticError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong type of error %T, want (*SemanticError)", cborData, err) } else if err.Error() != invalidUTF8ErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want error %q", cborData, err.Error(), invalidUTF8ErrorMsg) } } if !reflect.DeepEqual(v, want) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, want, want) } } func TestUnmarshalPrefilledArray(t *testing.T) { prefilledArr := []int{1, 2, 3, 4, 5} want := []int{10, 11, 3, 4, 5} cborData := hexDecode("820a0b") // []int{10, 11} if err := Unmarshal(cborData, &prefilledArr); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if len(prefilledArr) != 2 || cap(prefilledArr) != 5 { t.Errorf("Unmarshal(0x%x) = %v (len %d, cap %d), want len == 2, cap == 5", cborData, prefilledArr, len(prefilledArr), cap(prefilledArr)) } if !reflect.DeepEqual(prefilledArr[:cap(prefilledArr)], want) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, prefilledArr, prefilledArr, want, want) } cborData = hexDecode("80") // empty array if err := Unmarshal(cborData, &prefilledArr); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if len(prefilledArr) != 0 || cap(prefilledArr) != 0 { t.Errorf("Unmarshal(0x%x) = %v (len %d, cap %d), want len == 0, cap == 0", cborData, prefilledArr, len(prefilledArr), cap(prefilledArr)) } } func TestUnmarshalPrefilledMap(t *testing.T) { prefilledMap := map[string]string{"key": "value", "a": "1"} want := map[string]string{"key": "value", "a": "A", "b": "B", "c": "C", "d": "D", "e": "E"} cborData := hexDecode("a56161614161626142616361436164614461656145") // map[string]string{"a": "A", "b": "B", "c": "C", "d": "D", "e": "E"} if err := Unmarshal(cborData, &prefilledMap); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if !reflect.DeepEqual(prefilledMap, want) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, prefilledMap, prefilledMap, want, want) } prefilledMap = map[string]string{"key": "value"} want = map[string]string{"key": "value"} cborData = hexDecode("a0") // map[string]string{} if err := Unmarshal(cborData, &prefilledMap); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if !reflect.DeepEqual(prefilledMap, want) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, prefilledMap, prefilledMap, want, want) } } func TestUnmarshalPrefilledStruct(t *testing.T) { type s struct { a int B []int C bool } prefilledStruct := s{a: 100, B: []int{200, 300, 400, 500}, C: true} want := s{a: 100, B: []int{2, 3}, C: true} cborData := hexDecode("a26161016162820203") // map[string]interface{} {"a": 1, "b": []int{2, 3}} if err := Unmarshal(cborData, &prefilledStruct); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if !reflect.DeepEqual(prefilledStruct, want) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, prefilledStruct, prefilledStruct, want, want) } if len(prefilledStruct.B) != 2 || cap(prefilledStruct.B) != 4 { t.Errorf("Unmarshal(0x%x) = %v (len %d, cap %d), want len == 2, cap == 5", cborData, prefilledStruct.B, len(prefilledStruct.B), cap(prefilledStruct.B)) } if !reflect.DeepEqual(prefilledStruct.B[:cap(prefilledStruct.B)], []int{2, 3, 400, 500}) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, prefilledStruct.B, prefilledStruct.B, []int{2, 3, 400, 500}, []int{2, 3, 400, 500}) } } func TestStructFieldNil(t *testing.T) { type TestStruct struct { I int PI *int PPI **int } var struc TestStruct cborData, err := Marshal(struc) if err != nil { t.Fatalf("Marshal(%+v) returned error %v", struc, err) } var struc2 TestStruct err = Unmarshal(cborData, &struc2) if err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if !reflect.DeepEqual(struc, struc2) { t.Errorf("Unmarshal(0x%x) returned %+v, want %+v", cborData, struc2, struc) } } func TestLengthOverflowsInt(t *testing.T) { // Data is generating by go-fuzz. // string/slice/map length in uint64 cast to int causes integer overflow. cborData := [][]byte{ hexDecode("bbcf30303030303030cfd697829782"), hexDecode("5bcf30303030303030cfd697829782"), } wantErrorMsg := "is too large" for _, data := range cborData { var intf interface{} if err := Unmarshal(data, &intf); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want error containing substring %q", data, wantErrorMsg) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing substring %q", data, err.Error(), wantErrorMsg) } } } func TestMapKeyUnhashable(t *testing.T) { testCases := []struct { name string cborData []byte wantErrorMsg string }{ {"slice as map key", hexDecode("bf8030ff"), "cbor: invalid map key type: []interface {}"}, // {[]: -17} {"slice as map key", hexDecode("a1813030"), "cbor: invalid map key type: []interface {}"}, // {[-17]: -17} {"slice as map key", hexDecode("bfd1a388f730303030303030303030303030ff"), "cbor: invalid map key type: []interface {}"}, // {17({[undefined, -17, -17, -17, -17, -17, -17, -17]: -17, -17: -17}): -17}} {"byte slice as map key", hexDecode("8f3030a730304430303030303030303030303030303030303030303030303030303030"), "cbor: invalid map key type: []uint8"}, // [-17, -17, {-17: -17, h'30303030': -17}, -17, -17, -17, -17, -17, -17, -17, -17, -17, -17, -17, -17] {"map as map key", hexDecode("bf30a1a030ff"), "cbor: invalid map key type: map"}, // {-17: {{}: -17}}, empty map as map key {"map as map key", hexDecode("bfb0303030303030303030303030303030303030303030303030303030303030303030ff"), "cbor: invalid map key type: map"}, // {{-17: -17}: -17}, map as key {"tagged slice as map key", hexDecode("a1c84c30303030303030303030303030"), "cbor: invalid map key type: cbor.Tag"}, // {8(h'303030303030303030303030'): -17} {"nested-tagged slice as map key", hexDecode("a33030306430303030d1cb4030"), "cbor: invalid map key type: cbor.Tag"}, // {-17: "0000", 17(11(h'')): -17} {"big.Int as map key", hexDecode("a13bbd3030303030303030"), "cbor: invalid map key type: big.Int"}, // {-13632449055575519281: -17} {"tagged big.Int as map key", hexDecode("a1c24901000000000000000030"), "cbor: invalid map key type: big.Int"}, // {18446744073709551616: -17} {"tagged big.Int as map key", hexDecode("a1c34901000000000000000030"), "cbor: invalid map key type: big.Int"}, //{-18446744073709551617: -17} } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { var v interface{} if err := Unmarshal(tc.cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want %q", tc.cborData, tc.wantErrorMsg) } else if !strings.Contains(err.Error(), tc.wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } if _, ok := v.(map[interface{}]interface{}); ok { var v map[interface{}]interface{} if err := Unmarshal(tc.cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want %q", tc.cborData, tc.wantErrorMsg) } else if !strings.Contains(err.Error(), tc.wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } } }) } } func TestMapKeyNaN(t *testing.T) { // Data is generating by go-fuzz. cborData := hexDecode("b0303030303030303030303030303030303038303030faffff30303030303030303030303030") // {-17: -17, NaN: -17} var intf interface{} if err := Unmarshal(cborData, &intf); err != nil { t.Fatalf("Unmarshal(0x%x) returned error %v", cborData, err) } em, err := EncOptions{Sort: SortCanonical}.EncMode() if err != nil { t.Errorf("EncMode() returned an error %v", err) } if _, err := em.Marshal(intf); err != nil { t.Errorf("Marshal(%v) returned error %v", intf, err) } } func TestUnmarshalUndefinedElement(t *testing.T) { // Data is generating by go-fuzz. cborData := hexDecode("bfd1a388f730303030303030303030303030ff") // {17({[undefined, -17, -17, -17, -17, -17, -17, -17]: -17, -17: -17}): -17} var intf interface{} wantErrorMsg := "invalid map key type" if err := Unmarshal(cborData, &intf); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want error containing substring %q", cborData, wantErrorMsg) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing substring %q", cborData, err.Error(), wantErrorMsg) } } func TestMapKeyNil(t *testing.T) { testData := [][]byte{ hexDecode("a1f630"), // {null: -17} } want := map[interface{}]interface{}{nil: int64(-17)} for _, data := range testData { var intf interface{} if err := Unmarshal(data, &intf); err != nil { t.Fatalf("Unmarshal(0x%x) returned error %v", data, err) } else if !reflect.DeepEqual(intf, want) { t.Errorf("Unmarshal(0x%x) returned %+v, want %+v", data, intf, want) } if _, err := Marshal(intf); err != nil { t.Errorf("Marshal(%v) returned error %v", intf, err) } var v map[interface{}]interface{} if err := Unmarshal(data, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", data, err) } else if !reflect.DeepEqual(v, want) { t.Errorf("Unmarshal(0x%x) returned %+v, want %+v", data, v, want) } if _, err := Marshal(v); err != nil { t.Errorf("Marshal(%v) returned error %v", v, err) } } } func TestDecodeTime(t *testing.T) { testCases := []struct { name string cborRFC3339Time []byte cborUnixTime []byte wantTime time.Time }{ // Decoding CBOR null/defined to time.Time is no-op. See TestUnmarshalNil. { name: "NaN", cborRFC3339Time: hexDecode("f97e00"), cborUnixTime: hexDecode("f97e00"), wantTime: time.Time{}, }, { name: "positive infinity", cborRFC3339Time: hexDecode("f97c00"), cborUnixTime: hexDecode("f97c00"), wantTime: time.Time{}, }, { name: "negative infinity", cborRFC3339Time: hexDecode("f9fc00"), cborUnixTime: hexDecode("f9fc00"), wantTime: time.Time{}, }, { name: "time without fractional seconds", // positive integer cborRFC3339Time: hexDecode("74323031332d30332d32315432303a30343a30305a"), cborUnixTime: hexDecode("1a514b67b0"), wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"), }, { name: "time with fractional seconds", // float cborRFC3339Time: hexDecode("7819313937302d30312d30315432313a34363a34302d30363a3030"), cborUnixTime: hexDecode("fa47c35000"), wantTime: parseTime(time.RFC3339Nano, "1970-01-01T21:46:40-06:00"), }, { name: "time with fractional seconds", // float cborRFC3339Time: hexDecode("76323031332d30332d32315432303a30343a30302e355a"), cborUnixTime: hexDecode("fb41d452d9ec200000"), wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00.5Z"), }, { name: "time before January 1, 1970 UTC without fractional seconds", // negative integer cborRFC3339Time: hexDecode("74313936392d30332d32315432303a30343a30305a"), cborUnixTime: hexDecode("3a0177f2cf"), wantTime: parseTime(time.RFC3339Nano, "1969-03-21T20:04:00Z"), }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { tm := time.Now() if err := Unmarshal(tc.cborRFC3339Time, &tm); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborRFC3339Time, err) } else if !tc.wantTime.Equal(tm) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborRFC3339Time, tm, tm, tc.wantTime, tc.wantTime) } tm = time.Now() if err := Unmarshal(tc.cborUnixTime, &tm); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborUnixTime, err) } else if !tc.wantTime.Equal(tm) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborUnixTime, tm, tm, tc.wantTime, tc.wantTime) } }) } } func TestDecodeTimeWithTag(t *testing.T) { testCases := []struct { name string cborRFC3339Time []byte cborUnixTime []byte wantTime time.Time }{ { name: "time without fractional seconds", // positive integer cborRFC3339Time: hexDecode("c074323031332d30332d32315432303a30343a30305a"), cborUnixTime: hexDecode("c11a514b67b0"), wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"), }, { name: "time with fractional seconds", // float cborRFC3339Time: hexDecode("c076323031332d30332d32315432303a30343a30302e355a"), cborUnixTime: hexDecode("c1fb41d452d9ec200000"), wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00.5Z"), }, { name: "time before January 1, 1970 UTC without fractional seconds", // negative integer cborRFC3339Time: hexDecode("c074313936392d30332d32315432303a30343a30305a"), cborUnixTime: hexDecode("c13a0177f2cf"), wantTime: parseTime(time.RFC3339Nano, "1969-03-21T20:04:00Z"), }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { tm := time.Now() if err := Unmarshal(tc.cborRFC3339Time, &tm); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborRFC3339Time, err) } else if !tc.wantTime.Equal(tm) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborRFC3339Time, tm, tm, tc.wantTime, tc.wantTime) } tm = time.Now() if err := Unmarshal(tc.cborUnixTime, &tm); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborUnixTime, err) } else if !tc.wantTime.Equal(tm) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborUnixTime, tm, tm, tc.wantTime, tc.wantTime) } var v interface{} if err := Unmarshal(tc.cborRFC3339Time, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborRFC3339Time, err) } else if tm, ok := v.(time.Time); !ok || !tc.wantTime.Equal(tm) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborRFC3339Time, v, v, tc.wantTime, tc.wantTime) } v = nil if err := Unmarshal(tc.cborUnixTime, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborUnixTime, err) } else if tm, ok := v.(time.Time); !ok || !tc.wantTime.Equal(tm) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborUnixTime, v, v, tc.wantTime, tc.wantTime) } }) } } func TestDecodeTimeError(t *testing.T) { testCases := []struct { name string cborData []byte wantErrorMsg string }{ { name: "invalid RFC3339 time string", cborData: hexDecode("7f657374726561646d696e67ff"), wantErrorMsg: "cbor: cannot set streaming for time.Time", }, { name: "byte string data cannot be decoded into time.Time", cborData: hexDecode("4f013030303030303030e03031ed3030"), wantErrorMsg: "cbor: cannot unmarshal byte string into Go value of type time.Time", }, { name: "bool cannot be decoded into time.Time", cborData: hexDecode("f4"), wantErrorMsg: "cbor: cannot unmarshal primitives into Go value of type time.Time", }, { name: "invalid UTF-8 string", cborData: hexDecode("7f62e6b061b4ff"), wantErrorMsg: "cbor: invalid UTF-8 string", }, { name: "negative integer overflow", cborData: hexDecode("3bffffffffffffffff"), wantErrorMsg: "cbor: cannot unmarshal negative integer into Go value of type time.Time", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { tm := time.Now() if err := Unmarshal(tc.cborData, &tm); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want error msg %q", tc.cborData, tc.wantErrorMsg) } else if !strings.Contains(err.Error(), tc.wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } }) } } func TestDecodeInvalidTagTime(t *testing.T) { typeTimeSlice := reflect.TypeOf([]time.Time{}) testCases := []struct { name string cborData []byte decodeToTypes []reflect.Type wantErrorMsg string }{ { name: "Tag 0 with invalid RFC3339 time string", cborData: hexDecode("c07f657374726561646d696e67ff"), decodeToTypes: []reflect.Type{typeIntf, typeTime}, wantErrorMsg: "cbor: cannot set streaming for time.Time", }, { name: "Tag 0 with invalid UTF-8 string", cborData: hexDecode("c07f62e6b061b4ff"), decodeToTypes: []reflect.Type{typeIntf, typeTime}, wantErrorMsg: "cbor: invalid UTF-8 string", }, { name: "Tag 0 with integer content", cborData: hexDecode("c01a514b67b0"), decodeToTypes: []reflect.Type{typeIntf, typeTime}, wantErrorMsg: "cbor: tag number 0 must be followed by text string, got positive integer", }, { name: "Tag 0 with byte string content", cborData: hexDecode("c04f013030303030303030e03031ed3030"), decodeToTypes: []reflect.Type{typeIntf, typeTime}, wantErrorMsg: "cbor: tag number 0 must be followed by text string, got byte string", }, { name: "Tag 0 with integer content as array element", cborData: hexDecode("81c01a514b67b0"), decodeToTypes: []reflect.Type{typeIntf, typeTimeSlice}, wantErrorMsg: "cbor: tag number 0 must be followed by text string, got positive integer", }, { name: "Tag 1 with negative integer overflow", cborData: hexDecode("c13bffffffffffffffff"), decodeToTypes: []reflect.Type{typeIntf, typeTime}, wantErrorMsg: "cbor: cannot unmarshal tag into Go value of type time.Time", }, { name: "Tag 1 with string content", cborData: hexDecode("c174323031332d30332d32315432303a30343a30305a"), decodeToTypes: []reflect.Type{typeIntf, typeTime}, wantErrorMsg: "cbor: tag number 1 must be followed by integer or floating-point number, got UTF-8 text string", }, { name: "Tag 1 with simple value", cborData: hexDecode("d801f6"), // 1(null) decodeToTypes: []reflect.Type{typeIntf, typeTime}, wantErrorMsg: "cbor: tag number 1 must be followed by integer or floating-point number, got primitive", }, { name: "Tag 1 with string content as array element", cborData: hexDecode("81c174323031332d30332d32315432303a30343a30305a"), decodeToTypes: []reflect.Type{typeIntf, typeTimeSlice}, wantErrorMsg: "cbor: tag number 1 must be followed by integer or floating-point number, got UTF-8 text string", }, } dm, _ := DecOptions{TimeTag: DecTagOptional}.DecMode() for _, tc := range testCases { for _, decodeToType := range tc.decodeToTypes { t.Run(tc.name+" decode to "+decodeToType.String(), func(t *testing.T) { v := reflect.New(decodeToType) if err := dm.Unmarshal(tc.cborData, v.Interface()); err == nil { t.Errorf("Unmarshal(0x%x) didn't return error, want error msg %q", tc.cborData, tc.wantErrorMsg) } else if !strings.Contains(err.Error(), tc.wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", tc.cborData, err, tc.wantErrorMsg) } }) } } } func TestDecodeTag0Error(t *testing.T) { cborData := hexDecode("c01a514b67b0") // 0(1363896240) wantErrorMsg := "cbor: tag number 0 must be followed by text string, got positive integer" timeTagIgnoredDM, _ := DecOptions{TimeTag: DecTagIgnored}.DecMode() timeTagOptionalDM, _ := DecOptions{TimeTag: DecTagOptional}.DecMode() timeTagRequiredDM, _ := DecOptions{TimeTag: DecTagRequired}.DecMode() testCases := []struct { name string dm DecMode }{ {name: "DecTagIgnored", dm: timeTagIgnoredDM}, {name: "DecTagOptional", dm: timeTagOptionalDM}, {name: "DecTagRequired", dm: timeTagRequiredDM}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { // Decode to interface{} var v interface{} if err := tc.dm.Unmarshal(cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return error, want error msg %q", cborData, wantErrorMsg) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", cborData, err, wantErrorMsg) } // Decode to time.Time var tm time.Time if err := tc.dm.Unmarshal(cborData, &tm); err == nil { t.Errorf("Unmarshal(0x%x) didn't return error, want error msg %q", cborData, wantErrorMsg) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", cborData, err, wantErrorMsg) } // Decode to uint64 var ui uint64 if err := tc.dm.Unmarshal(cborData, &ui); err == nil { t.Errorf("Unmarshal(0x%x) didn't return error, want error msg %q", cborData, wantErrorMsg) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", cborData, err, wantErrorMsg) } }) } } func TestDecodeTag1Error(t *testing.T) { cborData := hexDecode("c174323031332d30332d32315432303a30343a30305a") // 1("2013-03-21T20:04:00Z") wantErrorMsg := "cbor: tag number 1 must be followed by integer or floating-point number, got UTF-8 text string" timeTagIgnoredDM, _ := DecOptions{TimeTag: DecTagIgnored}.DecMode() timeTagOptionalDM, _ := DecOptions{TimeTag: DecTagOptional}.DecMode() timeTagRequiredDM, _ := DecOptions{TimeTag: DecTagRequired}.DecMode() testCases := []struct { name string dm DecMode }{ {name: "DecTagIgnored", dm: timeTagIgnoredDM}, {name: "DecTagOptional", dm: timeTagOptionalDM}, {name: "DecTagRequired", dm: timeTagRequiredDM}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { // Decode to interface{} var v interface{} if err := tc.dm.Unmarshal(cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return error, want error msg %q", cborData, wantErrorMsg) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", cborData, err, wantErrorMsg) } // Decode to time.Time var tm time.Time if err := tc.dm.Unmarshal(cborData, &tm); err == nil { t.Errorf("Unmarshal(0x%x) didn't return error, want error msg %q", cborData, wantErrorMsg) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", cborData, err, wantErrorMsg) } // Decode to string var s string if err := tc.dm.Unmarshal(cborData, &s); err == nil { t.Errorf("Unmarshal(0x%x) didn't return error, want error msg %q", cborData, wantErrorMsg) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", cborData, err, wantErrorMsg) } }) } } func TestDecodeTimeStreaming(t *testing.T) { // Decoder decodes from mixed invalid and valid time. testCases := []struct { cborData []byte wantErrorMsg string wantObj time.Time }{ { cborData: hexDecode("c07f62e6b061b4ff"), wantErrorMsg: "cbor: invalid UTF-8 string", }, { cborData: hexDecode("c074323031332d30332d32315432303a30343a30305a"), wantObj: time.Date(2013, 3, 21, 20, 4, 0, 0, time.UTC), }, { cborData: hexDecode("c01a514b67b0"), wantErrorMsg: "cbor: tag number 0 must be followed by text string, got positive integer", }, { cborData: hexDecode("c074323031332d30332d32315432303a30343a30305a"), wantObj: time.Date(2013, 3, 21, 20, 4, 0, 0, time.UTC), }, { cborData: hexDecode("c13bffffffffffffffff"), wantErrorMsg: "cbor: cannot unmarshal tag into Go value of type time.Time", }, { cborData: hexDecode("c11a514b67b0"), wantObj: time.Date(2013, 3, 21, 20, 4, 0, 0, time.UTC), }, { cborData: hexDecode("c174323031332d30332d32315432303a30343a30305a"), wantErrorMsg: "tag number 1 must be followed by integer or floating-point number, got UTF-8 text string", }, { cborData: hexDecode("c11a514b67b0"), wantObj: time.Date(2013, 3, 21, 20, 4, 0, 0, time.UTC), }, } // Data is a mixed stream of valid and invalid time data var cborData []byte for _, tc := range testCases { cborData = append(cborData, tc.cborData...) } dm, _ := DecOptions{TimeTag: DecTagOptional}.DecMode() dec := dm.NewDecoder(bytes.NewReader(cborData)) for _, tc := range testCases { var v interface{} err := dec.Decode(&v) if tc.wantErrorMsg != "" { if err == nil { t.Errorf("Unmarshal(0x%x) didn't return error, want error msg %q", tc.cborData, tc.wantErrorMsg) } else if !strings.Contains(err.Error(), tc.wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error msg %q, want %q", tc.cborData, err, tc.wantErrorMsg) } } else { tm, ok := v.(time.Time) if !ok { t.Errorf("Unmarshal(0x%x) returned %s (%T), want time.Time", tc.cborData, v, v) } if !tc.wantObj.Equal(tm) { t.Errorf("Unmarshal(0x%x) returned %s, want %s", tc.cborData, tm, tc.wantObj) } } } dec = dm.NewDecoder(bytes.NewReader(cborData)) for _, tc := range testCases { var tm time.Time err := dec.Decode(&tm) if tc.wantErrorMsg != "" { if err == nil { t.Errorf("Unmarshal(0x%x) did't return error, want error msg %q", tc.cborData, tc.wantErrorMsg) } else if !strings.Contains(err.Error(), tc.wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error msg %q, want %q", tc.cborData, err, tc.wantErrorMsg) } } else { if !tc.wantObj.Equal(tm) { t.Errorf("Unmarshal(0x%x) returned %s, want %s", tc.cborData, tm, tc.wantObj) } } } } func TestDecTimeTagOption(t *testing.T) { timeTagIgnoredDecMode, _ := DecOptions{TimeTag: DecTagIgnored}.DecMode() timeTagOptionalDecMode, _ := DecOptions{TimeTag: DecTagOptional}.DecMode() timeTagRequiredDecMode, _ := DecOptions{TimeTag: DecTagRequired}.DecMode() testCases := []struct { name string cborRFC3339Time []byte cborUnixTime []byte decMode DecMode wantTime time.Time wantErrorMsg string }{ // not-tagged time CBOR data { name: "not-tagged data with DecTagIgnored option", cborRFC3339Time: hexDecode("74323031332d30332d32315432303a30343a30305a"), cborUnixTime: hexDecode("1a514b67b0"), decMode: timeTagIgnoredDecMode, wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"), }, { name: "not-tagged data with timeTagOptionalDecMode option", cborRFC3339Time: hexDecode("74323031332d30332d32315432303a30343a30305a"), cborUnixTime: hexDecode("1a514b67b0"), decMode: timeTagOptionalDecMode, wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"), }, { name: "not-tagged data with timeTagRequiredDecMode option", cborRFC3339Time: hexDecode("74323031332d30332d32315432303a30343a30305a"), cborUnixTime: hexDecode("1a514b67b0"), decMode: timeTagRequiredDecMode, wantErrorMsg: "expect CBOR tag value", }, // tagged time CBOR data { name: "tagged data with timeTagIgnoredDecMode option", cborRFC3339Time: hexDecode("c074323031332d30332d32315432303a30343a30305a"), cborUnixTime: hexDecode("c11a514b67b0"), decMode: timeTagIgnoredDecMode, wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"), }, { name: "tagged data with timeTagOptionalDecMode option", cborRFC3339Time: hexDecode("c074323031332d30332d32315432303a30343a30305a"), cborUnixTime: hexDecode("c11a514b67b0"), decMode: timeTagOptionalDecMode, wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"), }, { name: "tagged data with timeTagRequiredDecMode option", cborRFC3339Time: hexDecode("c074323031332d30332d32315432303a30343a30305a"), cborUnixTime: hexDecode("c11a514b67b0"), decMode: timeTagRequiredDecMode, wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"), }, // mis-tagged time CBOR data { name: "mis-tagged data with timeTagIgnoredDecMode option", cborRFC3339Time: hexDecode("c8c974323031332d30332d32315432303a30343a30305a"), cborUnixTime: hexDecode("c8c91a514b67b0"), decMode: timeTagIgnoredDecMode, wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"), }, { name: "mis-tagged data with timeTagOptionalDecMode option", cborRFC3339Time: hexDecode("c8c974323031332d30332d32315432303a30343a30305a"), cborUnixTime: hexDecode("c8c91a514b67b0"), decMode: timeTagOptionalDecMode, wantErrorMsg: "cbor: wrong tag number for time.Time, got 8, expect 0 or 1", }, { name: "mis-tagged data with timeTagRequiredDecMode option", cborRFC3339Time: hexDecode("c8c974323031332d30332d32315432303a30343a30305a"), cborUnixTime: hexDecode("c8c91a514b67b0"), decMode: timeTagRequiredDecMode, wantErrorMsg: "cbor: wrong tag number for time.Time, got 8, expect 0 or 1", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { tm := time.Now() err := tc.decMode.Unmarshal(tc.cborRFC3339Time, &tm) if tc.wantErrorMsg != "" { if err == nil { t.Errorf("Unmarshal(0x%x) didn't return error", tc.cborRFC3339Time) } else if !strings.Contains(err.Error(), tc.wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", tc.cborRFC3339Time, err.Error(), tc.wantErrorMsg) } } else { if !tc.wantTime.Equal(tm) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborRFC3339Time, tm, tm, tc.wantTime, tc.wantTime) } } tm = time.Now() err = tc.decMode.Unmarshal(tc.cborUnixTime, &tm) if tc.wantErrorMsg != "" { if err == nil { t.Errorf("Unmarshal(0x%x) didn't return error", tc.cborRFC3339Time) } else if !strings.Contains(err.Error(), tc.wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", tc.cborRFC3339Time, err.Error(), tc.wantErrorMsg) } } else { if !tc.wantTime.Equal(tm) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborRFC3339Time, tm, tm, tc.wantTime, tc.wantTime) } } }) } } func TestUnmarshalStructTag1(t *testing.T) { type strc struct { A string `cbor:"a"` B string `cbor:"b"` C string `cbor:"c"` } want := strc{ A: "A", B: "B", C: "C", } cborData := hexDecode("a3616161416162614261636143") // {"a":"A", "b":"B", "c":"C"} var v strc if err := Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if !reflect.DeepEqual(v, want) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, want, want) } } func TestUnmarshalStructTag2(t *testing.T) { type strc struct { A string `json:"a"` B string `json:"b"` C string `json:"c"` } want := strc{ A: "A", B: "B", C: "C", } cborData := hexDecode("a3616161416162614261636143") // {"a":"A", "b":"B", "c":"C"} var v strc if err := Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if !reflect.DeepEqual(v, want) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, want, want) } } func TestUnmarshalStructTag3(t *testing.T) { type strc struct { A string `json:"x" cbor:"a"` B string `json:"y" cbor:"b"` C string `json:"z"` } want := strc{ A: "A", B: "B", C: "C", } cborData := hexDecode("a36161614161626142617a6143") // {"a":"A", "b":"B", "z":"C"} var v strc if err := Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if !reflect.DeepEqual(v, want) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, v, v, want, want) } } func TestUnmarshalStructTag4(t *testing.T) { type strc struct { A string `json:"x" cbor:"a"` B string `json:"y" cbor:"b"` C string `json:"-"` } want := strc{ A: "A", B: "B", } cborData := hexDecode("a3616161416162614261636143") // {"a":"A", "b":"B", "c":"C"} var v strc if err := Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if !reflect.DeepEqual(v, want) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, v, v, want, want) } } type number uint64 func (n number) MarshalBinary() (data []byte, err error) { if n == 0 { return []byte{}, nil } data = make([]byte, 8) binary.BigEndian.PutUint64(data, uint64(n)) return } func (n *number) UnmarshalBinary(data []byte) (err error) { if len(data) == 0 { *n = 0 return nil } if len(data) != 8 { return errors.New("number:UnmarshalBinary: invalid length") } *n = number(binary.BigEndian.Uint64(data)) return } type stru struct { a, b, c string } func (s *stru) MarshalBinary() ([]byte, error) { if s.a == "" && s.b == "" && s.c == "" { return []byte{}, nil } return []byte(fmt.Sprintf("%s,%s,%s", s.a, s.b, s.c)), nil } func (s *stru) UnmarshalBinary(data []byte) (err error) { if len(data) == 0 { s.a, s.b, s.c = "", "", "" return nil } ss := strings.Split(string(data), ",") if len(ss) != 3 { return errors.New("stru:UnmarshalBinary: invalid element count") } s.a, s.b, s.c = ss[0], ss[1], ss[2] return } type marshalBinaryError string func (n marshalBinaryError) MarshalBinary() (data []byte, err error) { return nil, errors.New(string(n)) } func TestBinaryMarshalerUnmarshaler(t *testing.T) { testCases := []roundTripTest{ { name: "primitive obj", obj: number(1234567890), wantCborData: hexDecode("4800000000499602d2"), }, { name: "struct obj", obj: stru{a: "a", b: "b", c: "c"}, wantCborData: hexDecode("45612C622C63"), }, } em, _ := EncOptions{}.EncMode() dm, _ := DecOptions{}.DecMode() testRoundTrip(t, testCases, em, dm) } func TestBinaryUnmarshalerError(t *testing.T) { //nolint:dupl testCases := []struct { name string typ reflect.Type cborData []byte wantErrorMsg string }{ { name: "primitive type", typ: reflect.TypeOf(number(0)), cborData: hexDecode("44499602d2"), wantErrorMsg: "number:UnmarshalBinary: invalid length", }, { name: "struct type", typ: reflect.TypeOf(stru{}), cborData: hexDecode("47612C622C632C64"), wantErrorMsg: "stru:UnmarshalBinary: invalid element count", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { v := reflect.New(tc.typ) if err := Unmarshal(tc.cborData, v.Interface()); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want error msg %q", tc.cborData, tc.wantErrorMsg) } else if err.Error() != tc.wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } }) } } func TestBinaryMarshalerError(t *testing.T) { wantErrorMsg := "MarshalBinary: error" v := marshalBinaryError(wantErrorMsg) if _, err := Marshal(v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want error msg %q", v, wantErrorMsg) } else if err.Error() != wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", v, err.Error(), wantErrorMsg) } } type number2 uint64 func (n number2) MarshalCBOR() (data []byte, err error) { m := map[string]uint64{"num": uint64(n)} return Marshal(m) } func (n *number2) UnmarshalCBOR(data []byte) (err error) { var v map[string]uint64 if err := Unmarshal(data, &v); err != nil { return err } *n = number2(v["num"]) return nil } type stru2 struct { a, b, c string } func (s *stru2) MarshalCBOR() ([]byte, error) { v := []string{s.a, s.b, s.c} return Marshal(v) } func (s *stru2) UnmarshalCBOR(data []byte) (err error) { var v []string if err := Unmarshal(data, &v); err != nil { return err } if len(v) > 0 { s.a = v[0] } if len(v) > 1 { s.b = v[1] } if len(v) > 2 { s.c = v[2] } return nil } type marshalCBORError string func (n marshalCBORError) MarshalCBOR() (data []byte, err error) { return nil, errors.New(string(n)) } func TestMarshalerUnmarshaler(t *testing.T) { testCases := []roundTripTest{ { name: "primitive obj", obj: number2(1), wantCborData: hexDecode("a1636e756d01"), }, { name: "struct obj", obj: stru2{a: "a", b: "b", c: "c"}, wantCborData: hexDecode("83616161626163"), }, } em, _ := EncOptions{}.EncMode() dm, _ := DecOptions{}.DecMode() testRoundTrip(t, testCases, em, dm) } func TestUnmarshalerError(t *testing.T) { //nolint:dupl testCases := []struct { name string typ reflect.Type cborData []byte wantErrorMsg string }{ { name: "primitive type", typ: reflect.TypeOf(number2(0)), cborData: hexDecode("44499602d2"), wantErrorMsg: "cbor: cannot unmarshal byte string into Go value of type map[string]uint64", }, { name: "struct type", typ: reflect.TypeOf(stru2{}), cborData: hexDecode("47612C622C632C64"), wantErrorMsg: "cbor: cannot unmarshal byte string into Go value of type []string", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { v := reflect.New(tc.typ) if err := Unmarshal(tc.cborData, v.Interface()); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want error msg %q", tc.cborData, tc.wantErrorMsg) } else if err.Error() != tc.wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } }) } } func TestMarshalerError(t *testing.T) { wantErrorMsg := "MarshalCBOR: error" v := marshalCBORError(wantErrorMsg) if _, err := Marshal(v); err == nil { t.Errorf("Marshal(%+v) didn't return an error, want error msg %q", v, wantErrorMsg) } else if err.Error() != wantErrorMsg { t.Errorf("Marshal(%+v) returned error %q, want %q", v, err.Error(), wantErrorMsg) } } // Found at https://github.com/oasislabs/oasis-core/blob/master/go/common/cbor/cbor_test.go func TestOutOfMem1(t *testing.T) { cborData := []byte("\x9b\x00\x00000000") var f []byte if err := Unmarshal(cborData, &f); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } } // Found at https://github.com/oasislabs/oasis-core/blob/master/go/common/cbor/cbor_test.go func TestOutOfMem2(t *testing.T) { cborData := []byte("\x9b\x00\x00\x81112233") var f []byte if err := Unmarshal(cborData, &f); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } } // Found at https://github.com/cose-wg/Examples/tree/master/RFC8152 func TestCOSEExamples(t *testing.T) { cborData := [][]byte{ hexDecode("D8608443A10101A1054C02D1F7E6F26C43D4868D87CE582464F84D913BA60A76070A9A48F26E97E863E2852948658F0811139868826E89218A75715B818440A101225818DBD43C4E9D719C27C6275C67D628D493F090593DB8218F11818344A1013818A220A401022001215820B2ADD44368EA6D641F9CA9AF308B4079AEB519F11E9B8A55A600B21233E86E6822F40458246D65726961646F632E6272616E64796275636B406275636B6C616E642E6578616D706C6540"), hexDecode("D8628440A054546869732069732074686520636F6E74656E742E818343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A"), hexDecode("D8628440A054546869732069732074686520636F6E74656E742E828343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A8344A1013823A104581E62696C626F2E62616767696E7340686F626269746F6E2E6578616D706C65588400A2D28A7C2BDB1587877420F65ADF7D0B9A06635DD1DE64BB62974C863F0B160DD2163734034E6AC003B01E8705524C5C4CA479A952F0247EE8CB0B4FB7397BA08D009E0C8BF482270CC5771AA143966E5A469A09F613488030C5B07EC6D722E3835ADB5B2D8C44E95FFB13877DD2582866883535DE3BB03D01753F83AB87BB4F7A0297"), hexDecode("D8628440A1078343A10126A10442313158405AC05E289D5D0E1B0A7F048A5D2B643813DED50BC9E49220F4F7278F85F19D4A77D655C9D3B51E805A74B099E1E085AACD97FC29D72F887E8802BB6650CCEB2C54546869732069732074686520636F6E74656E742E818343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A"), hexDecode("D8628456A2687265736572766564F40281687265736572766564A054546869732069732074686520636F6E74656E742E818343A10126A10442313158403FC54702AA56E1B2CB20284294C9106A63F91BAC658D69351210A031D8FC7C5FF3E4BE39445B1A3E83E1510D1ACA2F2E8A7C081C7645042B18ABA9D1FAD1BD9C"), hexDecode("D28443A10126A10442313154546869732069732074686520636F6E74656E742E58408EB33E4CA31D1C465AB05AAC34CC6B23D58FEF5C083106C4D25A91AEF0B0117E2AF9A291AA32E14AB834DC56ED2A223444547E01F11D3B0916E5A4C345CACB36"), hexDecode("D8608443A10101A1054CC9CF4DF2FE6C632BF788641358247ADBE2709CA818FB415F1E5DF66F4E1A51053BA6D65A1A0C52A357DA7A644B8070A151B0818344A1013818A220A40102200121582098F50A4FF6C05861C8860D13A638EA56C3F5AD7590BBFBF054E1C7B4D91D628022F50458246D65726961646F632E6272616E64796275636B406275636B6C616E642E6578616D706C6540"), hexDecode("D8608443A1010AA1054D89F52F65A1C580933B5261A76C581C753548A19B1307084CA7B2056924ED95F2E3B17006DFE931B687B847818343A10129A2335061616262636364646565666667676868044A6F75722D73656372657440"), hexDecode("D8608443A10101A2054CC9CF4DF2FE6C632BF7886413078344A1013823A104581E62696C626F2E62616767696E7340686F626269746F6E2E6578616D706C65588400929663C8789BB28177AE28467E66377DA12302D7F9594D2999AFA5DFA531294F8896F2B6CDF1740014F4C7F1A358E3A6CF57F4ED6FB02FCF8F7AA989F5DFD07F0700A3A7D8F3C604BA70FA9411BD10C2591B483E1D2C31DE003183E434D8FBA18F17A4C7E3DFA003AC1CF3D30D44D2533C4989D3AC38C38B71481CC3430C9D65E7DDFF58247ADBE2709CA818FB415F1E5DF66F4E1A51053BA6D65A1A0C52A357DA7A644B8070A151B0818344A1013818A220A40102200121582098F50A4FF6C05861C8860D13A638EA56C3F5AD7590BBFBF054E1C7B4D91D628022F50458246D65726961646F632E6272616E64796275636B406275636B6C616E642E6578616D706C6540"), hexDecode("D8608443A10101A1054C02D1F7E6F26C43D4868D87CE582464F84D913BA60A76070A9A48F26E97E863E28529D8F5335E5F0165EEE976B4A5F6C6F09D818344A101381FA3225821706572656772696E2E746F6F6B407475636B626F726F7567682E6578616D706C650458246D65726961646F632E6272616E64796275636B406275636B6C616E642E6578616D706C6535420101581841E0D76F579DBD0D936A662D54D8582037DE2E366FDE1C62"), hexDecode("D08343A1010AA1054D89F52F65A1C580933B5261A78C581C5974E1B99A3A4CC09A659AA2E9E7FFF161D38CE71CB45CE460FFB569"), hexDecode("D08343A1010AA1064261A7581C252A8911D465C125B6764739700F0141ED09192DE139E053BD09ABCA"), hexDecode("D8618543A1010FA054546869732069732074686520636F6E74656E742E489E1226BA1F81B848818340A20125044A6F75722D73656372657440"), hexDecode("D8618543A10105A054546869732069732074686520636F6E74656E742E582081A03448ACD3D305376EAA11FB3FE416A955BE2CBE7EC96F012C994BC3F16A41818344A101381AA3225821706572656772696E2E746F6F6B407475636B626F726F7567682E6578616D706C650458246D65726961646F632E6272616E64796275636B406275636B6C616E642E6578616D706C653558404D8553E7E74F3C6A3A9DD3EF286A8195CBF8A23D19558CCFEC7D34B824F42D92BD06BD2C7F0271F0214E141FB779AE2856ABF585A58368B017E7F2A9E5CE4DB540"), hexDecode("D8618543A1010EA054546869732069732074686520636F6E74656E742E4836F5AFAF0BAB5D43818340A2012404582430313863306165352D346439622D343731622D626664362D6565663331346263373033375818711AB0DC2FC4585DCE27EFFA6781C8093EBA906F227B6EB0"), hexDecode("D8618543A10105A054546869732069732074686520636F6E74656E742E5820BF48235E809B5C42E995F2B7D5FA13620E7ED834E337F6AA43DF161E49E9323E828344A101381CA220A4010220032158420043B12669ACAC3FD27898FFBA0BCD2E6C366D53BC4DB71F909A759304ACFB5E18CDC7BA0B13FF8C7636271A6924B1AC63C02688075B55EF2D613574E7DC242F79C322F504581E62696C626F2E62616767696E7340686F626269746F6E2E6578616D706C655828339BC4F79984CDC6B3E6CE5F315A4C7D2B0AC466FCEA69E8C07DFBCA5BB1F661BC5F8E0DF9E3EFF58340A2012404582430313863306165352D346439622D343731622D626664362D65656633313462633730333758280B2C7CFCE04E98276342D6476A7723C090DFDD15F9A518E7736549E998370695E6D6A83B4AE507BB"), hexDecode("D18443A1010FA054546869732069732074686520636F6E74656E742E48726043745027214F"), } for _, d := range cborData { var v interface{} if err := Unmarshal(d, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", d, err) } } } func TestUnmarshalStructKeyAsIntError(t *testing.T) { type T1 struct { F1 int `cbor:"1,keyasint"` } cborData := hexDecode("a13bffffffffffffffff01") // {1: -18446744073709551616} var v T1 if err := Unmarshal(cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", cborData, err) } else if !strings.Contains(err.Error(), "cannot unmarshal") { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), "cannot unmarshal") } } func TestUnmarshalArrayToStruct(t *testing.T) { type T struct { _ struct{} `cbor:",toarray"` A int B int C int } testCases := []struct { name string cborData []byte }{ {"definite length array", hexDecode("83010203")}, {"indefinite length array", hexDecode("9f010203ff")}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { var v T if err := Unmarshal(tc.cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } }) } } func TestUnmarshalArrayToStructNoToArrayOptionError(t *testing.T) { type T struct { A int B int C int } cborData := hexDecode("8301020383010203") var v1 T wantT := T{} dec := NewDecoder(bytes.NewReader(cborData)) if err := dec.Decode(&v1); err == nil { t.Errorf("Decode(%+v) didn't return an error", v1) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Decode(%+v) returned wrong error type %T, want (*UnmarshalTypeError)", v1, err) } else if !strings.Contains(err.Error(), "cannot unmarshal") { t.Errorf("Decode(%+v) returned error %q, want error containing %q", err.Error(), v1, "cannot unmarshal") } if !reflect.DeepEqual(v1, wantT) { t.Errorf("Decode() = %+v (%T), want %+v (%T)", v1, v1, wantT, wantT) } var v2 []int want := []int{1, 2, 3} if err := dec.Decode(&v2); err != nil { t.Errorf("Decode() returned error %v", err) } if !reflect.DeepEqual(v2, want) { t.Errorf("Decode() = %+v (%T), want %+v (%T)", v2, v2, want, want) } } func TestUnmarshalNonArrayDataToStructToArray(t *testing.T) { type T struct { _ struct{} `cbor:",toarray"` A int B int C int } testCases := []struct { name string cborData []byte }{ {"CBOR positive int", hexDecode("00")}, // 0 {"CBOR negative int", hexDecode("20")}, // -1 {"CBOR byte string", hexDecode("4401020304")}, // h`01020304` {"CBOR text string", hexDecode("7f657374726561646d696e67ff")}, // streaming {"CBOR map", hexDecode("a3614101614202614303")}, // {"A": 1, "B": 2, "C": 3} {"CBOR bool", hexDecode("f5")}, // true {"CBOR float", hexDecode("fa7f7fffff")}, // 3.4028234663852886e+38 } wantT := T{} wantErrorMsg := "cannot unmarshal" for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { var v T if err := Unmarshal(tc.cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", tc.cborData) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", tc.cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", tc.cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(v, wantT) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", tc.cborData, v, v, wantT, wantT) } }) } } func TestUnmarshalArrayToStructWrongSizeError(t *testing.T) { type T struct { _ struct{} `cbor:",toarray"` A int B int } cborData := hexDecode("8301020383010203") var v1 T wantT := T{} dec := NewDecoder(bytes.NewReader(cborData)) if err := dec.Decode(&v1); err == nil { t.Errorf("Decode(%+v) didn't return an error", v1) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Decode(%+v) returned wrong error type %T, want (*UnmarshalTypeError)", v1, err) } else if !strings.Contains(err.Error(), "cannot unmarshal") { t.Errorf("Decode(%+v) returned error %q, want error containing %q", v1, err.Error(), "cannot unmarshal") } if !reflect.DeepEqual(v1, wantT) { t.Errorf("Decode() = %+v (%T), want %+v (%T)", v1, v1, wantT, wantT) } var v2 []int want := []int{1, 2, 3} if err := dec.Decode(&v2); err != nil { t.Errorf("Decode() returned error %v", err) } if !reflect.DeepEqual(v2, want) { t.Errorf("Decode() = %+v (%T), want %+v (%T)", v2, v2, want, want) } } func TestUnmarshalArrayToStructWrongFieldTypeError(t *testing.T) { type T struct { _ struct{} `cbor:",toarray"` A int B string C int } testCases := []struct { name string cborData []byte wantErrorMsg string wantV interface{} }{ // [1, 2, 3] {"wrong field type", hexDecode("83010203"), "cannot unmarshal", T{A: 1, C: 3}}, // [1, 0xfe, 3] {"invalid UTF-8 string", hexDecode("830161fe03"), invalidUTF8ErrorMsg, T{A: 1, C: 3}}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { var v T if err := Unmarshal(tc.cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", tc.cborData) } else if !strings.Contains(err.Error(), tc.wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", tc.cborData, err.Error(), tc.wantErrorMsg) } if !reflect.DeepEqual(v, tc.wantV) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", tc.cborData, v, v, tc.wantV, tc.wantV) } }) } } func TestUnmarshalArrayToStructCannotSetEmbeddedPointerError(t *testing.T) { type ( s1 struct { x int //nolint:unused,structcheck X int } S2 struct { y int //nolint:unused,structcheck Y int } S struct { _ struct{} `cbor:",toarray"` *s1 *S2 } ) cborData := []byte{0x82, 0x02, 0x04} // [2, 4] const wantErrorMsg = "cannot set embedded pointer to unexported struct" wantV := S{S2: &S2{Y: 4}} var v S err := Unmarshal(cborData, &v) if err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want error %q", cborData, wantErrorMsg) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(v, wantV) { t.Errorf("Decode() = %+v (%T), want %+v (%T)", v, v, wantV, wantV) } } func TestUnmarshalIntoSliceError(t *testing.T) { cborData := []byte{0x83, 0x61, 0x61, 0x61, 0xfe, 0x61, 0x62} // ["a", 0xfe, "b"] wantErrorMsg := invalidUTF8ErrorMsg var want interface{} // Unmarshal CBOR array into Go empty interface. var v1 interface{} want = []interface{}{"a", interface{}(nil), "b"} if err := Unmarshal(cborData, &v1); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want %q", cborData, wantErrorMsg) } else if err.Error() != wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(v1, want) { t.Errorf("Unmarshal(0x%x) = %v, want %v", cborData, v1, want) } // Unmarshal CBOR array into Go slice. var v2 []string want = []string{"a", "", "b"} if err := Unmarshal(cborData, &v2); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want %q", cborData, wantErrorMsg) } else if err.Error() != wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(v2, want) { t.Errorf("Unmarshal(0x%x) = %v, want %v", cborData, v2, want) } // Unmarshal CBOR array into Go array. var v3 [3]string want = [3]string{"a", "", "b"} if err := Unmarshal(cborData, &v3); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want %q", cborData, wantErrorMsg) } else if err.Error() != wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(v3, want) { t.Errorf("Unmarshal(0x%x) = %v, want %v", cborData, v3, want) } // Unmarshal CBOR array into populated Go slice. v4 := []string{"hello", "to", "you"} want = []string{"a", "to", "b"} if err := Unmarshal(cborData, &v4); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want %q", cborData, wantErrorMsg) } else if err.Error() != wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(v4, want) { t.Errorf("Unmarshal(0x%x) = %v, want %v", cborData, v4, want) } } func TestUnmarshalIntoMapError(t *testing.T) { cborData := [][]byte{ {0xa3, 0x61, 0x61, 0x61, 0x41, 0x61, 0xfe, 0x61, 0x43, 0x61, 0x62, 0x61, 0x42}, // {"a":"A", 0xfe: "C", "b":"B"} {0xa3, 0x61, 0x61, 0x61, 0x41, 0x61, 0x63, 0x61, 0xfe, 0x61, 0x62, 0x61, 0x42}, // {"a":"A", "c": 0xfe, "b":"B"} } wantErrorMsg := invalidUTF8ErrorMsg var want interface{} for _, data := range cborData { // Unmarshal CBOR map into Go empty interface. var v1 interface{} want = map[interface{}]interface{}{"a": "A", "b": "B"} if err := Unmarshal(data, &v1); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want %q", data, wantErrorMsg) } else if err.Error() != wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", data, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(v1, want) { t.Errorf("Unmarshal(0x%x) = %v, want %v", data, v1, want) } // Unmarshal CBOR map into Go map[interface{}]interface{}. var v2 map[interface{}]interface{} want = map[interface{}]interface{}{"a": "A", "b": "B"} if err := Unmarshal(data, &v2); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want %q", data, wantErrorMsg) } else if err.Error() != wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", data, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(v2, want) { t.Errorf("Unmarshal(0x%x) = %v, want %v", data, v2, want) } // Unmarshal CBOR array into Go map[string]string. var v3 map[string]string want = map[string]string{"a": "A", "b": "B"} if err := Unmarshal(data, &v3); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want %q", data, wantErrorMsg) } else if err.Error() != wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", data, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(v3, want) { t.Errorf("Unmarshal(0x%x) = %v, want %v", data, v3, want) } // Unmarshal CBOR array into populated Go map[string]string. v4 := map[string]string{"c": "D"} want = map[string]string{"a": "A", "b": "B", "c": "D"} if err := Unmarshal(data, &v4); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want %q", data, wantErrorMsg) } else if err.Error() != wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", data, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(v4, want) { t.Errorf("Unmarshal(0x%x) = %v, want %v", data, v4, want) } } } func TestStructToArrayError(t *testing.T) { type coseHeader struct { Alg int `cbor:"1,keyasint,omitempty"` Kid []byte `cbor:"4,keyasint,omitempty"` IV []byte `cbor:"5,keyasint,omitempty"` } type nestedCWT struct { _ struct{} `cbor:",toarray"` Protected []byte Unprotected coseHeader Ciphertext []byte } for _, tc := range []struct { cborData []byte wantErrorMsg string }{ // [-17, [-17, -17], -17] {hexDecode("9f3082303030ff"), "cbor: cannot unmarshal negative integer into Go struct field cbor.nestedCWT.Protected of type []uint8"}, // [[], [], ["\x930000", -17]] {hexDecode("9f9fff9fff9f65933030303030ffff"), "cbor: cannot unmarshal array into Go struct field cbor.nestedCWT.Unprotected of type cbor.coseHeader (cannot decode CBOR array to struct without toarray option)"}, } { var v nestedCWT if err := Unmarshal(tc.cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want %q", tc.cborData, tc.wantErrorMsg) } else if err.Error() != tc.wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } } } func TestStructKeyAsIntError(t *testing.T) { type claims struct { Iss string `cbor:"1,keyasint"` Sub string `cbor:"2,keyasint"` Aud string `cbor:"3,keyasint"` Exp float64 `cbor:"4,keyasint"` Nbf float64 `cbor:"5,keyasint"` Iat float64 `cbor:"6,keyasint"` Cti []byte `cbor:"7,keyasint"` } cborData := hexDecode("bf0783e662f03030ff") // {7: [simple(6), "\xF00", -17]} wantErrorMsg := invalidUTF8ErrorMsg wantV := claims{Cti: []byte{6, 0, 0}} var v claims if err := Unmarshal(cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want %q", cborData, wantErrorMsg) } else if err.Error() != wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(v, wantV) { t.Errorf("Unmarshal(0x%x) = %v, want %v", cborData, v, wantV) } } func TestUnmarshalToNotNilInterface(t *testing.T) { cborData := hexDecode("83010203") // []uint64{1, 2, 3} s := "hello" //nolint:goconst var v interface{} = s // Unmarshal() sees v as type inteface{} and sets CBOR data as default Go type. s is unmodified. Same behavior as encoding/json. wantV := []interface{}{uint64(1), uint64(2), uint64(3)} if err := Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if !reflect.DeepEqual(v, wantV) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, wantV, wantV) } else if s != "hello" { t.Errorf("Unmarshal(0x%x) modified s %q", cborData, s) } } func TestDecOptions(t *testing.T) { opts1 := DecOptions{ TimeTag: DecTagRequired, DupMapKey: DupMapKeyEnforcedAPF, IndefLength: IndefLengthForbidden, MaxNestedLevels: 100, MaxMapPairs: 101, MaxArrayElements: 102, TagsMd: TagsForbidden, IntDec: IntDecConvertSigned, ExtraReturnErrors: ExtraDecErrorUnknownField, } dm, err := opts1.DecMode() if err != nil { t.Errorf("DecMode() returned an error %v", err) } else { opts2 := dm.DecOptions() if !reflect.DeepEqual(opts1, opts2) { t.Errorf("DecOptions->DecMode->DecOptions returned different values: %v, %v", opts1, opts2) } } } type roundTripTest struct { name string obj interface{} wantCborData []byte } func testRoundTrip(t *testing.T, testCases []roundTripTest, em EncMode, dm DecMode) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { b, err := em.Marshal(tc.obj) if err != nil { t.Errorf("Marshal(%+v) returned error %v", tc.obj, err) } if !bytes.Equal(b, tc.wantCborData) { t.Errorf("Marshal(%+v) = 0x%x, want 0x%x", tc.obj, b, tc.wantCborData) } v := reflect.New(reflect.TypeOf(tc.obj)) if err := dm.Unmarshal(b, v.Interface()); err != nil { t.Errorf("Unmarshal() returned error %v", err) } if !reflect.DeepEqual(tc.obj, v.Elem().Interface()) { t.Errorf("Marshal-Unmarshal returned different values: %v, %v", tc.obj, v.Elem().Interface()) } }) } } func TestDecModeInvalidTimeTag(t *testing.T) { wantErrorMsg := "cbor: invalid TimeTag 101" _, err := DecOptions{TimeTag: 101}.DecMode() if err == nil { t.Errorf("DecMode() didn't return an error") } else if err.Error() != wantErrorMsg { t.Errorf("DecMode() returned error %q, want %q", err.Error(), wantErrorMsg) } } func TestDecModeInvalidDuplicateMapKey(t *testing.T) { wantErrorMsg := "cbor: invalid DupMapKey 101" _, err := DecOptions{DupMapKey: 101}.DecMode() if err == nil { t.Errorf("DecMode() didn't return an error") } else if err.Error() != wantErrorMsg { t.Errorf("DecMode() returned error %q, want %q", err.Error(), wantErrorMsg) } } func TestDecModeDefaultMaxNestedLevel(t *testing.T) { dm, err := DecOptions{}.DecMode() if err != nil { t.Errorf("DecMode() returned error %v", err) } else { maxNestedLevels := dm.DecOptions().MaxNestedLevels if maxNestedLevels != 32 { t.Errorf("DecOptions().MaxNestedLevels = %d, want %v", maxNestedLevels, 32) } } } func TestDecModeInvalidMaxNestedLevel(t *testing.T) { testCases := []struct { name string opts DecOptions wantErrorMsg string }{ { name: "MaxNestedLevels < 4", opts: DecOptions{MaxNestedLevels: 1}, wantErrorMsg: "cbor: invalid MaxNestedLevels 1 (range is [4, 256])", }, { name: "MaxNestedLevels > 256", opts: DecOptions{MaxNestedLevels: 257}, wantErrorMsg: "cbor: invalid MaxNestedLevels 257 (range is [4, 256])", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { _, err := tc.opts.DecMode() if err == nil { t.Errorf("DecMode() didn't return an error") } else if err.Error() != tc.wantErrorMsg { t.Errorf("DecMode() returned error %q, want %q", err.Error(), tc.wantErrorMsg) } }) } } func TestDecModeDefaultMaxMapPairs(t *testing.T) { dm, err := DecOptions{}.DecMode() if err != nil { t.Errorf("DecMode() returned error %v", err) } else { maxMapPairs := dm.DecOptions().MaxMapPairs if maxMapPairs != defaultMaxMapPairs { t.Errorf("DecOptions().MaxMapPairs = %d, want %v", maxMapPairs, defaultMaxMapPairs) } } } func TestDecModeInvalidMaxMapPairs(t *testing.T) { testCases := []struct { name string opts DecOptions wantErrorMsg string }{ { name: "MaxMapPairs < 16", opts: DecOptions{MaxMapPairs: 1}, wantErrorMsg: "cbor: invalid MaxMapPairs 1 (range is [16, 2147483647])", }, { name: "MaxMapPairs > 2147483647", opts: DecOptions{MaxMapPairs: 2147483648}, wantErrorMsg: "cbor: invalid MaxMapPairs 2147483648 (range is [16, 2147483647])", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { _, err := tc.opts.DecMode() if err == nil { t.Errorf("DecMode() didn't return an error") } else if err.Error() != tc.wantErrorMsg { t.Errorf("DecMode() returned error %q, want %q", err.Error(), tc.wantErrorMsg) } }) } } func TestDecModeDefaultMaxArrayElements(t *testing.T) { dm, err := DecOptions{}.DecMode() if err != nil { t.Errorf("DecMode() returned error %v", err) } else { maxArrayElements := dm.DecOptions().MaxArrayElements if maxArrayElements != defaultMaxArrayElements { t.Errorf("DecOptions().MaxArrayElementsr = %d, want %v", maxArrayElements, defaultMaxArrayElements) } } } func TestDecModeInvalidMaxArrayElements(t *testing.T) { testCases := []struct { name string opts DecOptions wantErrorMsg string }{ { name: "MaxArrayElements < 16", opts: DecOptions{MaxArrayElements: 1}, wantErrorMsg: "cbor: invalid MaxArrayElements 1 (range is [16, 2147483647])", }, { name: "MaxArrayElements > 2147483647", opts: DecOptions{MaxArrayElements: 2147483648}, wantErrorMsg: "cbor: invalid MaxArrayElements 2147483648 (range is [16, 2147483647])", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { _, err := tc.opts.DecMode() if err == nil { t.Errorf("DecMode() didn't return an error") } else if err.Error() != tc.wantErrorMsg { t.Errorf("DecMode() returned error %q, want %q", err.Error(), tc.wantErrorMsg) } }) } } func TestDecModeInvalidIndefiniteLengthMode(t *testing.T) { wantErrorMsg := "cbor: invalid IndefLength 101" _, err := DecOptions{IndefLength: 101}.DecMode() if err == nil { t.Errorf("DecMode() didn't return an error") } else if err.Error() != wantErrorMsg { t.Errorf("DecMode() returned error %q, want %q", err.Error(), wantErrorMsg) } } func TestDecModeInvalidTagsMode(t *testing.T) { wantErrorMsg := "cbor: invalid TagsMd 101" _, err := DecOptions{TagsMd: 101}.DecMode() if err == nil { t.Errorf("DecMode() didn't return an error") } else if err.Error() != wantErrorMsg { t.Errorf("DecMode() returned error %q, want %q", err.Error(), wantErrorMsg) } } func TestUnmarshalStructKeyAsIntNumError(t *testing.T) { type T1 struct { F1 int `cbor:"a,keyasint"` } type T2 struct { F1 int `cbor:"-18446744073709551616,keyasint"` } testCases := []struct { name string cborData []byte obj interface{} wantErrorMsg string }{ { name: "string as key", cborData: hexDecode("a1616101"), obj: T1{}, wantErrorMsg: "cbor: failed to parse field name \"a\" to int", }, { name: "out of range int as key", cborData: hexDecode("a13bffffffffffffffff01"), obj: T2{}, wantErrorMsg: "cbor: failed to parse field name \"-18446744073709551616\" to int", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { v := reflect.New(reflect.TypeOf(tc.obj)) err := Unmarshal(tc.cborData, v.Interface()) if err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want error %q", tc.cborData, tc.wantErrorMsg) } else if !strings.Contains(err.Error(), tc.wantErrorMsg) { t.Errorf("Unmarshal(0x%x) error %v, want %v", tc.cborData, err.Error(), tc.wantErrorMsg) } }) } } func TestUnmarshalEmptyMapWithDupMapKeyOpt(t *testing.T) { testCases := []struct { name string cborData []byte wantV interface{} }{ { name: "empty map", cborData: hexDecode("a0"), wantV: map[interface{}]interface{}{}, }, { name: "indefinite empty map", cborData: hexDecode("bfff"), wantV: map[interface{}]interface{}{}, }, } dm, err := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() if err != nil { t.Errorf("DecMode() returned error %v", err) } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { var v interface{} if err := dm.Unmarshal(tc.cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } if !reflect.DeepEqual(v, tc.wantV) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborData, v, v, tc.wantV, tc.wantV) } }) } } func TestUnmarshalDupMapKeyToEmptyInterface(t *testing.T) { cborData := hexDecode("a6616161416162614261636143616161466164614461656145") // {"a": "A", "b": "B", "c": "C", "a": "F", "d": "D", "e": "E"} // Duplicate key overwrites previous value (default). wantV := map[interface{}]interface{}{"a": "F", "b": "B", "c": "C", "d": "D", "e": "E"} var v interface{} if err := Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if !reflect.DeepEqual(v, wantV) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, wantV, wantV) } // Duplicate key triggers error. wantV = map[interface{}]interface{}{"a": nil, "b": "B", "c": "C"} wantErrorMsg := "cbor: found duplicate map key \"a\" at map element index 3" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() var v2 interface{} if err := dm.Unmarshal(cborData, &v2); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*DupMapKeyError)", cborData, err) } else if err.Error() != wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(v2, wantV) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v2, v2, wantV, wantV) } } func TestStreamDupMapKeyToEmptyInterface(t *testing.T) { cborData := hexDecode("a6616161416162614261636143616161466164614461656145") // map with duplicate key "c": {"a": "A", "b": "B", "c": "C", "a": "F", "d": "D", "e": "E"} var b []byte for i := 0; i < 3; i++ { b = append(b, cborData...) } // Duplicate key overwrites previous value (default). wantV := map[interface{}]interface{}{"a": "F", "b": "B", "c": "C", "d": "D", "e": "E"} dec := NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { var v1 interface{} if err := dec.Decode(&v1); err != nil { t.Errorf("Decode() returned error %v", err) } if !reflect.DeepEqual(v1, wantV) { t.Errorf("Decode() = %v (%T), want %v (%T)", v1, v1, wantV, wantV) } } var v interface{} if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } // Duplicate key triggers error. wantV = map[interface{}]interface{}{"a": nil, "b": "B", "c": "C"} wantErrorMsg := "cbor: found duplicate map key \"a\" at map element index 3" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() dec = dm.NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { var v2 interface{} if err := dec.Decode(&v2); err == nil { t.Errorf("Decode() didn't return an error") } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Decode() returned wrong error type %T, want (*DupMapKeyError)", err) } else if err.Error() != wantErrorMsg { t.Errorf("Decode() returned error %q, want error containing %q", err.Error(), wantErrorMsg) } if !reflect.DeepEqual(v2, wantV) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v2, v2, wantV, wantV) } } if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } } func TestUnmarshalDupMapKeyToEmptyMap(t *testing.T) { cborData := hexDecode("a6616161416162614261636143616161466164614461656145") // {"a": "A", "b": "B", "c": "C", "a": "F", "d": "D", "e": "E"} // Duplicate key overwrites previous value (default). wantM := map[string]string{"a": "F", "b": "B", "c": "C", "d": "D", "e": "E"} var m map[string]string if err := Unmarshal(cborData, &m); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if !reflect.DeepEqual(m, wantM) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, m, m, wantM, wantM) } // Duplicate key triggers error. wantM = map[string]string{"a": "", "b": "B", "c": "C"} wantErrorMsg := "cbor: found duplicate map key \"a\" at map element index 3" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() var m2 map[string]string if err := dm.Unmarshal(cborData, &m2); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*DupMapKeyError)", cborData, err) } else if err.Error() != wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(m2, wantM) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, m2, m2, wantM, wantM) } } func TestStreamDupMapKeyToEmptyMap(t *testing.T) { cborData := hexDecode("a6616161416162614261636143616161466164614461656145") // {"a": "A", "b": "B", "c": "C", "a": "F", "d": "D", "e": "E"} var b []byte for i := 0; i < 3; i++ { b = append(b, cborData...) } // Duplicate key overwrites previous value (default). wantM := map[string]string{"a": "F", "b": "B", "c": "C", "d": "D", "e": "E"} dec := NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { var m1 map[string]string if err := dec.Decode(&m1); err != nil { t.Errorf("Decode() returned error %v", err) } if !reflect.DeepEqual(m1, wantM) { t.Errorf("Decode() = %v (%T), want %v (%T)", m1, m1, wantM, wantM) } } var v interface{} if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } // Duplicate key triggers error. wantM = map[string]string{"a": "", "b": "B", "c": "C"} wantErrorMsg := "cbor: found duplicate map key \"a\" at map element index 3" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() dec = dm.NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { var m2 map[string]string if err := dec.Decode(&m2); err == nil { t.Errorf("Decode() didn't return an error") } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Decode() returned wrong error type %T, want (*DupMapKeyError)", err) } else if err.Error() != wantErrorMsg { t.Errorf("Decode() returned error %q, want error containing %q", err.Error(), wantErrorMsg) } if !reflect.DeepEqual(m2, wantM) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, m2, m2, wantM, wantM) } } if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } } func TestUnmarshalDupMapKeyToNotEmptyMap(t *testing.T) { cborData := hexDecode("a6616161416162614261636143616161466164614461656145") // {"a": "A", "b": "B", "c": "C", "a": "F", "d": "D", "e": "E"} // Duplicate key overwrites previous value (default). m := map[string]string{"a": "Z", "b": "Z", "c": "Z", "d": "Z", "e": "Z", "f": "Z"} wantM := map[string]string{"a": "F", "b": "B", "c": "C", "d": "D", "e": "E", "f": "Z"} if err := Unmarshal(cborData, &m); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if !reflect.DeepEqual(m, wantM) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, m, m, wantM, wantM) } // Duplicate key triggers error. m2 := map[string]string{"a": "Z", "b": "Z", "c": "Z", "d": "Z", "e": "Z", "f": "Z"} wantM = map[string]string{"a": "", "b": "B", "c": "C", "d": "Z", "e": "Z", "f": "Z"} wantErrorMsg := "cbor: found duplicate map key \"a\" at map element index 3" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() if err := dm.Unmarshal(cborData, &m2); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*DupMapKeyError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(m2, wantM) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, m2, m2, wantM, wantM) } } func TestStreamDupMapKeyToNotEmptyMap(t *testing.T) { cborData := hexDecode("a6616161416162614261636143616161466164614461656145") // {"a": "A", "b": "B", "c": "C", "a": "F", "d": "D", "e": "E"} var b []byte for i := 0; i < 3; i++ { b = append(b, cborData...) } // Duplicate key overwrites previous value (default). wantM := map[string]string{"a": "F", "b": "B", "c": "C", "d": "D", "e": "E", "f": "Z"} dec := NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { m1 := map[string]string{"a": "Z", "b": "Z", "c": "Z", "d": "Z", "e": "Z", "f": "Z"} if err := dec.Decode(&m1); err != nil { t.Errorf("Decode() returned error %v", err) } if !reflect.DeepEqual(m1, wantM) { t.Errorf("Decode() = %v (%T), want %v (%T)", m1, m1, wantM, wantM) } } var v interface{} if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } // Duplicate key triggers error. wantM = map[string]string{"a": "", "b": "B", "c": "C", "d": "Z", "e": "Z", "f": "Z"} wantErrorMsg := "cbor: found duplicate map key \"a\" at map element index 3" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() dec = dm.NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { m2 := map[string]string{"a": "Z", "b": "Z", "c": "Z", "d": "Z", "e": "Z", "f": "Z"} if err := dec.Decode(&m2); err == nil { t.Errorf("Decode() didn't return an error") } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Decode() returned wrong error type %T, want (*DupMapKeyError)", err) } else if err.Error() != wantErrorMsg { t.Errorf("Decode() returned error %q, want error containing %q", err.Error(), wantErrorMsg) } if !reflect.DeepEqual(m2, wantM) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, m2, m2, wantM, wantM) } } if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } } func TestUnmarshalDupMapKeyToStruct(t *testing.T) { type s struct { A string `cbor:"a"` B string `cbor:"b"` C string `cbor:"c"` D string `cbor:"d"` E string `cbor:"e"` } cborData := hexDecode("a6616161416162614261636143616161466164614461656145") // {"a": "A", "b": "B", "c": "C", "a": "F", "d": "D", "e": "E"} // Duplicate key doesn't overwrite previous value (default). wantS := s{A: "A", B: "B", C: "C", D: "D", E: "E"} var s1 s if err := Unmarshal(cborData, &s1); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s1, s1, wantS, wantS) } // Duplicate key triggers error. wantS = s{A: "A", B: "B", C: "C"} wantErrorMsg := "cbor: found duplicate map key \"a\" at map element index 3" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() var s2 s if err := dm.Unmarshal(cborData, &s2); err == nil { t.Errorf("Unmarshal(0x%x, %s) didn't return an error", cborData, reflect.TypeOf(s2)) } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*DupMapKeyError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s2, s2, wantS, wantS) } } func TestStreamDupMapKeyToStruct(t *testing.T) { type s struct { A string `cbor:"a"` B string `cbor:"b"` C string `cbor:"c"` D string `cbor:"d"` E string `cbor:"e"` } cborData := hexDecode("a6616161416162614261636143616161466164614461656145") // {"a": "A", "b": "B", "c": "C", "a": "F", "d": "D", "e": "E"} var b []byte for i := 0; i < 3; i++ { b = append(b, cborData...) } // Duplicate key overwrites previous value (default). wantS := s{A: "A", B: "B", C: "C", D: "D", E: "E"} dec := NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { var s1 s if err := dec.Decode(&s1); err != nil { t.Errorf("Decode() returned error %v", err) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Decode() = %v (%T), want %v (%T)", s1, s1, wantS, wantS) } } var v interface{} if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } // Duplicate key triggers error. wantS = s{A: "A", B: "B", C: "C"} wantErrorMsg := "cbor: found duplicate map key \"a\" at map element index 3" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() dec = dm.NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { var s2 s if err := dec.Decode(&s2); err == nil { t.Errorf("Decode() didn't return an error") } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Decode() returned wrong error type %T, want (*DupMapKeyError)", err) } else if err.Error() != wantErrorMsg { t.Errorf("Decode() returned error %q, want error containing %q", err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s2, s2, wantS, wantS) } } if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } } // dupl map key is a struct field func TestUnmarshalDupMapKeyToStructKeyAsInt(t *testing.T) { type s struct { A int `cbor:"1,keyasint"` B int `cbor:"3,keyasint"` C int `cbor:"5,keyasint"` } cborData := hexDecode("a40102030401030506") // {1:2, 3:4, 1:3, 5:6} // Duplicate key doesn't overwrite previous value (default). wantS := s{A: 2, B: 4, C: 6} var s1 s if err := Unmarshal(cborData, &s1); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s1, s1, wantS, wantS) } // Duplicate key triggers error. wantS = s{A: 2, B: 4} wantErrorMsg := "cbor: found duplicate map key \"1\" at map element index 2" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() var s2 s if err := dm.Unmarshal(cborData, &s2); err == nil { t.Errorf("Unmarshal(0x%x, %s) didn't return an error", cborData, reflect.TypeOf(s2)) } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*DupMapKeyError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s2, s2, wantS, wantS) } } func TestStreamDupMapKeyToStructKeyAsInt(t *testing.T) { type s struct { A int `cbor:"1,keyasint"` B int `cbor:"3,keyasint"` C int `cbor:"5,keyasint"` } cborData := hexDecode("a40102030401030506") // {1:2, 3:4, 1:3, 5:6} var b []byte for i := 0; i < 3; i++ { b = append(b, cborData...) } // Duplicate key overwrites previous value (default). wantS := s{A: 2, B: 4, C: 6} dec := NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { var s1 s if err := dec.Decode(&s1); err != nil { t.Errorf("Decode() returned error %v", err) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Decode() = %v (%T), want %v (%T)", s1, s1, wantS, wantS) } } var v interface{} if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } // Duplicate key triggers error. wantS = s{A: 2, B: 4} wantErrorMsg := "cbor: found duplicate map key \"1\" at map element index 2" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() dec = dm.NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { var s2 s if err := dec.Decode(&s2); err == nil { t.Errorf("Decode() didn't return an error") } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Decode() returned wrong error type %T, want (*DupMapKeyError)", err) } else if err.Error() != wantErrorMsg { t.Errorf("Decode() returned error %q, want error containing %q", err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s2, s2, wantS, wantS) } } if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } } func TestUnmarshalDupMapKeyToStructNoMatchingField(t *testing.T) { type s struct { B string `cbor:"b"` C string `cbor:"c"` D string `cbor:"d"` E string `cbor:"e"` } cborData := hexDecode("a6616161416162614261636143616161466164614461656145") // {"a": "A", "b": "B", "c": "C", "a": "F", "d": "D", "e": "E"} wantS := s{B: "B", C: "C", D: "D", E: "E"} var s1 s if err := Unmarshal(cborData, &s1); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s1, s1, wantS, wantS) } // Duplicate key triggers error even though map key "a" doesn't have a corresponding struct field. wantS = s{B: "B", C: "C"} wantErrorMsg := "cbor: found duplicate map key \"a\" at map element index 3" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() var s2 s if err := dm.Unmarshal(cborData, &s2); err == nil { t.Errorf("Unmarshal(0x%x, %s) didn't return an error", cborData, reflect.TypeOf(s2)) } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*DupMapKeyError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s2, s2, wantS, wantS) } } func TestStreamDupMapKeyToStructNoMatchingField(t *testing.T) { type s struct { B string `cbor:"b"` C string `cbor:"c"` D string `cbor:"d"` E string `cbor:"e"` } cborData := hexDecode("a6616161416162614261636143616161466164614461656145") // {"a": "A", "b": "B", "c": "C", "a": "F", "d": "D", "e": "E"} var b []byte for i := 0; i < 3; i++ { b = append(b, cborData...) } // Duplicate key overwrites previous value (default). wantS := s{B: "B", C: "C", D: "D", E: "E"} dec := NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { var s1 s if err := dec.Decode(&s1); err != nil { t.Errorf("Decode() returned error %v", err) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Decode() = %v (%T), want %v (%T)", s1, s1, wantS, wantS) } } var v interface{} if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } // Duplicate key triggers error. wantS = s{B: "B", C: "C"} wantErrorMsg := "cbor: found duplicate map key \"a\" at map element index 3" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() dec = dm.NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { var s2 s if err := dec.Decode(&s2); err == nil { t.Errorf("Decode() didn't return an error") } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Decode() returned wrong error type %T, want (*DupMapKeyError)", err) } else if err.Error() != wantErrorMsg { t.Errorf("Decode() returned error %q, want error containing %q", err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Decode() = %v (%T), want %v (%T)", s2, s2, wantS, wantS) } } if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } } func TestUnmarshalDupMapKeyToStructKeyAsIntNoMatchingField(t *testing.T) { type s struct { B int `cbor:"3,keyasint"` C int `cbor:"5,keyasint"` } cborData := hexDecode("a40102030401030506") // {1:2, 3:4, 1:3, 5:6} wantS := s{B: 4, C: 6} var s1 s if err := Unmarshal(cborData, &s1); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s1, s1, wantS, wantS) } // Duplicate key triggers error even though map key "a" doesn't have a corresponding struct field. wantS = s{B: 4} wantErrorMsg := "cbor: found duplicate map key \"1\" at map element index 2" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() var s2 s if err := dm.Unmarshal(cborData, &s2); err == nil { t.Errorf("Unmarshal(0x%x, %s) didn't return an error", cborData, reflect.TypeOf(s2)) } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*DupMapKeyError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s2, s2, wantS, wantS) } } func TestStreamDupMapKeyToStructKeyAsIntNoMatchingField(t *testing.T) { type s struct { B int `cbor:"3,keyasint"` C int `cbor:"5,keyasint"` } cborData := hexDecode("a40102030401030506") // {1:2, 3:4, 1:3, 5:6} var b []byte for i := 0; i < 3; i++ { b = append(b, cborData...) } // Duplicate key overwrites previous value (default). wantS := s{B: 4, C: 6} dec := NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { var s1 s if err := dec.Decode(&s1); err != nil { t.Errorf("Decode() returned error %v", err) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Decode() = %v (%T), want %v (%T)", s1, s1, wantS, wantS) } } var v interface{} if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } // Duplicate key triggers error. wantS = s{B: 4} wantErrorMsg := "cbor: found duplicate map key \"1\" at map element index 2" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() dec = dm.NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { var s2 s if err := dec.Decode(&s2); err == nil { t.Errorf("Decode() didn't return an error") } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Decode() returned wrong error type %T, want (*DupMapKeyError)", err) } else if err.Error() != wantErrorMsg { t.Errorf("Decode() returned error %q, want error containing %q", err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Decode() = %v (%T), want %v (%T)", s2, s2, wantS, wantS) } } if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } } func TestUnmarshalDupMapKeyToStructWrongType(t *testing.T) { type s struct { A string `cbor:"a"` B string `cbor:"b"` C string `cbor:"c"` D string `cbor:"d"` E string `cbor:"e"` } cborData := hexDecode("a861616141fa47c35000026162614261636143fa47c3500003616161466164614461656145") // {"a": "A", 100000.0:2, "b": "B", "c": "C", 100000.0:3, "a": "F", "d": "D", "e": "E"} var s1 s wantS := s{A: "A", B: "B", C: "C", D: "D", E: "E"} wantErrorMsg := "cbor: cannot unmarshal" if err := Unmarshal(cborData, &s1); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s1, s1, wantS, wantS) } wantS = s{A: "A", B: "B", C: "C"} wantErrorMsg = "cbor: found duplicate map key \"100000\" at map element index 4" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() var s2 s if err := dm.Unmarshal(cborData, &s2); err == nil { t.Errorf("Unmarshal(0x%x, %s) didn't return an error", cborData, reflect.TypeOf(s2)) } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*DupMapKeyError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s2, s2, wantS, wantS) } } func TestStreamDupMapKeyToStructWrongType(t *testing.T) { type s struct { A string `cbor:"a"` B string `cbor:"b"` C string `cbor:"c"` D string `cbor:"d"` E string `cbor:"e"` } cborData := hexDecode("a861616141fa47c35000026162614261636143fa47c3500003616161466164614461656145") // {"a": "A", 100000.0:2, "b": "B", "c": "C", 100000.0:3, "a": "F", "d": "D", "e": "E"} var b []byte for i := 0; i < 3; i++ { b = append(b, cborData...) } wantS := s{A: "A", B: "B", C: "C", D: "D", E: "E"} wantErrorMsg := "cbor: cannot unmarshal" dec := NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { var s1 s if err := dec.Decode(&s1); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s1, s1, wantS, wantS) } } var v interface{} if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } // Duplicate key triggers error. wantS = s{A: "A", B: "B", C: "C"} wantErrorMsg = "cbor: found duplicate map key \"100000\" at map element index 4" dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() dec = dm.NewDecoder(bytes.NewReader(b)) for i := 0; i < 3; i++ { var s2 s if err := dec.Decode(&s2); err == nil { t.Errorf("Decode() didn't return an error") } else if _, ok := err.(*DupMapKeyError); !ok { t.Errorf("Decode() returned wrong error type %T, want (*DupMapKeyError)", err) } else if err.Error() != wantErrorMsg { t.Errorf("Decode() returned error %q, want error containing %q", err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s2, s2, wantS, wantS) } } if err := dec.Decode(&v); err != io.EOF { t.Errorf("Decode() returned error %v, want %v", err, io.EOF) } } func TestUnmarshalDupMapKeyToStructStringParseError(t *testing.T) { type s struct { A string `cbor:"a"` B string `cbor:"b"` C string `cbor:"c"` D string `cbor:"d"` E string `cbor:"e"` } cborData := hexDecode("a661fe6141616261426163614361fe61466164614461656145") // {"\xFE": "A", "b": "B", "c": "C", "\xFE": "F", "d": "D", "e": "E"} wantS := s{A: "", B: "B", C: "C", D: "D", E: "E"} wantErrorMsg := "cbor: invalid UTF-8 string" // Duplicate key doesn't overwrite previous value (default). var s1 s if err := Unmarshal(cborData, &s1); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else if _, ok := err.(*SemanticError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*SemanticError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s1, s1, wantS, wantS) } // Duplicate key triggers error. dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() var s2 s if err := dm.Unmarshal(cborData, &s2); err == nil { t.Errorf("Unmarshal(0x%x, %s) didn't return an error", cborData, reflect.TypeOf(s2)) } else if _, ok := err.(*SemanticError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*SemanticError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s2, s2, wantS, wantS) } } func TestUnmarshalDupMapKeyToStructIntParseError(t *testing.T) { type s struct { A int `cbor:"1,keyasint"` B int `cbor:"3,keyasint"` C int `cbor:"5,keyasint"` } cborData := hexDecode("a43bffffffffffffffff0203043bffffffffffffffff030506") // {-18446744073709551616:2, 3:4, -18446744073709551616:3, 5:6} // Duplicate key doesn't overwrite previous value (default). wantS := s{B: 4, C: 6} wantErrorMsg := "cbor: cannot unmarshal" var s1 s if err := Unmarshal(cborData, &s1); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s1, s1, wantS, wantS) } // Duplicate key triggers error. dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() var s2 s if err := dm.Unmarshal(cborData, &s2); err == nil { t.Errorf("Unmarshal(0x%x, %s) didn't return an error", cborData, reflect.TypeOf(s2)) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s2, s2, wantS, wantS) } } func TestUnmarshalDupMapKeyToStructWrongTypeParseError(t *testing.T) { type s struct { A string `cbor:"a"` B string `cbor:"b"` C string `cbor:"c"` D string `cbor:"d"` E string `cbor:"e"` } cborData := hexDecode("a68161fe614161626142616361438161fe61466164614461656145") // {["\xFE"]: "A", "b": "B", "c": "C", ["\xFE"]: "F", "d": "D", "e": "E"} // Duplicate key doesn't overwrite previous value (default). wantS := s{A: "", B: "B", C: "C", D: "D", E: "E"} wantErrorMsg := "cbor: cannot unmarshal" var s1 s if err := Unmarshal(cborData, &s1); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s1, s1, wantS, wantS) } // Duplicate key triggers error. dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() var s2 s if err := dm.Unmarshal(cborData, &s2); err == nil { t.Errorf("Unmarshal(0x%x, %s) didn't return an error", cborData, reflect.TypeOf(s2)) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s2, s2, wantS, wantS) } } func TestUnmarshalDupMapKeyToStructWrongTypeUnhashableError(t *testing.T) { type s struct { A string `cbor:"a"` B string `cbor:"b"` C string `cbor:"c"` D string `cbor:"d"` E string `cbor:"e"` } cborData := hexDecode("a6810061416162614261636143810061466164614461656145") // {[0]: "A", "b": "B", "c": "C", [0]: "F", "d": "D", "e": "E"} wantS := s{A: "", B: "B", C: "C", D: "D", E: "E"} // Duplicate key doesn't overwrite previous value (default). wantErrorMsg := "cbor: cannot unmarshal" var s1 s if err := Unmarshal(cborData, &s1); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s1, s1, wantS, wantS) } // Duplicate key triggers error. dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() var s2 s if err := dm.Unmarshal(cborData, &s2); err == nil { t.Errorf("Unmarshal(0x%x, %s) didn't return an error", cborData, reflect.TypeOf(s2)) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s2, s2, wantS, wantS) } } func TestUnmarshalDupMapKeyToStructTagTypeError(t *testing.T) { type s struct { A string `cbor:"a"` B string `cbor:"b"` C string `cbor:"c"` D string `cbor:"d"` E string `cbor:"e"` } cborData := hexDecode("a6c24901000000000000000061416162614261636143c24901000000000000000061466164614461656145") // {bignum(18446744073709551616): "A", "b": "B", "c": "C", bignum(18446744073709551616): "F", "d": "D", "e": "E"} wantS := s{A: "", B: "B", C: "C", D: "D", E: "E"} // Duplicate key doesn't overwrite previous value (default). wantErrorMsg := "cbor: cannot unmarshal" var s1 s if err := Unmarshal(cborData, &s1); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s1, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s1, s1, wantS, wantS) } // Duplicate key triggers error. dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode() var s2 s if err := dm.Unmarshal(cborData, &s2); err == nil { t.Errorf("Unmarshal(0x%x, %s) didn't return an error", cborData, reflect.TypeOf(s2)) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", cborData, err) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), wantErrorMsg) } if !reflect.DeepEqual(s2, wantS) { t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s2, s2, wantS, wantS) } } func TestIndefiniteLengthArrayToArray(t *testing.T) { testCases := []struct { name string cborData []byte wantV interface{} }{ { name: "CBOR empty array to Go 5 elem array", cborData: hexDecode("9fff"), wantV: [5]byte{}, }, { name: "CBOR 3 elem array to Go 5 elem array", cborData: hexDecode("9f010203ff"), wantV: [5]byte{1, 2, 3, 0, 0}, }, { name: "CBOR 10 elem array to Go 5 elem array", cborData: hexDecode("9f0102030405060708090aff"), wantV: [5]byte{1, 2, 3, 4, 5}, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { v := reflect.New(reflect.TypeOf(tc.wantV)) if err := Unmarshal(tc.cborData, v.Interface()); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } if !reflect.DeepEqual(v.Elem().Interface(), tc.wantV) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborData, v.Elem().Interface(), v.Elem().Interface(), tc.wantV, tc.wantV) } }) } } func TestExceedMaxArrayElements(t *testing.T) { testCases := []struct { name string opts DecOptions cborData []byte wantErrorMsg string }{ { name: "array", opts: DecOptions{MaxArrayElements: 16}, cborData: hexDecode("910101010101010101010101010101010101"), wantErrorMsg: "cbor: exceeded max number of elements 16 for CBOR array", }, { name: "indefinite length array", opts: DecOptions{MaxArrayElements: 16}, cborData: hexDecode("9f0101010101010101010101010101010101ff"), wantErrorMsg: "cbor: exceeded max number of elements 16 for CBOR array", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { dm, _ := tc.opts.DecMode() var v interface{} if err := dm.Unmarshal(tc.cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", tc.cborData) } else if err.Error() != tc.wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } }) } } func TestExceedMaxMapPairs(t *testing.T) { testCases := []struct { name string opts DecOptions cborData []byte wantErrorMsg string }{ { name: "array", opts: DecOptions{MaxMapPairs: 16}, cborData: hexDecode("b101010101010101010101010101010101010101010101010101010101010101010101"), wantErrorMsg: "cbor: exceeded max number of key-value pairs 16 for CBOR map", }, { name: "indefinite length array", opts: DecOptions{MaxMapPairs: 16}, cborData: hexDecode("bf01010101010101010101010101010101010101010101010101010101010101010101ff"), wantErrorMsg: "cbor: exceeded max number of key-value pairs 16 for CBOR map", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { dm, _ := tc.opts.DecMode() var v interface{} if err := dm.Unmarshal(tc.cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", tc.cborData) } else if err.Error() != tc.wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } }) } } func TestDecIndefiniteLengthOption(t *testing.T) { testCases := []struct { name string opts DecOptions cborData []byte wantErrorMsg string }{ { name: "byte string", opts: DecOptions{IndefLength: IndefLengthForbidden}, cborData: hexDecode("5fff"), wantErrorMsg: "cbor: indefinite-length byte string isn't allowed", }, { name: "text string", opts: DecOptions{IndefLength: IndefLengthForbidden}, cborData: hexDecode("7fff"), wantErrorMsg: "cbor: indefinite-length UTF-8 text string isn't allowed", }, { name: "array", opts: DecOptions{IndefLength: IndefLengthForbidden}, cborData: hexDecode("9fff"), wantErrorMsg: "cbor: indefinite-length array isn't allowed", }, { name: "indefinite length array", opts: DecOptions{IndefLength: IndefLengthForbidden}, cborData: hexDecode("bfff"), wantErrorMsg: "cbor: indefinite-length map isn't allowed", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { // Default option allows indefinite length items var v interface{} if err := Unmarshal(tc.cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned an error %v", tc.cborData, err) } dm, _ := tc.opts.DecMode() if err := dm.Unmarshal(tc.cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", tc.cborData) } else if err.Error() != tc.wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } }) } } func TestDecTagsMdOption(t *testing.T) { cborData := hexDecode("c074323031332d30332d32315432303a30343a30305a") wantErrorMsg := "cbor: CBOR tag isn't allowed" // Default option allows CBOR tags var v interface{} if err := Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned an error %v", cborData, err) } // Decoding CBOR tags with TagsForbidden option returns error dm, _ := DecOptions{TagsMd: TagsForbidden}.DecMode() if err := dm.Unmarshal(cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", cborData) } else if err.Error() != wantErrorMsg { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", cborData, err.Error(), wantErrorMsg) } // Create DecMode with TagSet and TagsForbidden option returns error wantErrorMsg = "cbor: cannot create DecMode with TagSet when TagsMd is TagsForbidden" tags := NewTagSet() _, err := DecOptions{TagsMd: TagsForbidden}.DecModeWithTags(tags) if err == nil { t.Errorf("DecModeWithTags() didn't return an error") } else if err.Error() != wantErrorMsg { t.Errorf("DecModeWithTags() returned error %q, want %q", err.Error(), wantErrorMsg) } _, err = DecOptions{TagsMd: TagsForbidden}.DecModeWithSharedTags(tags) if err == nil { t.Errorf("DecModeWithSharedTags() didn't return an error") } else if err.Error() != wantErrorMsg { t.Errorf("DecModeWithSharedTags() returned error %q, want %q", err.Error(), wantErrorMsg) } } func TestDecModeInvalidIntDec(t *testing.T) { wantErrorMsg := "cbor: invalid IntDec 101" _, err := DecOptions{IntDec: 101}.DecMode() if err == nil { t.Errorf("DecMode() didn't return an error") } else if err.Error() != wantErrorMsg { t.Errorf("DecMode() returned error %q, want %q", err.Error(), wantErrorMsg) } } func TestIntDec(t *testing.T) { dm, err := DecOptions{IntDec: IntDecConvertSigned}.DecMode() if err != nil { t.Errorf("DecMode() returned an error %+v", err) } testCases := []struct { name string cborData []byte wantObj interface{} wantErrorMsg string }{ { name: "CBOR pos int", cborData: hexDecode("1a000f4240"), wantObj: int64(1000000), }, { name: "CBOR pos int overflows int64", cborData: hexDecode("1bffffffffffffffff"), wantErrorMsg: "18446744073709551615 overflows Go's int64", }, { name: "CBOR neg int", cborData: hexDecode("3903e7"), wantObj: int64(-1000), }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { var v interface{} err := dm.Unmarshal(tc.cborData, &v) if err == nil { if tc.wantErrorMsg != "" { t.Errorf("Unmarshal(0x%x) didn't return an error, want %q", tc.cborData, tc.wantErrorMsg) } else if !reflect.DeepEqual(v, tc.wantObj) { t.Errorf("Unmarshal(0x%x) return %v (%T), want %v (%T)", tc.cborData, v, v, tc.wantObj, tc.wantObj) } } else { if tc.wantErrorMsg == "" { t.Errorf("Unmarshal(0x%x) returned error %q", tc.cborData, err) } else if !strings.Contains(err.Error(), tc.wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } } }) } } func TestDecModeInvalidExtraError(t *testing.T) { wantErrorMsg := "cbor: invalid ExtraReturnErrors 3" _, err := DecOptions{ExtraReturnErrors: 3}.DecMode() if err == nil { t.Errorf("DecMode() didn't return an error") } else if err.Error() != wantErrorMsg { t.Errorf("DecMode() returned error %q, want %q", err.Error(), wantErrorMsg) } } func TestExtraErrorCondUnknowField(t *testing.T) { type s struct { A string B string C string } dm, _ := DecOptions{}.DecMode() dmUnknownFieldError, _ := DecOptions{ExtraReturnErrors: ExtraDecErrorUnknownField}.DecMode() testCases := []struct { name string cborData []byte dm DecMode wantObj interface{} wantErrorMsg string }{ { name: "field by field match", cborData: hexDecode("a3614161616142616261436163"), // map[string]string{"A": "a", "B": "b", "C": "c"} dm: dm, wantObj: s{A: "a", B: "b", C: "c"}, }, { name: "field by field match with ExtraDecErrorUnknownField", cborData: hexDecode("a3614161616142616261436163"), // map[string]string{"A": "a", "B": "b", "C": "c"} dm: dmUnknownFieldError, wantObj: s{A: "a", B: "b", C: "c"}, }, { name: "CBOR map less field", cborData: hexDecode("a26141616161426162"), // map[string]string{"A": "a", "B": "b"} dm: dm, wantObj: s{A: "a", B: "b", C: ""}, }, { name: "CBOR map less field with ExtraDecErrorUnknownField", cborData: hexDecode("a26141616161426162"), // map[string]string{"A": "a", "B": "b"} dm: dmUnknownFieldError, wantObj: s{A: "a", B: "b", C: ""}, }, { name: "CBOR map unknown field", cborData: hexDecode("a461416161614261626143616361446164"), // map[string]string{"A": "a", "B": "b", "C": "c", "D": "d"} dm: dm, wantObj: s{A: "a", B: "b", C: "c"}, }, { name: "CBOR map unknown field with ExtraDecErrorUnknownField", cborData: hexDecode("a461416161614261626143616361446164"), // map[string]string{"A": "a", "B": "b", "C": "c", "D": "d"} dm: dmUnknownFieldError, wantErrorMsg: "cbor: found unknown field at map element index 3", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { var v s err := tc.dm.Unmarshal(tc.cborData, &v) if err == nil { if tc.wantErrorMsg != "" { t.Errorf("Unmarshal(0x%x) didn't return an error, want %q", tc.cborData, tc.wantErrorMsg) } else if !reflect.DeepEqual(v, tc.wantObj) { t.Errorf("Unmarshal(0x%x) return %v (%T), want %v (%T)", tc.cborData, v, v, tc.wantObj, tc.wantObj) } } else { if tc.wantErrorMsg == "" { t.Errorf("Unmarshal(0x%x) returned error %q", tc.cborData, err) } else if !strings.Contains(err.Error(), tc.wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) } } }) } } func TestStreamExtraErrorCondUnknowField(t *testing.T) { type s struct { A string B string C string } cborData := hexDecode("a461416161614461646142616261436163a3614161616142616261436163") // map[string]string{"A": "a", "D": "d", "B": "b", "C": "c"}, map[string]string{"A": "a", "B": "b", "C": "c"} wantErrorMsg := "cbor: found unknown field at map element index 1" wantObj := s{A: "a", B: "b", C: "c"} dmUnknownFieldError, _ := DecOptions{ExtraReturnErrors: ExtraDecErrorUnknownField}.DecMode() dec := dmUnknownFieldError.NewDecoder(bytes.NewReader(cborData)) var v1 s err := dec.Decode(&v1) if err == nil { t.Errorf("Decode() didn't return an error, want %q", wantErrorMsg) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Decode() returned error %q, want %q", err.Error(), wantErrorMsg) } var v2 s err = dec.Decode(&v2) if err != nil { t.Errorf("Decode() returned an error %v", err) } else if !reflect.DeepEqual(v2, wantObj) { t.Errorf("Decode() return %v (%T), want %v (%T)", v2, v2, wantObj, wantObj) } } // TestUnmarshalTagNum55799 is identical to TestUnmarshal, // except that CBOR test data is prefixed with tag number 55799 (0xd9d9f7). func TestUnmarshalTagNum55799(t *testing.T) { tagNum55799 := hexDecode("d9d9f7") for _, tc := range unmarshalTests { // Prefix tag number 55799 to CBOR test data cborData := make([]byte, len(tc.cborData)+6) copy(cborData, tagNum55799) copy(cborData[3:], tagNum55799) copy(cborData[6:], tc.cborData) // Test unmarshalling CBOR into empty interface. var v interface{} if err := Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else { if tm, ok := tc.emptyInterfaceValue.(time.Time); ok { if vt, ok := v.(time.Time); !ok || !tm.Equal(vt) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, tc.emptyInterfaceValue, tc.emptyInterfaceValue) } } else if !reflect.DeepEqual(v, tc.emptyInterfaceValue) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, tc.emptyInterfaceValue, tc.emptyInterfaceValue) } } // Test unmarshalling CBOR into RawMessage. var r RawMessage if err := Unmarshal(cborData, &r); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if !bytes.Equal(r, tc.cborData) { t.Errorf("Unmarshal(0x%x) returned RawMessage %v, want %v", cborData, r, tc.cborData) } // Test unmarshalling CBOR into compatible data types. for _, value := range tc.values { v := reflect.New(reflect.TypeOf(value)) vPtr := v.Interface() if err := Unmarshal(cborData, vPtr); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else { if tm, ok := value.(time.Time); ok { if vt, ok := v.Elem().Interface().(time.Time); !ok || !tm.Equal(vt) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v.Elem().Interface(), v.Elem().Interface(), value, value) } } else if !reflect.DeepEqual(v.Elem().Interface(), value) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v.Elem().Interface(), v.Elem().Interface(), value, value) } } } // Test unmarshalling CBOR into incompatible data types. for _, typ := range tc.wrongTypes { v := reflect.New(typ) vPtr := v.Interface() if err := Unmarshal(cborData, vPtr); err == nil { t.Errorf("Unmarshal(0x%x, %s) didn't return an error", cborData, typ.String()) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", cborData, err) } else if !strings.Contains(err.Error(), "cannot unmarshal") { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", cborData, err.Error(), "cannot unmarshal") } } } } // TestUnmarshalFloatWithTagNum55799 is identical to TestUnmarshalFloat, // except that CBOR test data is prefixed with tag number 55799 (0xd9d9f7). func TestUnmarshalFloatWithTagNum55799(t *testing.T) { tagNum55799 := hexDecode("d9d9f7") for _, tc := range unmarshalFloatTests { // Prefix tag number 55799 to CBOR test data cborData := make([]byte, len(tc.cborData)+3) copy(cborData, tagNum55799) copy(cborData[3:], tc.cborData) // Test unmarshalling CBOR into empty interface. var v interface{} if err := Unmarshal(tc.cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } else { testFloat(t, tc.cborData, v, tc.emptyInterfaceValue, tc.equalityThreshold) } // Test unmarshalling CBOR into RawMessage. var r RawMessage if err := Unmarshal(tc.cborData, &r); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } else if !bytes.Equal(r, tc.cborData) { t.Errorf("Unmarshal(0x%x) returned RawMessage %v, want %v", tc.cborData, r, tc.cborData) } // Test unmarshalling CBOR into compatible data types. for _, value := range tc.values { v := reflect.New(reflect.TypeOf(value)) vPtr := v.Interface() if err := Unmarshal(tc.cborData, vPtr); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } else { testFloat(t, tc.cborData, v.Elem().Interface(), value, tc.equalityThreshold) } } // Test unmarshalling CBOR into incompatible data types. for _, typ := range tc.wrongTypes { v := reflect.New(typ) vPtr := v.Interface() if err := Unmarshal(tc.cborData, vPtr); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error", tc.cborData) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", tc.cborData, err) } else if !strings.Contains(err.Error(), "cannot unmarshal") { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", tc.cborData, err.Error(), "cannot unmarshal") } } } } func TestUnmarshalTagNum55799AsElement(t *testing.T) { testCases := []struct { name string cborData []byte emptyInterfaceValue interface{} values []interface{} wrongTypes []reflect.Type }{ { "array", hexDecode("d9d9f783d9d9f701d9d9f702d9d9f703"), // 55799([55799(1), 55799(2), 55799(3)]) []interface{}{uint64(1), uint64(2), uint64(3)}, []interface{}{[]interface{}{uint64(1), uint64(2), uint64(3)}, []byte{1, 2, 3}, []int{1, 2, 3}, []uint{1, 2, 3}, [0]int{}, [1]int{1}, [3]int{1, 2, 3}, [5]int{1, 2, 3, 0, 0}, []float32{1, 2, 3}, []float64{1, 2, 3}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag}, }, { "map", hexDecode("d9d9f7a2d9d9f701d9d9f702d9d9f703d9d9f704"), // 55799({55799(1): 55799(2), 55799(3): 55799(4)}) map[interface{}]interface{}{uint64(1): uint64(2), uint64(3): uint64(4)}, []interface{}{map[interface{}]interface{}{uint64(1): uint64(2), uint64(3): uint64(4)}, map[uint]int{1: 2, 3: 4}, map[int]uint{1: 2, 3: 4}}, []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { // Test unmarshalling CBOR into empty interface. var v interface{} if err := Unmarshal(tc.cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } else { if tm, ok := tc.emptyInterfaceValue.(time.Time); ok { if vt, ok := v.(time.Time); !ok || !tm.Equal(vt) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborData, v, v, tc.emptyInterfaceValue, tc.emptyInterfaceValue) } } else if !reflect.DeepEqual(v, tc.emptyInterfaceValue) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborData, v, v, tc.emptyInterfaceValue, tc.emptyInterfaceValue) } } // Test unmarshalling CBOR into compatible data types. for _, value := range tc.values { v := reflect.New(reflect.TypeOf(value)) vPtr := v.Interface() if err := Unmarshal(tc.cborData, vPtr); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err) } else { if tm, ok := value.(time.Time); ok { if vt, ok := v.Elem().Interface().(time.Time); !ok || !tm.Equal(vt) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborData, v.Elem().Interface(), v.Elem().Interface(), value, value) } } else if !reflect.DeepEqual(v.Elem().Interface(), value) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborData, v.Elem().Interface(), v.Elem().Interface(), value, value) } } } // Test unmarshalling CBOR into incompatible data types. for _, typ := range tc.wrongTypes { v := reflect.New(typ) vPtr := v.Interface() if err := Unmarshal(tc.cborData, vPtr); err == nil { t.Errorf("Unmarshal(0x%x, %s) didn't return an error", tc.cborData, typ.String()) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", tc.cborData, err) } else if !strings.Contains(err.Error(), "cannot unmarshal") { t.Errorf("Unmarshal(0x%x) returned error %q, want error containing %q", tc.cborData, err.Error(), "cannot unmarshal") } } }) } } func TestUnmarshalTagNum55799ToBinaryUnmarshaler(t *testing.T) { cborData := hexDecode("d9d9f74800000000499602d2") // 55799(h'00000000499602D2') wantObj := number(1234567890) var v number if err := Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if !reflect.DeepEqual(v, wantObj) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, wantObj, wantObj) } } func TestUnmarshalTagNum55799ToUnmarshaler(t *testing.T) { cborData := hexDecode("d9d9f7d864a1636e756d01") // 55799(100({"num": 1})) wantObj := number3(1) var v number3 if err := Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if !reflect.DeepEqual(v, wantObj) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, wantObj, wantObj) } } func TestUnmarshalTagNum55799ToRegisteredGoType(t *testing.T) { type myInt int typ := reflect.TypeOf(myInt(0)) tags := NewTagSet() if err := tags.Add(TagOptions{EncTag: EncTagRequired, DecTag: DecTagRequired}, typ, 125); err != nil { t.Fatalf("TagSet.Add(%s, %v) returned error %v", typ, 125, err) } dm, _ := DecOptions{}.DecModeWithTags(tags) cborData := hexDecode("d9d9f7d87d01") // 55799(125(1)) wantObj := myInt(1) var v myInt if err := dm.Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if !reflect.DeepEqual(v, wantObj) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, wantObj, wantObj) } } // TODO: wait for clarification from 7049bis https://github.com/cbor-wg/CBORbis/issues/183 // Nested tag number 55799 may be stripeed as well depending on 7049bis clarification. func TestUnmarshalNestedTagNum55799ToEmptyInterface(t *testing.T) { cborData := hexDecode("d864d9d9f701") // 100(55799(1)) wantObj := Tag{100, Tag{55799, uint64(1)}} var v interface{} if err := Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if !reflect.DeepEqual(v, wantObj) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, wantObj, wantObj) } } func TestUnmarshalNestedTagNum55799ToValue(t *testing.T) { cborData := hexDecode("d864d9d9f701") // 100(55799(1)) wantObj := 1 var v int if err := Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if !reflect.DeepEqual(v, wantObj) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, wantObj, wantObj) } } func TestUnmarshalNestedTagNum55799ToTag(t *testing.T) { cborData := hexDecode("d864d9d9f701") // 100(55799(1)) wantObj := Tag{100, Tag{55799, uint64(1)}} var v Tag if err := Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if !reflect.DeepEqual(v, wantObj) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, wantObj, wantObj) } } func TestUnmarshalNestedTagNum55799ToTime(t *testing.T) { cborData := hexDecode("c0d9d9f774323031332d30332d32315432303a30343a30305a") // 0(55799("2013-03-21T20:04:00Z")) wantErrorMsg := "tag number 0 must be followed by text string, got tag" var v time.Time if err := Unmarshal(cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return error", cborData) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %s, want %s", cborData, err.Error(), wantErrorMsg) } } func TestUnmarshalNestedTagNum55799ToBinaryUnmarshaler(t *testing.T) { cborData := hexDecode("d864d9d9f74800000000499602d2") // 100(55799(h'00000000499602D2')) wantObj := number(1234567890) var v number if err := Unmarshal(cborData, &v); err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", cborData, err) } else if !reflect.DeepEqual(v, wantObj) { t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", cborData, v, v, wantObj, wantObj) } } func TestUnmarshalNestedTagNum55799ToUnmarshaler(t *testing.T) { cborData := hexDecode("d864d9d9f7a1636e756d01") // 100(55799({"num": 1})) wantErrorMsg := "wrong tag content type" var v number3 if err := Unmarshal(cborData, &v); err == nil { t.Errorf("Unmarshal(0x%x) didn't return error", cborData) } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %s, want %s", cborData, err.Error(), wantErrorMsg) } } func TestUnmarshalNestedTagNum55799ToRegisteredGoType(t *testing.T) { type myInt int typ := reflect.TypeOf(myInt(0)) tags := NewTagSet() if err := tags.Add(TagOptions{EncTag: EncTagRequired, DecTag: DecTagRequired}, typ, 125); err != nil { t.Fatalf("TagSet.Add(%s, %v) returned error %v", typ, 125, err) } dm, _ := DecOptions{}.DecModeWithTags(tags) cborData := hexDecode("d87dd9d9f701") // 125(55799(1)) wantErrorMsg := "cbor: wrong tag number for cbor.myInt, got [125 55799], expected [125]" var v myInt if err := dm.Unmarshal(cborData, &v); err == nil { t.Errorf("Unmarshal() didn't return error") } else if !strings.Contains(err.Error(), wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %s, want %s", cborData, err.Error(), wantErrorMsg) } } func TestUnmarshalPosIntToBigInt(t *testing.T) { cborData := hexDecode("1bffffffffffffffff") // 18446744073709551615 wantEmptyInterfaceValue := uint64(18446744073709551615) wantBigIntValue := bigIntOrPanic("18446744073709551615") var v1 interface{} if err := Unmarshal(cborData, &v1); err != nil { t.Errorf("Unmarshal(0x%x) returned error %+v", cborData, err) } else if !reflect.DeepEqual(v1, wantEmptyInterfaceValue) { t.Errorf("Unmarshal(0x%x) returned %v (%T), want %v (%T)", cborData, v1, v1, wantEmptyInterfaceValue, wantEmptyInterfaceValue) } var v2 big.Int if err := Unmarshal(cborData, &v2); err != nil { t.Errorf("Unmarshal(0x%x) returned error %+v", cborData, err) } else if !reflect.DeepEqual(v2, wantBigIntValue) { t.Errorf("Unmarshal(0x%x) returned %v (%T), want %v (%T)", cborData, v2, v2, wantBigIntValue, wantBigIntValue) } } func TestUnmarshalNegIntToBigInt(t *testing.T) { testCases := []struct { name string cborData []byte wantEmptyInterfaceValue interface{} wantBigIntValue big.Int }{ { name: "fit Go int64", cborData: hexDecode("3b7fffffffffffffff"), // -9223372036854775808 wantEmptyInterfaceValue: int64(-9223372036854775808), wantBigIntValue: bigIntOrPanic("-9223372036854775808"), }, { name: "overflow Go int64", cborData: hexDecode("3b8000000000000000"), // -9223372036854775809 wantEmptyInterfaceValue: bigIntOrPanic("-9223372036854775809"), wantBigIntValue: bigIntOrPanic("-9223372036854775809"), }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { var v1 interface{} if err := Unmarshal(tc.cborData, &v1); err != nil { t.Errorf("Unmarshal(0x%x) returned error %+v", tc.cborData, err) } else if !reflect.DeepEqual(v1, tc.wantEmptyInterfaceValue) { t.Errorf("Unmarshal(0x%x) returned %v (%T), want %v (%T)", tc.cborData, v1, v1, tc.wantEmptyInterfaceValue, tc.wantEmptyInterfaceValue) } var v2 big.Int if err := Unmarshal(tc.cborData, &v2); err != nil { t.Errorf("Unmarshal(0x%x) returned error %+v", tc.cborData, err) } else if !reflect.DeepEqual(v2, tc.wantBigIntValue) { t.Errorf("Unmarshal(0x%x) returned %v (%T), want %v (%T)", tc.cborData, v2, v2, tc.wantBigIntValue, tc.wantBigIntValue) } }) } } func TestUnmarshalTag2(t *testing.T) { testCases := []struct { name string cborData []byte wantEmptyInterfaceValue interface{} wantValues []interface{} }{ { name: "fit Go int64", cborData: hexDecode("c2430f4240"), // 2(1000000) wantEmptyInterfaceValue: bigIntOrPanic("1000000"), wantValues: []interface{}{ int64(1000000), uint64(1000000), float32(1000000), float64(1000000), bigIntOrPanic("1000000"), }, }, { name: "fit Go uint64", cborData: hexDecode("c248ffffffffffffffff"), // 2(18446744073709551615) wantEmptyInterfaceValue: bigIntOrPanic("18446744073709551615"), wantValues: []interface{}{ uint64(18446744073709551615), float32(18446744073709551615), float64(18446744073709551615), bigIntOrPanic("18446744073709551615"), }, }, { name: "fit Go uint64 with leading zeros", cborData: hexDecode("c24900ffffffffffffffff"), // 2(18446744073709551615) wantEmptyInterfaceValue: bigIntOrPanic("18446744073709551615"), wantValues: []interface{}{ uint64(18446744073709551615), float32(18446744073709551615), float64(18446744073709551615), bigIntOrPanic("18446744073709551615"), }, }, { name: "overflow Go uint64", cborData: hexDecode("c249010000000000000000"), // 2(18446744073709551616) wantEmptyInterfaceValue: bigIntOrPanic("18446744073709551616"), wantValues: []interface{}{ bigIntOrPanic("18446744073709551616"), }, }, { name: "overflow Go uint64 with leading zeros", cborData: hexDecode("c24b0000010000000000000000"), // 2(18446744073709551616) wantEmptyInterfaceValue: bigIntOrPanic("18446744073709551616"), wantValues: []interface{}{ bigIntOrPanic("18446744073709551616"), }, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { var v1 interface{} if err := Unmarshal(tc.cborData, &v1); err != nil { t.Errorf("Unmarshal(0x%x) returned error %+v", tc.cborData, err) } else if !reflect.DeepEqual(v1, tc.wantEmptyInterfaceValue) { t.Errorf("Unmarshal(0x%x) returned %v (%T), want %v (%T)", tc.cborData, v1, v1, tc.wantEmptyInterfaceValue, tc.wantEmptyInterfaceValue) } for _, wantValue := range tc.wantValues { v := reflect.New(reflect.TypeOf(wantValue)) if err := Unmarshal(tc.cborData, v.Interface()); err != nil { t.Errorf("Unmarshal(0x%x) returned error %+v", tc.cborData, err) } else if !reflect.DeepEqual(v.Elem().Interface(), wantValue) { t.Errorf("Unmarshal(0x%x) returned %v (%T), want %v (%T)", tc.cborData, v.Elem().Interface(), v.Elem().Interface(), wantValue, wantValue) } } }) } } func TestUnmarshalTag3(t *testing.T) { testCases := []struct { name string cborData []byte wantEmptyInterfaceValue interface{} wantValues []interface{} }{ { name: "fit Go int64", cborData: hexDecode("c3487fffffffffffffff"), // 3(-9223372036854775808) wantEmptyInterfaceValue: bigIntOrPanic("-9223372036854775808"), wantValues: []interface{}{ int64(-9223372036854775808), float32(-9223372036854775808), float64(-9223372036854775808), bigIntOrPanic("-9223372036854775808"), }, }, { name: "fit Go int64 with leading zeros", cborData: hexDecode("c349007fffffffffffffff"), // 3(-9223372036854775808) wantEmptyInterfaceValue: bigIntOrPanic("-9223372036854775808"), wantValues: []interface{}{ int64(-9223372036854775808), float32(-9223372036854775808), float64(-9223372036854775808), bigIntOrPanic("-9223372036854775808"), }, }, { name: "overflow Go int64", cborData: hexDecode("c349010000000000000000"), // 3(-18446744073709551617) wantEmptyInterfaceValue: bigIntOrPanic("-18446744073709551617"), wantValues: []interface{}{ bigIntOrPanic("-18446744073709551617"), }, }, { name: "overflow Go int64 with leading zeros", cborData: hexDecode("c34b0000010000000000000000"), // 3(-18446744073709551617) wantEmptyInterfaceValue: bigIntOrPanic("-18446744073709551617"), wantValues: []interface{}{ bigIntOrPanic("-18446744073709551617"), }, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { var v1 interface{} if err := Unmarshal(tc.cborData, &v1); err != nil { t.Errorf("Unmarshal(0x%x) returned error %+v", tc.cborData, err) } else if !reflect.DeepEqual(v1, tc.wantEmptyInterfaceValue) { t.Errorf("Unmarshal(0x%x) returned %v (%T), want %v (%T)", tc.cborData, v1, v1, tc.wantEmptyInterfaceValue, tc.wantEmptyInterfaceValue) } for _, wantValue := range tc.wantValues { v := reflect.New(reflect.TypeOf(wantValue)) if err := Unmarshal(tc.cborData, v.Interface()); err != nil { t.Errorf("Unmarshal(0x%x) returned error %+v", tc.cborData, err) } else if !reflect.DeepEqual(v.Elem().Interface(), wantValue) { t.Errorf("Unmarshal(0x%x) returned %v (%T), want %v (%T)", tc.cborData, v.Elem().Interface(), v.Elem().Interface(), wantValue, wantValue) } } }) } } func TestUnmarshalInvalidTagBignum(t *testing.T) { typeBigIntSlice := reflect.TypeOf([]big.Int{}) testCases := []struct { name string cborData []byte decodeToTypes []reflect.Type wantErrorMsg string }{ { name: "Tag 2 with string", cborData: hexDecode("c27f657374726561646d696e67ff"), decodeToTypes: []reflect.Type{typeIntf, typeBigInt}, wantErrorMsg: "cbor: tag number 2 or 3 must be followed by byte string, got UTF-8 text string", }, { name: "Tag 3 with string", cborData: hexDecode("c37f657374726561646d696e67ff"), decodeToTypes: []reflect.Type{typeIntf, typeBigInt}, wantErrorMsg: "cbor: tag number 2 or 3 must be followed by byte string, got UTF-8 text string", }, { name: "Tag 3 with negavtive int", cborData: hexDecode("81C330"), // [3(-17)] decodeToTypes: []reflect.Type{typeIntf, typeBigIntSlice}, wantErrorMsg: "cbor: tag number 2 or 3 must be followed by byte string, got negative integer", }, } for _, tc := range testCases { for _, decodeToType := range tc.decodeToTypes { t.Run(tc.name+" decode to "+decodeToType.String(), func(t *testing.T) { v := reflect.New(decodeToType) if err := Unmarshal(tc.cborData, v.Interface()); err == nil { t.Errorf("Unmarshal(0x%x) didn't return error, want error msg %q", tc.cborData, tc.wantErrorMsg) } else if !strings.Contains(err.Error(), tc.wantErrorMsg) { t.Errorf("Unmarshal(0x%x) returned error %q, want %q", tc.cborData, err, tc.wantErrorMsg) } }) } } } type Foo interface { Foo() string } type UintFoo uint func (f *UintFoo) Foo() string { return fmt.Sprint(f) } type IntFoo int func (f *IntFoo) Foo() string { return fmt.Sprint(*f) } type ByteFoo []byte func (f *ByteFoo) Foo() string { return fmt.Sprint(*f) } type StringFoo string func (f *StringFoo) Foo() string { return string(*f) } type ArrayFoo []int func (f *ArrayFoo) Foo() string { return fmt.Sprint(*f) } type MapFoo map[int]int func (f *MapFoo) Foo() string { return fmt.Sprint(*f) } type StructFoo struct { Value int `cbor:"1,keyasint"` } func (f *StructFoo) Foo() string { return fmt.Sprint(*f) } type TestExample struct { Message string `cbor:"1,keyasint"` Foo Foo `cbor:"2,keyasint"` } func TestUnmarshalToInterface(t *testing.T) { uintFoo, uintFoo123 := UintFoo(0), UintFoo(123) intFoo, intFooNeg1 := IntFoo(0), IntFoo(-1) byteFoo, byteFoo123 := ByteFoo(nil), ByteFoo([]byte{1, 2, 3}) stringFoo, stringFoo123 := StringFoo(""), StringFoo("123") arrayFoo, arrayFoo123 := ArrayFoo(nil), ArrayFoo([]int{1, 2, 3}) mapFoo, mapFoo123 := MapFoo(nil), MapFoo(map[int]int{1: 1, 2: 2, 3: 3}) em, _ := EncOptions{Sort: SortCanonical}.EncMode() testCases := []struct { name string data []byte v *TestExample unmarshalToObj *TestExample }{ { name: "uint", data: hexDecode("a2016b736f6d65206d657373676502187b"), // {1: "some messge", 2: 123} v: &TestExample{ Message: "some messge", Foo: &uintFoo123, }, unmarshalToObj: &TestExample{Foo: &uintFoo}, }, { name: "int", data: hexDecode("a2016b736f6d65206d65737367650220"), // {1: "some messge", 2: -1} v: &TestExample{ Message: "some messge", Foo: &intFooNeg1, }, unmarshalToObj: &TestExample{Foo: &intFoo}, }, { name: "bytes", data: hexDecode("a2016b736f6d65206d65737367650243010203"), // {1: "some messge", 2: [1,2,3]} v: &TestExample{ Message: "some messge", Foo: &byteFoo123, }, unmarshalToObj: &TestExample{Foo: &byteFoo}, }, { name: "string", data: hexDecode("a2016b736f6d65206d65737367650263313233"), // {1: "some messge", 2: "123"} v: &TestExample{ Message: "some messge", Foo: &stringFoo123, }, unmarshalToObj: &TestExample{Foo: &stringFoo}, }, { name: "array", data: hexDecode("a2016b736f6d65206d65737367650283010203"), // {1: "some messge", 2: []int{1,2,3}} v: &TestExample{ Message: "some messge", Foo: &arrayFoo123, }, unmarshalToObj: &TestExample{Foo: &arrayFoo}, }, { name: "map", data: hexDecode("a2016b736f6d65206d657373676502a3010102020303"), // {1: "some messge", 2: map[int]int{1:1,2:2,3:3}} v: &TestExample{ Message: "some messge", Foo: &mapFoo123, }, unmarshalToObj: &TestExample{Foo: &mapFoo}, }, { name: "struct", data: hexDecode("a2016b736f6d65206d657373676502a1011901c8"), // {1: "some messge", 2: {1: 456}} v: &TestExample{ Message: "some messge", Foo: &StructFoo{Value: 456}, }, unmarshalToObj: &TestExample{Foo: &StructFoo{}}, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { data, err := em.Marshal(tc.v) if err != nil { t.Errorf("Marshal(%+v) returned error %v", tc.v, err) } else if !bytes.Equal(data, tc.data) { t.Errorf("Marshal(%+v) = 0x%x, want 0x%x", tc.v, data, tc.v) } // Unmarshal to empty interface var einterface TestExample if err = Unmarshal(data, &einterface); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want error (*UnmarshalTypeError)", data) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong type of error %T, want (*UnmarshalTypeError)", data, err) } // Unmarshal to interface value err = Unmarshal(data, tc.unmarshalToObj) if err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", data, err) } else if !reflect.DeepEqual(tc.unmarshalToObj, tc.v) { t.Errorf("Unmarshal(0x%x) = %v, want %v", data, tc.unmarshalToObj, tc.v) } }) } } type Bar struct { I int } func (b *Bar) Foo() string { return fmt.Sprint(*b) } type FooStruct struct { Foos []Foo } func TestUnmarshalTaggedDataToInterface(t *testing.T) { var tags = NewTagSet() err := tags.Add( TagOptions{EncTag: EncTagRequired, DecTag: DecTagRequired}, reflect.TypeOf(&Bar{}), 4, ) if err != nil { t.Error(err) } v := &FooStruct{ Foos: []Foo{&Bar{1}}, } want := hexDecode("a164466f6f7381c4a1614901") // {"Foos": [4({"I": 1})]} em, _ := EncOptions{}.EncModeWithTags(tags) data, err := em.Marshal(v) if err != nil { t.Errorf("Marshal(%+v) returned error %v", v, err) } else if !bytes.Equal(data, want) { t.Errorf("Marshal(%+v) = 0x%x, want 0x%x", v, data, want) } dm, _ := DecOptions{}.DecModeWithTags(tags) // Unmarshal to empty interface var v1 Bar if err = dm.Unmarshal(data, &v1); err == nil { t.Errorf("Unmarshal(0x%x) didn't return an error, want error (*UnmarshalTypeError)", data) } else if _, ok := err.(*UnmarshalTypeError); !ok { t.Errorf("Unmarshal(0x%x) returned wrong type of error %T, want (*UnmarshalTypeError)", data, err) } // Unmarshal to interface value v2 := &FooStruct{ Foos: []Foo{&Bar{}}, } err = dm.Unmarshal(data, v2) if err != nil { t.Errorf("Unmarshal(0x%x) returned error %v", data, err) } else if !reflect.DeepEqual(v2, v) { t.Errorf("Unmarshal(0x%x) = %v, want %v", data, v2, v) } }