base32_test.gno
3.08 Kb · 120 lines
1package base32
2
3import (
4 "strings"
5 "testing"
6
7 "gno.land/p/nt/uassert/v0"
8)
9
10// The RFC 4648 §10 test vectors — every partial-group length.
11func TestRFC4648Vectors(t *testing.T) {
12 cases := []struct{ in, want string }{
13 {"", ""},
14 {"f", "MY======"},
15 {"fo", "MZXQ===="},
16 {"foo", "MZXW6==="},
17 {"foob", "MZXW6YQ="},
18 {"fooba", "MZXW6YTB"},
19 {"foobar", "MZXW6YTBOI======"},
20 }
21 for _, c := range cases {
22 got, err := Encode(c.in)
23 uassert.NoError(t, err)
24 uassert.Equal(t, c.want, got)
25 }
26}
27
28func TestRFC4648RoundTrip(t *testing.T) {
29 for _, s := range []string{"", "f", "fo", "foo", "foob", "fooba", "foobar", "hello world"} {
30 enc, err := Encode(s)
31 uassert.NoError(t, err)
32 dec, err2 := Decode(enc)
33 uassert.NoError(t, err2)
34 uassert.Equal(t, s, dec)
35 }
36}
37
38func TestUnpadded(t *testing.T) {
39 got, _ := EncodeUnpadded("foobar")
40 uassert.Equal(t, "MZXW6YTBOI", got)
41 dec, err := Decode(got) // decoding tolerates the missing padding
42 uassert.NoError(t, err)
43 uassert.Equal(t, "foobar", dec)
44}
45
46func TestDecodeToleratesLowercase(t *testing.T) {
47 dec, err := Decode("mzxw6ytboi")
48 uassert.NoError(t, err)
49 uassert.Equal(t, "foobar", dec)
50}
51
52func TestCrockfordRoundTrip(t *testing.T) {
53 for _, s := range []string{"", "f", "foo", "foobar", "hello"} {
54 enc, err := EncodeCrockford(s)
55 uassert.NoError(t, err)
56 dec, err2 := DecodeCrockford(enc)
57 uassert.NoError(t, err2)
58 uassert.Equal(t, s, dec)
59 }
60}
61
62// The point of Crockford: a mis-typed identifier still decodes.
63func TestCrockfordIsForgiving(t *testing.T) {
64 enc, _ := EncodeCrockford("hello")
65 want, _ := DecodeCrockford(enc)
66
67 // lowercase
68 got, err := DecodeCrockford(strings.ToLower(enc))
69 uassert.NoError(t, err)
70 uassert.Equal(t, want, got)
71
72 // hyphens are ignored, wherever they land
73 got2, err2 := DecodeCrockford(enc[:2] + "-" + enc[2:])
74 uassert.NoError(t, err2)
75 uassert.Equal(t, want, got2)
76
77 // O reads as 0, I and L read as 1
78 a, _ := DecodeCrockford("0")
79 b, _ := DecodeCrockford("O")
80 uassert.Equal(t, a, b)
81 c, _ := DecodeCrockford("1")
82 d, _ := DecodeCrockford("I")
83 e, _ := DecodeCrockford("L")
84 uassert.Equal(t, c, d)
85 uassert.Equal(t, c, e)
86}
87
88// U is excluded from the Crockford alphabet on purpose.
89func TestCrockfordExcludesU(t *testing.T) {
90 uassert.Equal(t, -1, strings.IndexByte(CrockfordAlphabet, 'U'))
91 _, err := DecodeCrockford("U")
92 uassert.ErrorIs(t, err, ErrCorrupt)
93}
94
95func TestDecodeRejectsGarbage(t *testing.T) {
96 for _, s := range []string{"!!!", "MZXW6YTB@", "0189"} { // 0/1/8/9 are not RFC 4648
97 _, err := Decode(s)
98 uassert.Error(t, err)
99 }
100}
101
102// Leftover bits must be zero padding, never smuggled data.
103func TestDecodeRejectsNonZeroLeftoverBits(t *testing.T) {
104 // "MB" would leave non-zero bits after emitting one byte
105 _, err := Decode("MB")
106 uassert.ErrorIs(t, err, ErrCorrupt)
107}
108
109func TestTooLong(t *testing.T) {
110 _, err := Encode(strings.Repeat("a", MaxLen+1))
111 uassert.ErrorIs(t, err, ErrTooLong)
112}
113
114// Padded output is always a multiple of 8 characters.
115func TestPaddingLength(t *testing.T) {
116 for _, s := range []string{"f", "fo", "foo", "foob", "fooba", "foobar"} {
117 enc, _ := Encode(s)
118 uassert.Equal(t, 0, len(enc)%8)
119 }
120}