mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-18 08:09:58 +00:00
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:
commit
77f7d1b89d
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user