cbor/simplevalue_test.go
Faye Amacker bfcaa814f5 Fix cbor.SimpleValue encoding and decoding
This commit resolves two issues:

1.  Encoding cbor.SimpleValue with values 24..31 should fail because
CBOR simple values 24..31 are reserved and they MUST NOT be encoded
according to RFC 8949.

This commit makes encoder return UnsupportedValueError when encoding
cbor.SimpleValue with values 24..31 because that would not be
a well-formed CBOR data item.

2. Decoding other CBOR types to cbor.SimpleValue should fail because
cbor.SimpleValue represents CBOR simple value (major type 7) which is
different from CBOR integers and shouldn't be used interchangeably.

This commit makes decoder return UnmarshalTypeError when decoding
other CBOR types to cbor.SimpleValue.
2024-01-01 18:59:19 -06:00

178 lines
4.7 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"
"reflect"
"testing"
)
func TestUnmarshalSimpleValue(t *testing.T) {
t.Run("0..23", func(t *testing.T) {
for i := 0; i <= 23; i++ {
data := []byte{byte(cborTypePrimitives) | byte(i)}
want := SimpleValue(i)
switch i {
case 20: // false
testUnmarshalSimpleValueToEmptyInterface(t, data, false)
case 21: // true
testUnmarshalSimpleValueToEmptyInterface(t, data, true)
case 22: // null
testUnmarshalSimpleValueToEmptyInterface(t, data, nil)
case 23: // undefined
testUnmarshalSimpleValueToEmptyInterface(t, data, nil)
default:
testUnmarshalSimpleValueToEmptyInterface(t, data, want)
}
testUnmarshalSimpleValue(t, data, want)
}
})
t.Run("24..31", func(t *testing.T) {
for i := 24; i <= 31; i++ {
data := []byte{byte(cborTypePrimitives) | byte(24), byte(i)}
testUnmarshalInvalidSimpleValueToEmptyInterface(t, data)
testUnmarshalInvalidSimpleValue(t, data)
}
})
t.Run("32..255", func(t *testing.T) {
for i := 32; i <= 255; i++ {
data := []byte{byte(cborTypePrimitives) | byte(24), byte(i)}
want := SimpleValue(i)
testUnmarshalSimpleValueToEmptyInterface(t, data, want)
testUnmarshalSimpleValue(t, data, want)
}
})
}
func testUnmarshalInvalidSimpleValueToEmptyInterface(t *testing.T, data []byte) {
var v interface{}
if err := Unmarshal(data, v); err == nil {
t.Errorf("Unmarshal(0x%x) didn't return an error", data)
} else if _, ok := err.(*SyntaxError); !ok {
t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*SyntaxError)", data, err)
}
}
func testUnmarshalInvalidSimpleValue(t *testing.T, data []byte) {
var v SimpleValue
if err := Unmarshal(data, v); err == nil {
t.Errorf("Unmarshal(0x%x) didn't return an error", data)
} else if _, ok := err.(*SyntaxError); !ok {
t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*SyntaxError)", data, err)
}
}
func testUnmarshalSimpleValueToEmptyInterface(t *testing.T, data []byte, want interface{}) {
var v interface{}
if err := Unmarshal(data, &v); err != nil {
t.Errorf("Unmarshal(0x%x) returned error %v", data, err)
return
}
if !reflect.DeepEqual(v, want) {
t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", data, v, v, want, want)
}
}
func testUnmarshalSimpleValue(t *testing.T, data []byte, want SimpleValue) {
cborNil := isCBORNil(data)
// Decode to SimpleValue
var v SimpleValue
err := Unmarshal(data, &v)
if err != nil {
t.Errorf("Unmarshal(0x%x) returned error %v", data, err)
return
}
if !reflect.DeepEqual(v, want) {
t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", data, v, v, want, want)
}
// Decode to uninitialized *SimpleValue
var pv *SimpleValue
err = Unmarshal(data, &pv)
if err != nil {
t.Errorf("Unmarshal(0x%x) returned error %v", data, err)
return
}
if cborNil {
if pv != nil {
t.Errorf("Unmarshal(0x%x) returned %v, want nil *SimpleValue", data, *pv)
}
} else {
if !reflect.DeepEqual(*pv, want) {
t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", data, *pv, *pv, want, want)
}
}
// Decode to initialized *SimpleValue
v = SimpleValue(0)
pv = &v
err = Unmarshal(data, &pv)
if err != nil {
t.Errorf("Unmarshal(0x%x) returned error %v", data, err)
return
}
if cborNil {
if pv != nil {
t.Errorf("Unmarshal(0x%x) returned %v, want nil *SimpleValue", data, *pv)
}
} else {
if !reflect.DeepEqual(v, want) {
t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", data, v, v, want, want)
}
}
}
func TestMarshalSimpleValue(t *testing.T) {
t.Run("0..23", func(t *testing.T) {
for i := 0; i <= 23; i++ {
wantData := []byte{byte(cborTypePrimitives) | byte(i)}
v := SimpleValue(i)
data, err := Marshal(v)
if err != nil {
t.Errorf("Marshal(%v) returned error %v", v, err)
continue
}
if !bytes.Equal(data, wantData) {
t.Errorf("Marshal(%v) = 0x%x, want 0x%x", v, data, wantData)
}
}
})
t.Run("24..31", func(t *testing.T) {
for i := 24; i <= 31; i++ {
v := SimpleValue(i)
if data, err := Marshal(v); err == nil {
t.Errorf("Marshal(%v) didn't return an error", data)
} else if _, ok := err.(*UnsupportedValueError); !ok {
t.Errorf("Marshal(%v) returned wrong error type %T, want (*UnsupportedValueError)", data, err)
}
}
})
t.Run("32..255", func(t *testing.T) {
for i := 32; i <= 255; i++ {
wantData := []byte{byte(cborTypePrimitives) | byte(24), byte(i)}
v := SimpleValue(i)
data, err := Marshal(v)
if err != nil {
t.Errorf("Marshal(%v) returned error %v", v, err)
continue
}
if !bytes.Equal(data, wantData) {
t.Errorf("Marshal(%v) = 0x%x, want 0x%x", v, data, wantData)
}
}
})
}