1 // Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
2 // Use of this source code is governed by a MIT license found in the LICENSE file.
17 func TestCborIndefiniteLength(t *testing.T) {
18 oldMapType := testCborH.MapType
20 testCborH.MapType = oldMapType
22 testCborH.MapType = testMapStrIntfTyp
24 // M1 map[string][]byte
31 // define it (v), encode it using indefinite lengths, decode it (vv), compare v to vv
32 v = map[string]interface{}{
33 "one-byte-key": []byte{1, 2, 3, 4, 5, 6},
34 "two-string-key": "two-value",
35 "three-list-key": []interface{}{true, false, uint64(1), int64(-1)},
39 e := NewEncoder(&buf, testCborH)
40 buf.WriteByte(cborBdIndefiniteMap)
42 buf.WriteByte(cborBdIndefiniteString)
46 buf.WriteByte(cborBdBreak)
48 buf.WriteByte(cborBdIndefiniteBytes)
49 e.MustEncode([]byte{1, 2, 3})
50 e.MustEncode([]byte{4, 5, 6})
51 buf.WriteByte(cborBdBreak)
54 buf.WriteByte(cborBdIndefiniteString)
56 e.MustEncode("string-")
58 buf.WriteByte(cborBdBreak)
60 buf.WriteByte(cborBdIndefiniteString)
61 e.MustEncode([]byte("two-")) // encode as bytes, to check robustness of code
62 e.MustEncode([]byte("value"))
63 buf.WriteByte(cborBdBreak)
66 buf.WriteByte(cborBdIndefiniteString)
67 e.MustEncode("three-")
70 buf.WriteByte(cborBdBreak)
72 buf.WriteByte(cborBdIndefiniteArray)
75 e.MustEncode(uint64(1))
76 e.MustEncode(int64(-1))
77 buf.WriteByte(cborBdBreak)
79 buf.WriteByte(cborBdBreak) // close map
81 NewDecoderBytes(buf.Bytes(), testCborH).MustDecode(&vv)
82 if err := deepEqual(v, vv); err != nil {
83 logT(t, "-------- Before and After marshal do not match: Error: %v", err)
84 logT(t, " ....... GOLDEN: (%T) %#v", v, v)
85 logT(t, " ....... DECODED: (%T) %#v", vv, vv)
90 type testCborGolden struct {
91 Base64 string `codec:"cbor"`
92 Hex string `codec:"hex"`
93 Roundtrip bool `codec:"roundtrip"`
94 Decoded interface{} `codec:"decoded"`
95 Diagnostic string `codec:"diagnostic"`
96 Skip bool `codec:"skip"`
99 // Some tests are skipped because they include numbers outside the range of int64/uint64
100 func TestCborGoldens(t *testing.T) {
101 oldMapType := testCborH.MapType
103 testCborH.MapType = oldMapType
105 testCborH.MapType = testMapStrIntfTyp
106 // decode test-cbor-goldens.json into a list of []*testCborGolden
108 // - decode hex into []byte bs
109 // - decode bs into interface{} v
110 // - compare both using deepequal
111 // - for any miss, record it
112 var gs []*testCborGolden
113 f, err := os.Open("test-cbor-goldens.json")
115 logT(t, "error opening test-cbor-goldens.json: %v", err)
119 jh := new(JsonHandle)
120 jh.MapType = testMapStrIntfTyp
121 // d := NewDecoder(f, jh)
122 d := NewDecoder(bufio.NewReader(f), jh)
123 // err = d.Decode(&gs)
126 logT(t, "error json decoding test-cbor-goldens.json: %v", err)
130 tagregex := regexp.MustCompile(`[\d]+\(.+?\)`)
131 hexregex := regexp.MustCompile(`h'([0-9a-fA-F]*)'`)
132 for i, g := range gs {
133 // fmt.Printf("%v, skip: %v, isTag: %v, %s\n", i, g.Skip, tagregex.MatchString(g.Diagnostic), g.Diagnostic)
134 // skip tags or simple or those with prefix, as we can't verify them.
135 if g.Skip || strings.HasPrefix(g.Diagnostic, "simple(") || tagregex.MatchString(g.Diagnostic) {
136 // fmt.Printf("%v: skipped\n", i)
137 logT(t, "[%v] skipping because skip=true OR unsupported simple value or Tag Value", i)
140 // println("++++++++++++", i, "g.Diagnostic", g.Diagnostic)
141 if hexregex.MatchString(g.Diagnostic) {
142 // println(i, "g.Diagnostic matched hex")
143 if s2 := g.Diagnostic[2 : len(g.Diagnostic)-1]; s2 == "" {
144 g.Decoded = zeroByteSlice
145 } else if bs2, err2 := hex.DecodeString(s2); err2 == nil {
148 // fmt.Printf("%v: hex: %v\n", i, g.Decoded)
150 bs, err := hex.DecodeString(g.Hex)
152 logT(t, "[%v] error hex decoding %s [%v]: %v", i, g.Hex, g.Hex, err)
156 NewDecoderBytes(bs, testCborH).MustDecode(&v)
157 if _, ok := v.(RawExt); ok {
160 // check the diagnostics to compare
161 switch g.Diagnostic {
163 b := math.IsInf(v.(float64), 1)
164 testCborError(t, i, math.Inf(1), v, nil, &b)
166 b := math.IsInf(v.(float64), -1)
167 testCborError(t, i, math.Inf(-1), v, nil, &b)
169 // println(i, "checking NaN")
170 b := math.IsNaN(v.(float64))
171 testCborError(t, i, math.NaN(), v, nil, &b)
174 testCborError(t, i, nil, v, nil, &b)
177 // testCborCoerceJsonNumber(reflect.ValueOf(&v0))
178 testCborError(t, i, v0, v, deepEqual(v0, v), nil)
183 func testCborError(t *testing.T, i int, v0, v1 interface{}, err error, equal *bool) {
184 if err == nil && equal == nil {
185 // fmt.Printf("%v testCborError passed (err and equal nil)\n", i)
189 logT(t, "[%v] deepEqual error: %v", i, err)
190 logT(t, " ....... GOLDEN: (%T) %#v", v0, v0)
191 logT(t, " ....... DECODED: (%T) %#v", v1, v1)
194 if equal != nil && !*equal {
195 logT(t, "[%v] values not equal", i)
196 logT(t, " ....... GOLDEN: (%T) %#v", v0, v0)
197 logT(t, " ....... DECODED: (%T) %#v", v1, v1)
200 // fmt.Printf("%v testCborError passed (checks passed)\n", i)
203 func TestCborHalfFloat(t *testing.T) {
204 m := map[uint16]float64{
205 // using examples from
206 // https://en.wikipedia.org/wiki/Half-precision_floating-point_format
208 0x3c01: 1 + math.Pow(2, -10),
211 0x0400: math.Pow(2, -14),
212 0x03ff: math.Pow(2, -14) - math.Pow(2, -24),
213 0x0001: math.Pow(2, -24),
218 ba[0] = cborBdFloat16
220 for k, v := range m {
222 bigen.PutUint16(ba[1:], k)
223 testUnmarshalErr(&res, ba[:3], testCborH, t, "-")
225 logT(t, "equal floats: from %x %b, %v", k, k, v)
227 failT(t, "unequal floats: from %x %b, %v != %v", k, k, res, v)