...

Source file src/github.com/go-asn1-ber/asn1-ber/identifier_test.go

Documentation: github.com/go-asn1-ber/asn1-ber

     1  package ber
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"math"
     7  	"testing"
     8  )
     9  
    10  func TestReadIdentifier(t *testing.T) {
    11  	testCases := map[string]struct {
    12  		Data []byte
    13  
    14  		ExpectedIdentifier Identifier
    15  		ExpectedBytesRead  int
    16  		ExpectedError      string
    17  	}{
    18  		"empty": {
    19  			Data:              []byte{},
    20  			ExpectedBytesRead: 0,
    21  			ExpectedError:     io.EOF.Error(),
    22  		},
    23  
    24  		"universal primitive eoc": {
    25  			Data: []byte{byte(ClassUniversal) | byte(TypePrimitive) | byte(TagEOC)},
    26  			ExpectedIdentifier: Identifier{
    27  				ClassType: ClassUniversal,
    28  				TagType:   TypePrimitive,
    29  				Tag:       TagEOC,
    30  			},
    31  			ExpectedBytesRead: 1,
    32  		},
    33  		"universal primitive character string": {
    34  			Data: []byte{byte(ClassUniversal) | byte(TypePrimitive) | byte(TagCharacterString)},
    35  			ExpectedIdentifier: Identifier{
    36  				ClassType: ClassUniversal,
    37  				TagType:   TypePrimitive,
    38  				Tag:       TagCharacterString,
    39  			},
    40  			ExpectedBytesRead: 1,
    41  		},
    42  
    43  		"universal constructed bit string": {
    44  			Data: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(TagBitString)},
    45  			ExpectedIdentifier: Identifier{
    46  				ClassType: ClassUniversal,
    47  				TagType:   TypeConstructed,
    48  				Tag:       TagBitString,
    49  			},
    50  			ExpectedBytesRead: 1,
    51  		},
    52  		"universal constructed character string": {
    53  			Data: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(TagCharacterString)},
    54  			ExpectedIdentifier: Identifier{
    55  				ClassType: ClassUniversal,
    56  				TagType:   TypeConstructed,
    57  				Tag:       TagCharacterString,
    58  			},
    59  			ExpectedBytesRead: 1,
    60  		},
    61  
    62  		"application constructed object descriptor": {
    63  			Data: []byte{byte(ClassApplication) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
    64  			ExpectedIdentifier: Identifier{
    65  				ClassType: ClassApplication,
    66  				TagType:   TypeConstructed,
    67  				Tag:       TagObjectDescriptor,
    68  			},
    69  			ExpectedBytesRead: 1,
    70  		},
    71  		"context constructed object descriptor": {
    72  			Data: []byte{byte(ClassContext) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
    73  			ExpectedIdentifier: Identifier{
    74  				ClassType: ClassContext,
    75  				TagType:   TypeConstructed,
    76  				Tag:       TagObjectDescriptor,
    77  			},
    78  			ExpectedBytesRead: 1,
    79  		},
    80  		"private constructed object descriptor": {
    81  			Data: []byte{byte(ClassPrivate) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
    82  			ExpectedIdentifier: Identifier{
    83  				ClassType: ClassPrivate,
    84  				TagType:   TypeConstructed,
    85  				Tag:       TagObjectDescriptor,
    86  			},
    87  			ExpectedBytesRead: 1,
    88  		},
    89  
    90  		"high-tag-number tag missing bytes": {
    91  			Data:              []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag)},
    92  			ExpectedError:     io.ErrUnexpectedEOF.Error(),
    93  			ExpectedBytesRead: 1,
    94  		},
    95  		"high-tag-number tag invalid first byte": {
    96  			Data:              []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag), 0x0},
    97  			ExpectedError:     "invalid first high-tag-number tag byte",
    98  			ExpectedBytesRead: 2,
    99  		},
   100  		"high-tag-number tag invalid first byte with continue bit": {
   101  			Data:              []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag), byte(HighTagContinueBitmask)},
   102  			ExpectedError:     "invalid first high-tag-number tag byte",
   103  			ExpectedBytesRead: 2,
   104  		},
   105  		"high-tag-number tag continuation missing bytes": {
   106  			Data:              []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag), byte(HighTagContinueBitmask | 0x1)},
   107  			ExpectedError:     io.ErrUnexpectedEOF.Error(),
   108  			ExpectedBytesRead: 2,
   109  		},
   110  		"high-tag-number tag overflow": {
   111  			Data: []byte{
   112  				byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
   113  				byte(HighTagContinueBitmask | 0x1),
   114  				byte(HighTagContinueBitmask | 0x1),
   115  				byte(HighTagContinueBitmask | 0x1),
   116  				byte(HighTagContinueBitmask | 0x1),
   117  				byte(HighTagContinueBitmask | 0x1),
   118  				byte(HighTagContinueBitmask | 0x1),
   119  				byte(HighTagContinueBitmask | 0x1),
   120  				byte(HighTagContinueBitmask | 0x1),
   121  				byte(HighTagContinueBitmask | 0x1),
   122  				byte(0x1),
   123  			},
   124  			ExpectedError:     "high-tag-number tag overflow",
   125  			ExpectedBytesRead: 11,
   126  		},
   127  		"max high-tag-number tag": {
   128  			Data: []byte{
   129  				byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
   130  				byte(HighTagContinueBitmask | 0x7f),
   131  				byte(HighTagContinueBitmask | 0x7f),
   132  				byte(HighTagContinueBitmask | 0x7f),
   133  				byte(HighTagContinueBitmask | 0x7f),
   134  				byte(HighTagContinueBitmask | 0x7f),
   135  				byte(HighTagContinueBitmask | 0x7f),
   136  				byte(HighTagContinueBitmask | 0x7f),
   137  				byte(HighTagContinueBitmask | 0x7f),
   138  				byte(0x7f),
   139  			},
   140  			ExpectedIdentifier: Identifier{
   141  				ClassType: ClassUniversal,
   142  				TagType:   TypeConstructed,
   143  				Tag:       Tag(0x7FFFFFFFFFFFFFFF), // 01111111...(63)...11111b
   144  			},
   145  			ExpectedBytesRead: 10,
   146  		},
   147  		"high-tag-number encoding of low-tag value": {
   148  			Data: []byte{
   149  				byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
   150  				byte(TagObjectDescriptor),
   151  			},
   152  			ExpectedIdentifier: Identifier{
   153  				ClassType: ClassUniversal,
   154  				TagType:   TypeConstructed,
   155  				Tag:       TagObjectDescriptor,
   156  			},
   157  			ExpectedBytesRead: 2,
   158  		},
   159  		"max high-tag-number tag ignores extra data": {
   160  			Data: []byte{
   161  				byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
   162  				byte(HighTagContinueBitmask | 0x7f),
   163  				byte(HighTagContinueBitmask | 0x7f),
   164  				byte(HighTagContinueBitmask | 0x7f),
   165  				byte(HighTagContinueBitmask | 0x7f),
   166  				byte(HighTagContinueBitmask | 0x7f),
   167  				byte(HighTagContinueBitmask | 0x7f),
   168  				byte(HighTagContinueBitmask | 0x7f),
   169  				byte(HighTagContinueBitmask | 0x7f),
   170  				byte(0x7f),
   171  				byte(0x01), // extra data, shouldn't be read
   172  				byte(0x02), // extra data, shouldn't be read
   173  				byte(0x03), // extra data, shouldn't be read
   174  			},
   175  			ExpectedIdentifier: Identifier{
   176  				ClassType: ClassUniversal,
   177  				TagType:   TypeConstructed,
   178  				Tag:       Tag(0x7FFFFFFFFFFFFFFF), // 01111111...(63)...11111b
   179  			},
   180  			ExpectedBytesRead: 10,
   181  		},
   182  	}
   183  
   184  	for k, tc := range testCases {
   185  		reader := bytes.NewBuffer(tc.Data)
   186  		identifier, read, err := readIdentifier(reader)
   187  
   188  		if err != nil {
   189  			if tc.ExpectedError == "" {
   190  				t.Errorf("%s: unexpected error: %v", k, err)
   191  			} else if err.Error() != tc.ExpectedError {
   192  				t.Errorf("%s: expected error %v, got %v", k, tc.ExpectedError, err)
   193  			}
   194  		} else if tc.ExpectedError != "" {
   195  			t.Errorf("%s: expected error %v, got none", k, tc.ExpectedError)
   196  			continue
   197  		}
   198  
   199  		if read != tc.ExpectedBytesRead {
   200  			t.Errorf("%s: expected read %d, got %d", k, tc.ExpectedBytesRead, read)
   201  		}
   202  
   203  		if identifier.ClassType != tc.ExpectedIdentifier.ClassType {
   204  			t.Errorf("%s: expected class type %d (%s), got %d (%s)", k,
   205  				tc.ExpectedIdentifier.ClassType,
   206  				ClassMap[tc.ExpectedIdentifier.ClassType],
   207  				identifier.ClassType,
   208  				ClassMap[identifier.ClassType],
   209  			)
   210  		}
   211  		if identifier.TagType != tc.ExpectedIdentifier.TagType {
   212  			t.Errorf("%s: expected tag type %d (%s), got %d (%s)", k,
   213  				tc.ExpectedIdentifier.TagType,
   214  				TypeMap[tc.ExpectedIdentifier.TagType],
   215  				identifier.TagType,
   216  				TypeMap[identifier.TagType],
   217  			)
   218  		}
   219  		if identifier.Tag != tc.ExpectedIdentifier.Tag {
   220  			t.Errorf("%s: expected tag %d (%s), got %d (%s)", k,
   221  				tc.ExpectedIdentifier.Tag,
   222  				tagMap[tc.ExpectedIdentifier.Tag],
   223  				identifier.Tag,
   224  				tagMap[identifier.Tag],
   225  			)
   226  		}
   227  	}
   228  }
   229  
   230  func TestEncodeIdentifier(t *testing.T) {
   231  	testCases := map[string]struct {
   232  		Identifier    Identifier
   233  		ExpectedBytes []byte
   234  	}{
   235  		"universal primitive eoc": {
   236  			Identifier: Identifier{
   237  				ClassType: ClassUniversal,
   238  				TagType:   TypePrimitive,
   239  				Tag:       TagEOC,
   240  			},
   241  			ExpectedBytes: []byte{byte(ClassUniversal) | byte(TypePrimitive) | byte(TagEOC)},
   242  		},
   243  		"universal primitive character string": {
   244  			Identifier: Identifier{
   245  				ClassType: ClassUniversal,
   246  				TagType:   TypePrimitive,
   247  				Tag:       TagCharacterString,
   248  			},
   249  			ExpectedBytes: []byte{byte(ClassUniversal) | byte(TypePrimitive) | byte(TagCharacterString)},
   250  		},
   251  
   252  		"universal constructed bit string": {
   253  			Identifier: Identifier{
   254  				ClassType: ClassUniversal,
   255  				TagType:   TypeConstructed,
   256  				Tag:       TagBitString,
   257  			},
   258  			ExpectedBytes: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(TagBitString)},
   259  		},
   260  		"universal constructed character string": {
   261  			Identifier: Identifier{
   262  				ClassType: ClassUniversal,
   263  				TagType:   TypeConstructed,
   264  				Tag:       TagCharacterString,
   265  			},
   266  			ExpectedBytes: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(TagCharacterString)},
   267  		},
   268  
   269  		"application constructed object descriptor": {
   270  			Identifier: Identifier{
   271  				ClassType: ClassApplication,
   272  				TagType:   TypeConstructed,
   273  				Tag:       TagObjectDescriptor,
   274  			},
   275  			ExpectedBytes: []byte{byte(ClassApplication) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
   276  		},
   277  		"context constructed object descriptor": {
   278  			Identifier: Identifier{
   279  				ClassType: ClassContext,
   280  				TagType:   TypeConstructed,
   281  				Tag:       TagObjectDescriptor,
   282  			},
   283  			ExpectedBytes: []byte{byte(ClassContext) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
   284  		},
   285  		"private constructed object descriptor": {
   286  			Identifier: Identifier{
   287  				ClassType: ClassPrivate,
   288  				TagType:   TypeConstructed,
   289  				Tag:       TagObjectDescriptor,
   290  			},
   291  			ExpectedBytes: []byte{byte(ClassPrivate) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
   292  		},
   293  
   294  		"max low-tag-number tag": {
   295  			Identifier: Identifier{
   296  				ClassType: ClassUniversal,
   297  				TagType:   TypeConstructed,
   298  				Tag:       TagBMPString,
   299  			},
   300  			ExpectedBytes: []byte{
   301  				byte(ClassUniversal) | byte(TypeConstructed) | byte(TagBMPString),
   302  			},
   303  		},
   304  
   305  		"min high-tag-number tag": {
   306  			Identifier: Identifier{
   307  				ClassType: ClassUniversal,
   308  				TagType:   TypeConstructed,
   309  				Tag:       TagBMPString + 1,
   310  			},
   311  			ExpectedBytes: []byte{
   312  				byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
   313  				byte(TagBMPString + 1),
   314  			},
   315  		},
   316  
   317  		"max high-tag-number tag": {
   318  			Identifier: Identifier{
   319  				ClassType: ClassUniversal,
   320  				TagType:   TypeConstructed,
   321  				Tag:       Tag(math.MaxInt64),
   322  			},
   323  			ExpectedBytes: []byte{
   324  				byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
   325  				byte(HighTagContinueBitmask | 0x7f),
   326  				byte(HighTagContinueBitmask | 0x7f),
   327  				byte(HighTagContinueBitmask | 0x7f),
   328  				byte(HighTagContinueBitmask | 0x7f),
   329  				byte(HighTagContinueBitmask | 0x7f),
   330  				byte(HighTagContinueBitmask | 0x7f),
   331  				byte(HighTagContinueBitmask | 0x7f),
   332  				byte(HighTagContinueBitmask | 0x7f),
   333  				byte(0x7f),
   334  			},
   335  		},
   336  	}
   337  
   338  	for k, tc := range testCases {
   339  		b := encodeIdentifier(tc.Identifier)
   340  		if !bytes.Equal(tc.ExpectedBytes, b) {
   341  			t.Errorf("%s: Expected\n\t%#v\ngot\n\t%#v", k, tc.ExpectedBytes, b)
   342  		}
   343  	}
   344  }
   345  
   346  func TestEncodeHighTag(t *testing.T) {
   347  	cases := []struct {
   348  		tag  Tag
   349  		want []byte
   350  	}{
   351  		{134, []byte{0x80 + 0x01, 0x06}},
   352  		{123456, []byte{0x80 + 0x07, 0x80 + 0x44, 0x40}},
   353  		{0xFF, []byte{0x81, 0x7F}},
   354  	}
   355  
   356  	for _, c := range cases {
   357  		got := encodeHighTag(c.tag)
   358  
   359  		if !bytes.Equal(c.want, got) {
   360  			t.Errorf("tag: %d want: %#v got: %#v", c.tag, c.want, got)
   361  		}
   362  	}
   363  }
   364  

View as plain text