cbor/valid_test.go
Faye Amacker 508be9165f Rename two test funcs that can panic
This commit renames two test funcs to begin with "must"
if they can panic:
- hexDecode() -> mustHexDecode()
- bigIntOrPanic() -> mustBigInt()
2025-06-29 19:51:48 -05:00

442 lines
13 KiB
Go

// 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"
"testing"
)
func TestValid1(t *testing.T) {
for _, mt := range marshalTests {
if err := Wellformed(mt.wantData); err != nil {
t.Errorf("Wellformed() returned error %v", err)
}
}
}
func TestValid2(t *testing.T) {
for _, mt := range marshalTests {
dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode()
if err := dm.Wellformed(mt.wantData); err != nil {
t.Errorf("Wellformed() returned error %v", err)
}
}
}
func TestValidExtraneousData(t *testing.T) {
testCases := []struct {
name string
data []byte
extraneousDataNumOfBytes int
extraneousDataIndex int
}{
{
name: "two numbers",
data: []byte{0x00, 0x01},
extraneousDataNumOfBytes: 1,
extraneousDataIndex: 1,
}, // 0, 1
{
name: "bytestring and int",
data: []byte{0x44, 0x01, 0x02, 0x03, 0x04, 0x00},
extraneousDataNumOfBytes: 1,
extraneousDataIndex: 5,
}, // h'01020304', 0
{
name: "int and partial array",
data: []byte{0x00, 0x83, 0x01, 0x02},
extraneousDataNumOfBytes: 3,
extraneousDataIndex: 1,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := Wellformed(tc.data)
if err == nil {
t.Errorf("Wellformed(0x%x) didn't return an error", tc.data)
} else {
ederr, ok := err.(*ExtraneousDataError)
if !ok {
t.Errorf("Wellformed(0x%x) error type %T, want *ExtraneousDataError", tc.data, err)
} else if ederr.numOfBytes != tc.extraneousDataNumOfBytes {
t.Errorf("Wellformed(0x%x) returned %d bytes of extraneous data, want %d", tc.data, ederr.numOfBytes, tc.extraneousDataNumOfBytes)
} else if ederr.index != tc.extraneousDataIndex {
t.Errorf("Wellformed(0x%x) returned extraneous data index %d, want %d", tc.data, ederr.index, tc.extraneousDataIndex)
}
}
})
}
}
func TestValidOnStreamingData(t *testing.T) {
var buf bytes.Buffer
for _, t := range marshalTests {
buf.Write(t.wantData)
}
d := decoder{data: buf.Bytes(), dm: defaultDecMode}
for i := 0; i < len(marshalTests); i++ {
if err := d.wellformed(true, false); err != nil {
t.Errorf("wellformed() returned error %v", err)
}
}
}
func TestDepth(t *testing.T) {
testCases := []struct {
name string
data []byte
wantDepth int
}{
{
name: "uint",
data: mustHexDecode("00"),
wantDepth: 0,
}, // 0
{
name: "int",
data: mustHexDecode("20"),
wantDepth: 0,
}, // -1
{
name: "bool",
data: mustHexDecode("f4"),
wantDepth: 0,
}, // false
{
name: "nil",
data: mustHexDecode("f6"),
wantDepth: 0,
}, // nil
{
name: "float",
data: mustHexDecode("fa47c35000"),
wantDepth: 0,
}, // 100000.0
{
name: "byte string",
data: mustHexDecode("40"),
wantDepth: 0,
}, // []byte{}
{
name: "indefinite length byte string",
data: mustHexDecode("5f42010243030405ff"),
wantDepth: 0,
}, // []byte{1, 2, 3, 4, 5}
{
name: "text string",
data: mustHexDecode("60"),
wantDepth: 0,
}, // ""
{
name: "indefinite length text string",
data: mustHexDecode("7f657374726561646d696e67ff"),
wantDepth: 0,
}, // "streaming"
{
name: "empty array",
data: mustHexDecode("80"),
wantDepth: 1,
}, // []
{
name: "indefinite length empty array",
data: mustHexDecode("9fff"),
wantDepth: 1,
}, // []
{
name: "array",
data: mustHexDecode("98190102030405060708090a0b0c0d0e0f101112131415161718181819"),
wantDepth: 1,
}, // [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]
{
name: "indefinite length array",
data: mustHexDecode("9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff"),
wantDepth: 1,
}, // [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]
{
name: "nested array",
data: mustHexDecode("8301820203820405"),
wantDepth: 2,
}, // [1,[2,3],[4,5]]
{
name: "indefinite length nested array",
data: mustHexDecode("83018202039f0405ff"),
wantDepth: 2,
}, // [1,[2,3],[4,5]]
{
name: "array and map",
data: mustHexDecode("826161a161626163"),
wantDepth: 2,
}, // [a", {"b": "c"}]
{
name: "indefinite length array and map",
data: mustHexDecode("826161bf61626163ff"),
wantDepth: 2,
}, // [a", {"b": "c"}]
{
name: "empty map",
data: mustHexDecode("a0"),
wantDepth: 1,
}, // {}
{
name: "indefinite length empty map",
data: mustHexDecode("bfff"),
wantDepth: 1,
}, // {}
{
name: "map",
data: mustHexDecode("a201020304"),
wantDepth: 1,
}, // {1:2, 3:4}
{
name: "nested map",
data: mustHexDecode("a26161016162820203"),
wantDepth: 2,
}, // {"a": 1, "b": [2, 3]}
{
name: "indefinite length nested map",
data: mustHexDecode("bf61610161629f0203ffff"),
wantDepth: 2,
}, // {"a": 1, "b": [2, 3]}
{
name: "tag",
data: mustHexDecode("c074323031332d30332d32315432303a30343a30305a"),
wantDepth: 0,
}, // 0("2013-03-21T20:04:00Z")
{
name: "tagged map",
data: mustHexDecode("d864a26161016162820203"),
wantDepth: 2,
}, // 100({"a": 1, "b": [2, 3]})
{
name: "tagged map and array",
data: mustHexDecode("d864a26161016162d865820203"),
wantDepth: 2,
}, // 100({"a": 1, "b": 101([2, 3])})
{
name: "tagged map and array",
data: mustHexDecode("d864a26161016162d865d866820203"),
wantDepth: 3,
}, // 100({"a": 1, "b": 101(102([2, 3]))})
{
name: "nested tag",
data: mustHexDecode("d864d865d86674323031332d30332d32315432303a30343a30305a"),
wantDepth: 2,
}, // 100(101(102("2013-03-21T20:04:00Z")))
{
name: "32-level array",
data: mustHexDecode("82018181818181818181818181818181818181818181818181818181818181818101"),
wantDepth: 32,
},
{
name: "32-level indefinite length array",
data: mustHexDecode("9f018181818181818181818181818181818181818181818181818181818181818101ff"),
wantDepth: 32,
},
{
name: "32-level map",
data: mustHexDecode("a1018181818181818181818181818181818181818181818181818181818181818101"),
wantDepth: 32,
},
{
name: "32-level indefinite length map",
data: mustHexDecode("bf018181818181818181818181818181818181818181818181818181818181818101ff"),
wantDepth: 32,
},
{
name: "32-level tag",
data: mustHexDecode("d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d86474323031332d30332d32315432303a30343a30305a"),
wantDepth: 32,
}, // 100(100(...("2013-03-21T20:04:00Z")))
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
d := decoder{data: tc.data, dm: defaultDecMode}
depth, err := d.wellformedInternal(0, false)
if err != nil {
t.Errorf("wellformed(0x%x) returned error %v", tc.data, err)
}
if depth != tc.wantDepth {
t.Errorf("wellformed(0x%x) returned depth %d, want %d", tc.data, depth, tc.wantDepth)
}
})
}
}
func TestDepthError(t *testing.T) {
testCases := []struct {
name string
data []byte
opts DecOptions
wantErrorMsg string
}{
{
name: "33-level array",
data: mustHexDecode("82018181818181818181818181818181818181818181818181818181818181818101"),
opts: DecOptions{MaxNestedLevels: 4},
wantErrorMsg: "cbor: exceeded max nested level 4",
},
{
name: "33-level array",
data: mustHexDecode("82018181818181818181818181818181818181818181818181818181818181818101"),
opts: DecOptions{MaxNestedLevels: 10},
wantErrorMsg: "cbor: exceeded max nested level 10",
},
{
name: "33-level array",
data: mustHexDecode("8201818181818181818181818181818181818181818181818181818181818181818101"),
opts: DecOptions{},
wantErrorMsg: "cbor: exceeded max nested level 32",
},
{
name: "33-level indefinite length array",
data: mustHexDecode("9f01818181818181818181818181818181818181818181818181818181818181818101ff"),
opts: DecOptions{},
wantErrorMsg: "cbor: exceeded max nested level 32",
},
{
name: "33-level map",
data: mustHexDecode("a101818181818181818181818181818181818181818181818181818181818181818101"),
opts: DecOptions{},
wantErrorMsg: "cbor: exceeded max nested level 32",
},
{
name: "33-level indefinite length map",
data: mustHexDecode("bf01818181818181818181818181818181818181818181818181818181818181818101ff"),
opts: DecOptions{},
wantErrorMsg: "cbor: exceeded max nested level 32",
},
{
name: "33-level tag",
data: mustHexDecode("d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d86474323031332d30332d32315432303a30343a30305a"),
opts: DecOptions{},
wantErrorMsg: "cbor: exceeded max nested level 32",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
dm, _ := tc.opts.decMode()
d := decoder{data: tc.data, dm: dm}
if _, err := d.wellformedInternal(0, false); err == nil {
t.Errorf("wellformed(0x%x) didn't return an error", tc.data)
} else if _, ok := err.(*MaxNestedLevelError); !ok {
t.Errorf("wellformed(0x%x) returned wrong error type %T, want (*MaxNestedLevelError)", tc.data, err)
} else if err.Error() != tc.wantErrorMsg {
t.Errorf("wellformed(0x%x) returned error %q, want error %q", tc.data, err.Error(), tc.wantErrorMsg)
}
})
}
}
func TestValidBuiltinTagTest(t *testing.T) {
testCases := []struct {
name string
data []byte
}{
{
name: "tag 0",
data: mustHexDecode("c074323031332d30332d32315432303a30343a30305a"),
},
{
name: "tag 1",
data: mustHexDecode("c11a514b67b0"),
},
{
name: "tag 2",
data: mustHexDecode("c249010000000000000000"),
},
{
name: "tag 3",
data: mustHexDecode("c349010000000000000000"),
},
{
name: "nested tag 0",
data: mustHexDecode("d9d9f7c074323031332d30332d32315432303a30343a30305a"),
},
{
name: "nested tag 1",
data: mustHexDecode("d9d9f7c11a514b67b0"),
},
{
name: "nested tag 2",
data: mustHexDecode("d9d9f7c249010000000000000000"),
},
{
name: "nested tag 3",
data: mustHexDecode("d9d9f7c349010000000000000000"),
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
d := decoder{data: tc.data, dm: defaultDecMode}
if err := d.wellformed(true, true); err != nil {
t.Errorf("wellformed(0x%x) returned error %v", tc.data, err)
}
})
}
}
func TestInvalidBuiltinTagTest(t *testing.T) {
testCases := []struct {
name string
data []byte
wantErrorMsg string
}{
{
name: "tag 0",
data: mustHexDecode("c01a514b67b0"),
wantErrorMsg: "cbor: tag number 0 must be followed by text string, got positive integer",
},
{
name: "tag 1",
data: mustHexDecode("c174323031332d30332d32315432303a30343a30305a"),
wantErrorMsg: "cbor: tag number 1 must be followed by integer or floating-point number, got UTF-8 text string",
},
{
name: "tag 2",
data: mustHexDecode("c269010000000000000000"),
wantErrorMsg: "cbor: tag number 2 or 3 must be followed by byte string, got UTF-8 text string",
},
{
name: "tag 3",
data: mustHexDecode("c300"),
wantErrorMsg: "cbor: tag number 2 or 3 must be followed by byte string, got positive integer",
},
{
name: "nested tag 0",
data: mustHexDecode("d9d9f7c01a514b67b0"),
wantErrorMsg: "cbor: tag number 0 must be followed by text string, got positive integer",
},
{
name: "nested tag 1",
data: mustHexDecode("d9d9f7c174323031332d30332d32315432303a30343a30305a"),
wantErrorMsg: "cbor: tag number 1 must be followed by integer or floating-point number, got UTF-8 text string",
},
{
name: "nested tag 2",
data: mustHexDecode("d9d9f7c269010000000000000000"),
wantErrorMsg: "cbor: tag number 2 or 3 must be followed by byte string, got UTF-8 text string",
},
{
name: "nested tag 3",
data: mustHexDecode("d9d9f7c300"),
wantErrorMsg: "cbor: tag number 2 or 3 must be followed by byte string, got positive integer",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
d := decoder{data: tc.data, dm: defaultDecMode}
err := d.wellformed(true, true)
if err == nil {
t.Errorf("wellformed(0x%x) didn't return an error", tc.data)
} else if err.Error() != tc.wantErrorMsg {
t.Errorf("wellformed(0x%x) error %q, want %q", tc.data, err.Error(), tc.wantErrorMsg)
}
})
}
}