cford32_test.gno

19.06 Kb ยท 677 lines
  1package cford32
  2
  3import (
  4	"bytes"
  5	"errors"
  6	"fmt"
  7	"io"
  8	"math"
  9	"math/rand"
 10	"strings"
 11	"testing"
 12
 13	"gno.land/p/demo/uassert"
 14)
 15
 16func TestCompactRoundtrip(t *testing.T) {
 17	buf := make([]byte, 13)
 18	prev := make([]byte, 13)
 19	for i := uint64(0); i < (1 << 10); i++ {
 20		res := AppendCompact(i, buf[:0])
 21		back, err := Uint64(res)
 22		testEqual(t, "Uint64(%q) = (%d, %v), want %v", string(res), back, err, nil)
 23		testEqual(t, "Uint64(%q) = %d, want %v", string(res), back, i)
 24
 25		testEqual(t, "bytes.Compare(prev, res) = %d, want %d", bytes.Compare(prev, res), -1)
 26		prev, buf = res, prev
 27	}
 28	for i := uint64(1<<34 - 1024); i < (1<<34 + 1024); i++ {
 29		res := AppendCompact(i, buf[:0])
 30		back, err := Uint64(res)
 31		// println(string(res))
 32		testEqual(t, "Uint64(%q) = (%d, %v), want %v", string(res), back, err, nil)
 33		testEqual(t, "Uint64(%q) = %d, want %v", string(res), back, i)
 34
 35		testEqual(t, "bytes.Compare(prev, res) = %d, want %d", bytes.Compare(prev, res), -1)
 36		prev, buf = res, prev
 37	}
 38	for i := uint64(1<<64 - 5000); i != 0; i++ {
 39		res := AppendCompact(i, buf[:0])
 40		back, err := Uint64(res)
 41		testEqual(t, "Uint64(%q) = (%d, %v), want %v", string(res), back, err, nil)
 42		testEqual(t, "Uint64(%q) = %d, want %v", string(res), back, i)
 43
 44		testEqual(t, "bytes.Compare(prev, res) = %d, want %d", bytes.Compare(prev, res), -1)
 45		prev, buf = res, prev
 46	}
 47}
 48
 49func BenchmarkCompact(b *testing.B) {
 50	buf := make([]byte, 13)
 51	for i := 0; i < b.N; i++ {
 52		_ = AppendCompact(uint64(i), buf[:0])
 53	}
 54}
 55
 56func TestUint64(t *testing.T) {
 57	tt := []struct {
 58		val    string
 59		output uint64
 60		err    string
 61	}{
 62		{"0000001", 1, ""},
 63		{"OoOoOoL", 1, ""},
 64		{"OoUoOoL", 0, CorruptInputError(2).Error()},
 65		{"!123123", 0, CorruptInputError(0).Error()},
 66		{"Loooooo", 1073741824, ""},
 67		{"goooooo", 0, CorruptInputError(0).Error()},
 68		{"goooooooooooo", 0, ""},
 69		{"goooooooooolo", 32, ""},
 70		{"fzzzzzz", (1 << 34) - 1, ""},
 71		{"g00000fzzzzzz", (1 << 34) - 1, ""},
 72		{"g000000", 0, CorruptInputError(0).Error()},
 73		{"g00000g000000", (1 << 34), ""},
 74	}
 75
 76	for _, tc := range tt {
 77		t.Run(tc.val, func(t *testing.T) {
 78			res, err := Uint64([]byte(tc.val))
 79			if tc.err != "" {
 80				_ = uassert.Error(t, err) &&
 81					uassert.Equal(t, tc.err, err.Error())
 82			} else {
 83				_ = uassert.NoError(t, err) &&
 84					uassert.Equal(t, tc.output, res)
 85			}
 86		})
 87	}
 88}
 89
 90func TestRandomCompactRoundtrip(t *testing.T) {
 91	for i := 0; i < 1<<12; i++ {
 92		value := rand.Uint64()
 93		encoded := PutCompact(value)
 94		decoded, err := Uint64(encoded)
 95		uassert.NoError(t, err)
 96		uassert.Equal(t, value, decoded)
 97	}
 98}
 99
