1package ber
2
3import (
4	"bytes"
5	"io"
6	"math"
7	"testing"
8)
9
10func TestReadLength(t *testing.T) {
11	testcases := map[string]struct {
12		Data []byte
13
14		ExpectedLength    int64
15		ExpectedBytesRead int
16		ExpectedError     string
17	}{
18		"empty": {
19			Data:              []byte{},
20			ExpectedBytesRead: 0,
21			ExpectedError:     io.ErrUnexpectedEOF.Error(),
22		},
23		"invalid first byte": {
24			Data:              []byte{0xFF},
25			ExpectedBytesRead: 1,
26			ExpectedError:     "invalid length byte 0xff",
27		},
28
29		"indefinite form": {
30			Data:              []byte{LengthLongFormBitmask},
31			ExpectedLength:    LengthIndefinite,
32			ExpectedBytesRead: 1,
33		},
34
35		"short-definite-form zero length": {
36			Data:              []byte{0},
37			ExpectedLength:    0,
38			ExpectedBytesRead: 1,
39		},
40		"short-definite-form length 1": {
41			Data:              []byte{1},
42			ExpectedLength:    1,
43			ExpectedBytesRead: 1,
44		},
45		"short-definite-form max length": {
46			Data:              []byte{127},
47			ExpectedLength:    127,
48			ExpectedBytesRead: 1,
49		},
50
51		"long-definite-form missing bytes": {
52			Data:              []byte{LengthLongFormBitmask | 1},
53			ExpectedBytesRead: 1,
54			ExpectedError:     io.ErrUnexpectedEOF.Error(),
55		},
56		"long-definite-form overflow": {
57			Data:              []byte{LengthLongFormBitmask | 9},
58			ExpectedBytesRead: 1,
59			ExpectedError:     "long-form length overflow",
60		},
61		"long-definite-form zero length": {
62			Data:              []byte{LengthLongFormBitmask | 1, 0x0},
63			ExpectedLength:    0,
64			ExpectedBytesRead: 2,
65		},
66		"long-definite-form length 127": {
67			Data:              []byte{LengthLongFormBitmask | 1, 127},
68			ExpectedLength:    127,
69			ExpectedBytesRead: 2,
70		},
71		"long-definite-form max length (32-bit)": {
72			Data: []byte{
73				LengthLongFormBitmask | 4,
74				0x7F,
75				0xFF,
76				0xFF,
77				0xFF,
78				0xFF,
79			},
80			ExpectedLength:    math.MaxInt32,
81			ExpectedBytesRead: 5,
82		},
83		"long-definite-form max length (64-bit)": {
84			Data: []byte{
85				LengthLongFormBitmask | 8,
86				0x7F,
87				0xFF,
88				0xFF,
89				0xFF,
90				0xFF,
91				0xFF,
92				0xFF,
93				0xFF,
94			},
95			ExpectedLength:    math.MaxInt64,
96			ExpectedBytesRead: 9,
97		},
98	}
99
100	for k, tc := range testcases {
101		// Skip tests requiring 64-bit integers on platforms that don't support them
102		if tc.ExpectedLength != int64(int(tc.ExpectedLength)) {
103			continue
104		}
105
106		reader := bytes.NewBuffer(tc.Data)
107		length, read, err := readLength(reader)
108
109		if err != nil {
110			if tc.ExpectedError == "" {
111				t.Errorf("%s: unexpected error: %v", k, err)
112			} else if err.Error() != tc.ExpectedError {
113				t.Errorf("%s: expected error %v, got %v", k, tc.ExpectedError, err)
114			}
115		} else if tc.ExpectedError != "" {
116			t.Errorf("%s: expected error %v, got none", k, tc.ExpectedError)
117			continue
118		}
119
120		if read != tc.ExpectedBytesRead {
121			t.Errorf("%s: expected read %d, got %d", k, tc.ExpectedBytesRead, read)
122		}
123
124		if int64(length) != tc.ExpectedLength {
125			t.Errorf("%s: expected length %d, got %d", k, tc.ExpectedLength, length)
126		}
127	}
128}
129
130func TestEncodeLength(t *testing.T) {
131	testcases := map[string]struct {
132		Length        int64
133		ExpectedBytes []byte
134	}{
135		"0": {
136			Length:        0,
137			ExpectedBytes: []byte{0},
138		},
139		"1": {
140			Length:        1,
141			ExpectedBytes: []byte{1},
142		},
143
144		"max short-form length": {
145			Length:        127,
146			ExpectedBytes: []byte{127},
147		},
148		"min long-form length": {
149			Length:        128,
150			ExpectedBytes: []byte{LengthLongFormBitmask | 1, 128},
151		},
152
153		"max long-form length (32-bit)": {
154			Length: math.MaxInt32,
155			ExpectedBytes: []byte{
156				LengthLongFormBitmask | 4,
157				0x7F,
158				0xFF,
159				0xFF,
160				0xFF,
161			},
162		},
163
164		"max long-form length (64-bit)": {
165			Length: math.MaxInt64,
166			ExpectedBytes: []byte{
167				LengthLongFormBitmask | 8,
168				0x7F,
169				0xFF,
170				0xFF,
171				0xFF,
172				0xFF,
173				0xFF,
174				0xFF,
175				0xFF,
176			},
177		},
178	}
179
180	for k, tc := range testcases {
181		// Skip tests requiring 64-bit integers on platforms that don't support them
182		if tc.Length != int64(int(tc.Length)) {
183			continue
184		}
185
186		b := encodeLength(int(tc.Length))
187		if bytes.Compare(tc.ExpectedBytes, b) != 0 {
188			t.Errorf("%s: Expected\n\t%#v\ngot\n\t%#v", k, tc.ExpectedBytes, b)
189		}
190	}
191}
192