Merge pull request #124324 from benluddy/cbor-decode-tests-grouped-by-cbor-type

KEP-4222: Group CBOR decode tests by the kind of their inputs.
This commit is contained in:
Kubernetes Prow Robot 2024-04-18 04:24:41 -07:00 committed by GitHub
commit 77f7d1b89d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -37,14 +37,99 @@ func TestDecode(t *testing.T) {
return b return b
} }
for _, tc := range []struct { type test struct {
name string name string
modes []cbor.DecMode modes []cbor.DecMode // most tests should run for all modes
in []byte in []byte
into interface{} // prototype for concrete destination type. if nil, decode into empty interface value. into interface{} // prototype for concrete destination type. if nil, decode into empty interface value.
want interface{} want interface{}
assertOnError func(t *testing.T, e error) assertOnError func(t *testing.T, e error)
}{ }
// Test cases are grouped by the kind of the CBOR data item being decoded, as enumerated in
// https://www.rfc-editor.org/rfc/rfc8949.html#section-2.
group := func(t *testing.T, name string, tests []test) {
t.Run(name, func(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
decModes := test.modes
if len(decModes) == 0 {
decModes = allDecModes
}
for _, decMode := range decModes {
modeName, ok := decModeNames[decMode]
if !ok {
t.Fatal("test case configured to run against unrecognized mode")
}
t.Run(fmt.Sprintf("%s/mode=%s", test.name, modeName), func(t *testing.T) {
var dst reflect.Value
if test.into == nil {
var i interface{}
dst = reflect.ValueOf(&i)
} else {
dst = reflect.New(reflect.TypeOf(test.into))
}
err := decMode.Unmarshal(test.in, dst.Interface())
test.assertOnError(t, err)
if test.want != nil {
if diff := cmp.Diff(test.want, dst.Elem().Interface()); diff != "" {
t.Errorf("unexpected output:\n%s", diff)
}
}
})
}
})
}
})
}
group(t, "unsigned integer", []test{
{
name: "unsigned integer decodes to interface{} as int64",
in: hex("0a"), // 10
want: int64(10),
assertOnError: assertNilError,
},
})
group(t, "negative integer", []test{})
group(t, "byte string", []test{})
group(t, "text string", []test{
{
name: "reject text string containing invalid utf-8 sequence",
in: hex("6180"), // text string beginning with continuation byte 0x80
assertOnError: assertOnConcreteError(func(t *testing.T, e *cbor.SemanticError) {
const expected = "cbor: invalid UTF-8 string"
if msg := e.Error(); msg != expected {
t.Errorf("expected %v, got %v", expected, msg)
}
}),
},
{
name: "indefinite-length text string",
in: hex("7f616161626163ff"), // (_ "a", "b", "c")
want: "abc",
assertOnError: assertNilError,
},
})
group(t, "array", []test{
{
name: "nested indefinite-length array",
in: hex("9f9f8080ff9f8080ffff"), // [_ [_ [] []] [_ [][]]]
want: []interface{}{
[]interface{}{[]interface{}{}, []interface{}{}},
[]interface{}{[]interface{}{}, []interface{}{}},
},
assertOnError: assertNilError,
},
})
group(t, "map", []test{
{ {
name: "reject duplicate negative int keys into struct", name: "reject duplicate negative int keys into struct",
modes: []cbor.DecMode{modes.DecodeLax}, modes: []cbor.DecMode{modes.DecodeLax},
@ -216,22 +301,6 @@ func TestDecode(t *testing.T) {
}, },
assertOnError: assertNilError, assertOnError: assertNilError,
}, },
{
name: "reject text string containing invalid utf-8 sequence",
in: hex("6180"), // text string beginning with continuation byte 0x80
assertOnError: assertOnConcreteError(func(t *testing.T, e *cbor.SemanticError) {
const expected = "cbor: invalid UTF-8 string"
if msg := e.Error(); msg != expected {
t.Errorf("expected %v, got %v", expected, msg)
}
}),
},
{
name: "unsigned integer decodes to interface{} as int64",
in: hex("0a"), // 10
want: int64(10),
assertOnError: assertNilError,
},
{ {
name: "unknown field error", name: "unknown field error",
modes: []cbor.DecMode{modes.Decode}, modes: []cbor.DecMode{modes.Decode},
@ -251,21 +320,6 @@ func TestDecode(t *testing.T) {
want: struct{}{}, want: struct{}{},
assertOnError: assertNilError, assertOnError: assertNilError,
}, },
{
name: "indefinite-length text string",
in: hex("7f616161626163ff"), // (_ "a", "b", "c")
want: "abc",
assertOnError: assertNilError,
},
{
name: "nested indefinite-length array",
in: hex("9f9f8080ff9f8080ffff"), // [_ [_ [] []] [_ [][]]]
want: []interface{}{
[]interface{}{[]interface{}{}, []interface{}{}},
[]interface{}{[]interface{}{}, []interface{}{}},
},
assertOnError: assertNilError,
},
{ {
name: "nested indefinite-length map", name: "nested indefinite-length map",
in: hex("bf6141bf616101616202ff6142bf616901616a02ffff"), // {_ "A": {_ "a": 1, "b": 2}, "B": {_ "i": 1, "j": 2}} in: hex("bf6141bf616101616202ff6142bf616901616a02ffff"), // {_ "A": {_ "a": 1, "b": 2}, "B": {_ "i": 1, "j": 2}}
@ -275,34 +329,21 @@ func TestDecode(t *testing.T) {
}, },
assertOnError: assertNilError, assertOnError: assertNilError,
}, },
} { })
decModes := tc.modes
if len(decModes) == 0 {
decModes = allDecModes
}
for _, decMode := range decModes { group(t, "floating-point number", []test{})
modeName, ok := decModeNames[decMode]
if !ok {
t.Fatal("test case configured to run against unrecognized mode")
}
t.Run(fmt.Sprintf("mode=%s/%s", modeName, tc.name), func(t *testing.T) { group(t, "simple value", []test{})
var dst reflect.Value
if tc.into == nil { t.Run("tag", func(t *testing.T) {
var i interface{} group(t, "rfc3339 time", []test{})
dst = reflect.ValueOf(&i)
} else { group(t, "epoch time", []test{})
dst = reflect.New(reflect.TypeOf(tc.into))
} group(t, "unsigned bignum", []test{})
err := decMode.Unmarshal(tc.in, dst.Interface())
tc.assertOnError(t, err) group(t, "negative bignum", []test{})
if tc.want != nil {
if diff := cmp.Diff(tc.want, dst.Elem().Interface()); diff != "" { group(t, "unrecognized", []test{})
t.Errorf("unexpected output:\n%s", diff) })
}
}
})
}
}
} }