100type testpair struct {
101	decoded, encoded string
102}
103
104var pairs = []testpair{
105	{"", ""},
106	{"f", "CR"},
107	{"fo", "CSQG"},
108	{"foo", "CSQPY"},
109	{"foob", "CSQPYRG"},
110	{"fooba", "CSQPYRK1"},
111	{"foobar", "CSQPYRK1E8"},
112
113	{"sure.", "EDTQ4S9E"},
114	{"sure", "EDTQ4S8"},
115	{"sur", "EDTQ4"},
116	{"su", "EDTG"},
117	{"leasure.", "DHJP2WVNE9JJW"},
118	{"easure.", "CNGQ6XBJCMQ0"},
119	{"asure.", "C5SQAWK55R"},
120}
121
122var bigtest = testpair{
123	"Twas brillig, and the slithy toves",
124	"AHVP2WS0C9S6JV3CD5KJR831DSJ20X38CMG76V39EHM7J83MDXV6AWR",
125}
126
127func testEqual(t *testing.T, msg string, args ...any) bool {
128	t.Helper()
129	if args[len(args)-2] != args[len(args)-1] {
130		t.Errorf(msg, args...)
131		return false
132	}
133	return true
134}
135
136func TestEncode(t *testing.T) {
137	for _, p := range pairs {
138		got := EncodeToString([]byte(p.decoded))
139		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, got, p.encoded)
140		dst := AppendEncode([]byte("lead"), []byte(p.decoded))
141		testEqual(t, `AppendEncode("lead", %q) = %q, want %q`, p.decoded, string(dst), "lead"+p.encoded)
142	}
143}
144
145func TestEncoder(t *testing.T) {
146	for _, p := range pairs {
147		bb := &strings.Builder{}
148		encoder := NewEncoder(bb)
149		encoder.Write([]byte(p.decoded))
150		encoder.Close()
151		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, bb.String(), p.encoded)
152	}
153}
154
155func TestEncoderBuffering(t *testing.T) {
156	input := []byte(bigtest.decoded)
157	for bs := 1; bs <= 12; bs++ {
158		bb := &strings.Builder{}
159		encoder := NewEncoder(bb)
160		for pos := 0; pos < len(input); pos += bs {
161			end := pos + bs
162			if end > len(input) {
163				end = len(input)
164			}
165			n, err := encoder.Write(input[pos:end])
166			testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, error(nil))
167			testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos)
168		}
169		err := encoder.Close()
170		testEqual(t, "Close gave error %v, want %v", err, error(nil))
171		testEqual(t, "Encoding/%d of %q = %q, want %q", bs, bigtest.decoded, bb.String(), bigtest.encoded)
172	}
173}
174
175func TestDecode(t *testing.T) {
176	for _, p := range pairs {
177		dbuf := make([]byte, DecodedLen(len(p.encoded)))
178		count, err := decode(dbuf, []byte(p.encoded))
179		testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, error(nil))
180		testEqual(t, "Decode(%q) = length %v, want %v", p.encoded, count, len(p.decoded))
181		testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded)
182
183		dbuf, err = DecodeString(p.encoded)
184		testEqual(t, "DecodeString(%q) = error %v, want %v", p.encoded, err, error(nil))
185		testEqual(t, "DecodeString(%q) = %q, want %q", p.encoded, string(dbuf), p.decoded)
186
187		// XXX: https://github.com/gnolang/gno/issues/1570
188		dst, err := AppendDecode(append([]byte(nil), []byte("lead")...), []byte(p.encoded))
189		testEqual(t, "AppendDecode(%q) = error %v, want %v", p.encoded, err, error(nil))
190		testEqual(t, `AppendDecode("lead", %q) = %q, want %q`, p.encoded, string(dst), "lead"+p.decoded)
191
192		dst2, err := AppendDecode(dst[:0:len(p.decoded)], []byte(p.encoded))
193		testEqual(t, "AppendDecode(%q) = error %v, want %v", p.encoded, err, error(nil))
194		testEqual(t, `AppendDecode("", %q) = %q, want %q`, p.encoded, string(dst2), p.decoded)
195		// XXX: https://github.com/gnolang/gno/issues/1569
196		// old used &dst2[0] != &dst[0] as a check.
197		if len(dst) > 0 && len(dst2) > 0 && cap(dst2) != len(p.decoded) {
198			t.Errorf("unexpected capacity growth: got %d, want %d", cap(dst2), len(p.decoded))
199		}
200	}
201}
202
203// A minimal variation on strings.Reader.
204// Here, we return a io.EOF immediately on Read if the read has reached the end
205// of the reader. It's used to simplify TestDecoder.
206type stringReader struct {
207	s string
208	i int64
209}
210
211func (r *stringReader) Read(b []byte) (n int, err error) {
212	if r.i >= int64(len(r.s)) {
213		return 0, io.EOF
214	}
215	n = copy(b, r.s[r.i:])
216	r.i += int64(n)
217	if r.i >= int64(len(r.s)) {
218		return n, io.EOF
219	}
220	return
221}
222
223func TestDecoder(t *testing.T) {
224	for _, p := range pairs {
225		decoder := NewDecoder(&stringReader{p.encoded, 0})
226		dbuf := make([]byte, DecodedLen(len(p.encoded)))
227		count, err := decoder.Read(dbuf)
228		if err != nil && err != io.EOF {
229			t.Fatal("Read failed", err)
230		}
231		testEqual(t, "Read from %q = length %v, want %v", p.encoded, count, len(p.decoded))
232		testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded)
233		if err != io.EOF {
234			_, err = decoder.Read(dbuf)
235		}
236		testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF)
237	}
238}
239
240type badReader struct {
241	data   []byte
242	errs   []error
243	called int
244	limit  int
245}
246
247// Populates p with data, returns a count of the bytes written and an
248// error.  The error returned is taken from badReader.errs, with each
249// invocation of Read returning the next error in this slice, or io.EOF,
250// if all errors from the slice have already been returned.  The
251// number of bytes returned is determined by the size of the input buffer
252// the test passes to decoder.Read and will be a multiple of 8, unless
253// badReader.limit is non zero.
254func (b *badReader) Read(p []byte) (int, error) {
255	lim := len(p)
256	if b.limit != 0 && b.limit < lim {
257		lim = b.limit
258	}
259	if len(b.data) < lim {
260		lim = len(b.data)
261	}
262	for i := range p[:lim] {
263		p[i] = b.data[i]
264	}
265	b.data = b.data[lim:]
266	err := io.EOF
267	if b.called < len(b.errs) {
268		err = b.errs[b.called]
269	}
270	b.called++
271	return lim, err
272}
273
274// TestIssue20044 tests that decoder.Read behaves correctly when the caller
275// supplied reader returns an error.
276func TestIssue20044(t *testing.T) {
277	badErr := errors.New("bad reader error")
278	testCases := []struct {
279		r       badReader
280		res     string
281		err     error
282		dbuflen int
283	}{
284		// Check valid input data accompanied by an error is processed and the error is propagated.
285		{
286			r:   badReader{data: []byte("d1jprv3fexqq4v34"), errs: []error{badErr}},
287			res: "helloworld", err: badErr,
288		},
289		// Check a read error accompanied by input data consisting of newlines only is propagated.
290		{
291			r:   badReader{data: []byte("\n\n\n\n\n\n\n\n"), errs: []error{badErr, nil}},
292			res: "", err: badErr,
293		},
294		// Reader will be called twice.  The first time it will return 8 newline characters.  The
295		// second time valid base32 encoded data and an error.  The data should be decoded
296		// correctly and the error should be propagated.
297		{
298			r:   badReader{data: []byte("\n\n\n\n\n\n\n\nd1jprv3fexqq4v34"), errs: []error{nil, badErr}},
299			res: "helloworld", err: badErr, dbuflen: 8,
300		},
301		// Reader returns invalid input data (too short) and an error.  Verify the reader
302		// error is returned.
303		{
304			r:   badReader{data: []byte("c"), errs: []error{badErr}},
305			res: "", err: badErr,
306		},
307		// Reader returns invalid input data (too short) but no error.  Verify io.ErrUnexpectedEOF
308		// is returned.
309		// NOTE(thehowl): I don't think this should applyto us?
310		/* {
311			r:   badReader{data: []byte("c"), errs: []error{nil}},
312			res: "", err: io.ErrUnexpectedEOF,
313		},*/
314		// Reader returns invalid input data and an error.  Verify the reader and not the
315		// decoder error is returned.
316		{
317			r:   badReader{data: []byte("cu"), errs: []error{badErr}},
318			res: "", err: badErr,
319		},
320		// Reader returns valid data and io.EOF.  Check data is decoded and io.EOF is propagated.
321		{
322			r:   badReader{data: []byte("csqpyrk1"), errs: []error{io.EOF}},
323			res: "fooba", err: io.EOF,
324		},
325		// Check errors are properly reported when decoder.Read is called multiple times.
326		// decoder.Read will be called 8 times, badReader.Read will be called twice, returning
327		// valid data both times but an error on the second call.
328		{
329			r:   badReader{data: []byte("dhjp2wvne9jjwc9g"), errs: []error{nil, badErr}},
330			res: "leasure.10", err: badErr, dbuflen: 1,
331		},
332		// Check io.EOF is properly reported when decoder.Read is called multiple times.
333		// decoder.Read will be called 8 times, badReader.Read will be called twice, returning
334		// valid data both times but io.EOF on the second call.
335		{
336			r:   badReader{data: []byte("dhjp2wvne9jjw"), errs: []error{nil, io.EOF}},
337			res: "leasure.", err: io.EOF, dbuflen: 1,
338		},
339		// The following two test cases check that errors are propagated correctly when more than
340		// 8 bytes are read at a time.
341		{
342			r:   badReader{data: []byte("dhjp2wvne9jjw"), errs: []error{io.EOF}},
343			res: "leasure.", err: io.EOF, dbuflen: 11,
344		},
345		{
346			r:   badReader{data: []byte("dhjp2wvne9jjwc9g"), errs: []error{badErr}},
347			res: "leasure.10", err: badErr, dbuflen: 11,
348		},
349		// Check that errors are correctly propagated when the reader returns valid bytes in
350		// groups that are not divisible by 8.  The first read will return 11 bytes and no
351		// error.  The second will return 7 and an error.  The data should be decoded correctly
352		// and the error should be propagated.
353		// NOTE(thehowl): again, this is on the assumption that this is padded, and it's not.
354		/* {
355			r:   badReader{data: []byte("dhjp2wvne9jjw"), errs: []error{nil, badErr}, limit: 11},
356			res: "leasure.", err: badErr,
357		}, */
358	}
359
360	for idx, tc := range testCases {
361		t.Run(fmt.Sprintf("%d-%s", idx, string(tc.res)), func(t *testing.T) {
362			input := tc.r.data
363			decoder := NewDecoder(&tc.r)
364			var dbuflen int
365			if tc.dbuflen > 0 {
366				dbuflen = tc.dbuflen
367			} else {
368				dbuflen = DecodedLen(len(input))
369			}
370			dbuf := make([]byte, dbuflen)
371			var err error
372			var res []byte
373			for err == nil {
374				var n int
375				n, err = decoder.Read(dbuf)
376				if n > 0 {
377					res = append(res, dbuf[:n]...)
378				}
379			}
380
381			testEqual(t, "Decoding of %q = %q, want %q", string(input), string(res), tc.res)
382			testEqual(t, "Decoding of %q err = %v, expected %v", string(input), err, tc.err)
383		})
384	}
385}
386
387// TestDecoderError verifies decode errors are propagated when there are no read
388// errors.
389func TestDecoderError(t *testing.T) {
390	for _, readErr := range []error{io.EOF, nil} {
391		input := "ucsqpyrk1u"
392		dbuf := make([]byte, DecodedLen(len(input)))
393		br := badReader{data: []byte(input), errs: []error{readErr}}
394		decoder := NewDecoder(&br)
395		n, err := decoder.Read(dbuf)
396		testEqual(t, "Read after EOF, n = %d, expected %d", n, 0)
397		if _, ok := err.(CorruptInputError); !ok {
398			t.Errorf("Corrupt input error expected.  Found %T", err)
399		}
400	}
401}
402
403// TestReaderEOF ensures decoder.Read behaves correctly when input data is
404// exhausted.
405func TestReaderEOF(t *testing.T) {
406	for _, readErr := range []error{io.EOF, nil} {
407		input := "MZXW6YTB"
408		br := badReader{data: []byte(input), errs: []error{nil, readErr}}
409		decoder := NewDecoder(&br)
410		dbuf := make([]byte, DecodedLen(len(input)))
411		n, err := decoder.Read(dbuf)
412		testEqual(t, "Decoding of %q err = %v, expected %v", input, err, error(nil))
413		n, err = decoder.Read(dbuf)
414		testEqual(t, "Read after EOF, n = %d, expected %d", n, 0)
415		testEqual(t, "Read after EOF, err = %v, expected %v", err, io.EOF)
416		n, err = decoder.Read(dbuf)
417		testEqual(t, "Read after EOF, n = %d, expected %d", n, 0)
418		testEqual(t, "Read after EOF, err = %v, expected %v", err, io.EOF)
419	}
420}
421
422func TestDecoderBuffering(t *testing.T) {
423	for bs := 1; bs <= 12; bs++ {
424		decoder := NewDecoder(strings.NewReader(bigtest.encoded))
425		buf := make([]byte, len(bigtest.decoded)+12)
426		var total int
427		var n int
428		var err error
429		for total = 0; total < len(bigtest.decoded) && err == nil; {
430			n, err = decoder.Read(buf[total : total+bs])
431			total += n
432		}
433		if err != nil && err != io.EOF {
434			t.Errorf("Read from %q at pos %d = %d, unexpected error %v", bigtest.encoded, total, n, err)
435		}
436		testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded)
437	}
438}
439
440func TestDecodeCorrupt(t *testing.T) {
441	testCases := []struct {
442		input  string
443		offset int // -1 means no corruption.
444	}{
445		{"", -1},
446		{"iIoOlL", -1},
447		{"!!!!", 0},
448		{"uxp10", 0},
449		{"x===", 1},
450		{"AA=A====", 2},
451		{"AAA=AAAA", 3},
452		// Much fewer cases compared to Go as there are much fewer cases where input
453		// can be "corrupted".
454	}
455	for _, tc := range testCases {
456		dbuf := make([]byte, DecodedLen(len(tc.input)))
457		_, err := Decode(dbuf, []byte(tc.input))
458		if tc.offset == -1 {
459			if err != nil {
460				t.Error("Decoder wrongly detected corruption in", tc.input)
461			}
462			continue
463		}
464		switch err := err.(type) {
465		case CorruptInputError:
466			testEqual(t, "Corruption in %q at offset %v, want %v", tc.input, int(err), tc.offset)
467		default:
468			t.Error("Decoder failed to detect corruption in", tc)
469		}
470	}
471}
472
473func TestBig(t *testing.T) {
474	n := 3*1000 + 1
475	raw := make([]byte, n)
476	const alpha = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
477	for i := 0; i < n; i++ {
478		raw[i] = alpha[i%len(alpha)]
479	}
480	encoded := new(bytes.Buffer)
481	w := NewEncoder(encoded)
482	nn, err := w.Write(raw)
483	if nn != n || err != nil {
484		t.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn, err, n)
485	}
486	err = w.Close()
487	if err != nil {
488		t.Fatalf("Encoder.Close() = %v want nil", err)
489	}
490	decoded, err := io.ReadAll(NewDecoder(encoded))
491	if err != nil {
492		t.Fatalf("io.ReadAll(NewDecoder(...)): %v", err)
493	}
494
495	if !bytes.Equal(raw, decoded) {
496		var i int
497		for i = 0; i < len(decoded) && i < len(raw); i++ {
498			if decoded[i] != raw[i] {
499				break
500			}
501		}
502		t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i)
503	}
504}
505
506func testStringEncoding(t *testing.T, expected string, examples []string) {
507	for _, e := range examples {
508		buf, err := DecodeString(e)
509		if err != nil {
510			t.Errorf("Decode(%q) failed: %v", e, err)
511			continue
512		}
513		if s := string(buf); s != expected {
514			t.Errorf("Decode(%q) = %q, want %q", e, s, expected)
515		}
516	}
517}
518
519func TestNewLineCharacters(t *testing.T) {
520	// Each of these should decode to the string "sure", without errors.
521	examples := []string{
522		"EDTQ4S8",
523		"EDTQ4S8\r",
524		"EDTQ4S8\n",
525		"EDTQ4S8\r\n",
526		"EDTQ4S\r\n8",
527		"EDT\rQ4S\n8",
528		"edt\nq4s\r8",
529		"edt\nq4s8",
530		"EDTQ4S\n8",
531	}
532	testStringEncoding(t, "sure", examples)
533}
534
535func BenchmarkEncode(b *testing.B) {
536	data := make([]byte, 8192)
537	buf := make([]byte, EncodedLen(len(data)))
538	b.SetBytes(int64(len(data)))
539	for i := 0; i < b.N; i++ {
540		Encode(buf, data)
541	}
542}
543
544func BenchmarkEncodeToString(b *testing.B) {
545	data := make([]byte, 8192)
546	b.SetBytes(int64(len(data)))
547	for i := 0; i < b.N; i++ {
548		EncodeToString(data)
549	}
550}
551
552func BenchmarkDecode(b *testing.B) {
553	data := make([]byte, EncodedLen(8192))
554	Encode(data, make([]byte, 8192))
555	buf := make([]byte, 8192)
556	b.SetBytes(int64(len(data)))
557	for i := 0; i < b.N; i++ {
558		Decode(buf, data)
559	}
560}
561
562func BenchmarkDecodeString(b *testing.B) {
563	data := EncodeToString(make([]byte, 8192))
564	b.SetBytes(int64(len(data)))
565	for i := 0; i < b.N; i++ {
566		DecodeString(data)
567	}
568}
569
570/* TODO: rewrite without using goroutines
571func TestBufferedDecodingSameError(t *testing.T) {
572	testcases := []struct {
573		prefix            string
574		chunkCombinations [][]string
575		expected          error
576	}{
577		// Normal case, this is valid input
578		{"helloworld", [][]string{
579			{"D1JP", "RV3F", "EXQQ", "4V34"},
580			{"D1JPRV3FEXQQ4V34"},
581			{"D1J", "PRV", "3FE", "XQQ", "4V3", "4"},
582			{"D1JPRV3FEXQQ4V", "34"},
583		}, nil},
584
585		// Normal case, this is valid input
586		{"fooba", [][]string{
587			{"CSQPYRK1"},
588			{"CSQPYRK", "1"},
589			{"CSQPYR", "K1"},
590			{"CSQPY", "RK1"},
591			{"CSQPY", "RK", "1"},
592			{"CSQPY", "RK1"},
593			{"CSQP", "YR", "K1"},
594		}, nil},
595
596		// NOTE: many test cases have been removed as we don't return ErrUnexpectedEOF.
597	}
598
599	for _, testcase := range testcases {
600		for _, chunks := range testcase.chunkCombinations {
601			pr, pw := io.Pipe()
602
603			// Write the encoded chunks into the pipe
604			go func() {
605				for _, chunk := range chunks {
606					pw.Write([]byte(chunk))
607				}
608				pw.Close()
609			}()
610
611			decoder := NewDecoder(pr)
612			back, err := io.ReadAll(decoder)
613
614			if err != testcase.expected {
615				t.Errorf("Expected %v, got %v; case %s %+v", testcase.expected, err, testcase.prefix, chunks)
616			}
617			if testcase.expected == nil {
618				testEqual(t, "Decode from NewDecoder(chunkReader(%v)) = %q, want %q", chunks, string(back), testcase.prefix)
619			}
620		}
621	}
622}
623*/
624
625func TestEncodedLen(t *testing.T) {
626	type test struct {
627		n    int
628		want int64
629	}
630	tests := []test{
631		{0, 0},
632		{1, 2},
633		{2, 4},
634		{3, 5},
635		{4, 7},
636		{5, 8},
637		{6, 10},
638		{7, 12},
639		{10, 16},
640		{11, 18},
641	}
642	// check overflow
643	tests = append(tests, test{(math.MaxInt-4)/8 + 1, 1844674407370955162})
644	tests = append(tests, test{math.MaxInt/8*5 + 4, math.MaxInt})
645	for _, tt := range tests {
646		if got := EncodedLen(tt.n); int64(got) != tt.want {
647			t.Errorf("EncodedLen(%d): got %d, want %d", tt.n, got, tt.want)
648		}
649	}
650}
651
652func TestDecodedLen(t *testing.T) {
653	type test struct {
654		n    int
655		want int64
656	}
657	tests := []test{
658		{0, 0},
659		{2, 1},
660		{4, 2},
661		{5, 3},
662		{7, 4},
663		{8, 5},
664		{10, 6},
665		{12, 7},
666		{16, 10},
667		{18, 11},
668	}
669	// check overflow
670	tests = append(tests, test{math.MaxInt/5 + 1, 1152921504606846976})
671	tests = append(tests, test{math.MaxInt, 5764607523034234879})
672	for _, tt := range tests {
673		if got := DecodedLen(tt.n); int64(got) != tt.want {
674			t.Errorf("DecodedLen(%d): got %d, want %d", tt.n, got, tt.want)
675		}
676	}
677}