dex/vendor/gopkg.in/asn1-ber.v1/identifier_test.go
2016-07-26 15:51:24 -07:00

345 lines
10 KiB
Go

package ber
import (
"bytes"
"io"
"math"
"testing"
)
func TestReadIdentifier(t *testing.T) {
testcases := map[string]struct {
Data []byte
ExpectedIdentifier Identifier
ExpectedBytesRead int
ExpectedError string
}{
"empty": {
Data: []byte{},
ExpectedBytesRead: 0,
ExpectedError: io.ErrUnexpectedEOF.Error(),
},
"universal primitive eoc": {
Data: []byte{byte(ClassUniversal) | byte(TypePrimitive) | byte(TagEOC)},
ExpectedIdentifier: Identifier{
ClassType: ClassUniversal,
TagType: TypePrimitive,
Tag: TagEOC,
},
ExpectedBytesRead: 1,
},
"universal primitive character string": {
Data: []byte{byte(ClassUniversal) | byte(TypePrimitive) | byte(TagCharacterString)},
ExpectedIdentifier: Identifier{
ClassType: ClassUniversal,
TagType: TypePrimitive,
Tag: TagCharacterString,
},
ExpectedBytesRead: 1,
},
"universal constructed bit string": {
Data: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(TagBitString)},
ExpectedIdentifier: Identifier{
ClassType: ClassUniversal,
TagType: TypeConstructed,
Tag: TagBitString,
},
ExpectedBytesRead: 1,
},
"universal constructed character string": {
Data: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(TagCharacterString)},
ExpectedIdentifier: Identifier{
ClassType: ClassUniversal,
TagType: TypeConstructed,
Tag: TagCharacterString,
},
ExpectedBytesRead: 1,
},
"application constructed object descriptor": {
Data: []byte{byte(ClassApplication) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
ExpectedIdentifier: Identifier{
ClassType: ClassApplication,
TagType: TypeConstructed,
Tag: TagObjectDescriptor,
},
ExpectedBytesRead: 1,
},
"context constructed object descriptor": {
Data: []byte{byte(ClassContext) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
ExpectedIdentifier: Identifier{
ClassType: ClassContext,
TagType: TypeConstructed,
Tag: TagObjectDescriptor,
},
ExpectedBytesRead: 1,
},
"private constructed object descriptor": {
Data: []byte{byte(ClassPrivate) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
ExpectedIdentifier: Identifier{
ClassType: ClassPrivate,
TagType: TypeConstructed,
Tag: TagObjectDescriptor,
},
ExpectedBytesRead: 1,
},
"high-tag-number tag missing bytes": {
Data: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag)},
ExpectedError: io.ErrUnexpectedEOF.Error(),
ExpectedBytesRead: 1,
},
"high-tag-number tag invalid first byte": {
Data: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag), 0x0},
ExpectedError: "invalid first high-tag-number tag byte",
ExpectedBytesRead: 2,
},
"high-tag-number tag invalid first byte with continue bit": {
Data: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag), byte(HighTagContinueBitmask)},
ExpectedError: "invalid first high-tag-number tag byte",
ExpectedBytesRead: 2,
},
"high-tag-number tag continuation missing bytes": {
Data: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag), byte(HighTagContinueBitmask | 0x1)},
ExpectedError: io.ErrUnexpectedEOF.Error(),
ExpectedBytesRead: 2,
},
"high-tag-number tag overflow": {
Data: []byte{
byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
byte(HighTagContinueBitmask | 0x1),
byte(HighTagContinueBitmask | 0x1),
byte(HighTagContinueBitmask | 0x1),
byte(HighTagContinueBitmask | 0x1),
byte(HighTagContinueBitmask | 0x1),
byte(HighTagContinueBitmask | 0x1),
byte(HighTagContinueBitmask | 0x1),
byte(HighTagContinueBitmask | 0x1),
byte(HighTagContinueBitmask | 0x1),
byte(0x1),
},
ExpectedError: "high-tag-number tag overflow",
ExpectedBytesRead: 11,
},
"max high-tag-number tag": {
Data: []byte{
byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(0x7f),
},
ExpectedIdentifier: Identifier{
ClassType: ClassUniversal,
TagType: TypeConstructed,
Tag: Tag(0x7FFFFFFFFFFFFFFF), // 01111111...(63)...11111b
},
ExpectedBytesRead: 10,
},
"high-tag-number encoding of low-tag value": {
Data: []byte{
byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
byte(TagObjectDescriptor),
},
ExpectedIdentifier: Identifier{
ClassType: ClassUniversal,
TagType: TypeConstructed,
Tag: TagObjectDescriptor,
},
ExpectedBytesRead: 2,
},
"max high-tag-number tag ignores extra data": {
Data: []byte{
byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(0x7f),
byte(0x01), // extra data, shouldn't be read
byte(0x02), // extra data, shouldn't be read
byte(0x03), // extra data, shouldn't be read
},
ExpectedIdentifier: Identifier{
ClassType: ClassUniversal,
TagType: TypeConstructed,
Tag: Tag(0x7FFFFFFFFFFFFFFF), // 01111111...(63)...11111b
},
ExpectedBytesRead: 10,
},
}
for k, tc := range testcases {
reader := bytes.NewBuffer(tc.Data)
identifier, read, err := readIdentifier(reader)
if err != nil {
if tc.ExpectedError == "" {
t.Errorf("%s: unexpected error: %v", k, err)
} else if err.Error() != tc.ExpectedError {
t.Errorf("%s: expected error %v, got %v", k, tc.ExpectedError, err)
}
} else if tc.ExpectedError != "" {
t.Errorf("%s: expected error %v, got none", k, tc.ExpectedError)
continue
}
if read != tc.ExpectedBytesRead {
t.Errorf("%s: expected read %d, got %d", k, tc.ExpectedBytesRead, read)
}
if identifier.ClassType != tc.ExpectedIdentifier.ClassType {
t.Errorf("%s: expected class type %d (%s), got %d (%s)", k,
tc.ExpectedIdentifier.ClassType,
ClassMap[tc.ExpectedIdentifier.ClassType],
identifier.ClassType,
ClassMap[identifier.ClassType],
)
}
if identifier.TagType != tc.ExpectedIdentifier.TagType {
t.Errorf("%s: expected tag type %d (%s), got %d (%s)", k,
tc.ExpectedIdentifier.TagType,
TypeMap[tc.ExpectedIdentifier.TagType],
identifier.TagType,
TypeMap[identifier.TagType],
)
}
if identifier.Tag != tc.ExpectedIdentifier.Tag {
t.Errorf("%s: expected tag %d (%s), got %d (%s)", k,
tc.ExpectedIdentifier.Tag,
tagMap[tc.ExpectedIdentifier.Tag],
identifier.Tag,
tagMap[identifier.Tag],
)
}
}
}
func TestEncodeIdentifier(t *testing.T) {
testcases := map[string]struct {
Identifier Identifier
ExpectedBytes []byte
}{
"universal primitive eoc": {
Identifier: Identifier{
ClassType: ClassUniversal,
TagType: TypePrimitive,
Tag: TagEOC,
},
ExpectedBytes: []byte{byte(ClassUniversal) | byte(TypePrimitive) | byte(TagEOC)},
},
"universal primitive character string": {
Identifier: Identifier{
ClassType: ClassUniversal,
TagType: TypePrimitive,
Tag: TagCharacterString,
},
ExpectedBytes: []byte{byte(ClassUniversal) | byte(TypePrimitive) | byte(TagCharacterString)},
},
"universal constructed bit string": {
Identifier: Identifier{
ClassType: ClassUniversal,
TagType: TypeConstructed,
Tag: TagBitString,
},
ExpectedBytes: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(TagBitString)},
},
"universal constructed character string": {
Identifier: Identifier{
ClassType: ClassUniversal,
TagType: TypeConstructed,
Tag: TagCharacterString,
},
ExpectedBytes: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(TagCharacterString)},
},
"application constructed object descriptor": {
Identifier: Identifier{
ClassType: ClassApplication,
TagType: TypeConstructed,
Tag: TagObjectDescriptor,
},
ExpectedBytes: []byte{byte(ClassApplication) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
},
"context constructed object descriptor": {
Identifier: Identifier{
ClassType: ClassContext,
TagType: TypeConstructed,
Tag: TagObjectDescriptor,
},
ExpectedBytes: []byte{byte(ClassContext) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
},
"private constructed object descriptor": {
Identifier: Identifier{
ClassType: ClassPrivate,
TagType: TypeConstructed,
Tag: TagObjectDescriptor,
},
ExpectedBytes: []byte{byte(ClassPrivate) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
},
"max low-tag-number tag": {
Identifier: Identifier{
ClassType: ClassUniversal,
TagType: TypeConstructed,
Tag: TagBMPString,
},
ExpectedBytes: []byte{
byte(ClassUniversal) | byte(TypeConstructed) | byte(TagBMPString),
},
},
"min high-tag-number tag": {
Identifier: Identifier{
ClassType: ClassUniversal,
TagType: TypeConstructed,
Tag: TagBMPString + 1,
},
ExpectedBytes: []byte{
byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
byte(TagBMPString + 1),
},
},
"max high-tag-number tag": {
Identifier: Identifier{
ClassType: ClassUniversal,
TagType: TypeConstructed,
Tag: Tag(math.MaxInt64),
},
ExpectedBytes: []byte{
byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(HighTagContinueBitmask | 0x7f),
byte(0x7f),
},
},
}
for k, tc := range testcases {
b := encodeIdentifier(tc.Identifier)
if bytes.Compare(tc.ExpectedBytes, b) != 0 {
t.Errorf("%s: Expected\n\t%#v\ngot\n\t%#v", k, tc.ExpectedBytes, b)
}
}
}