Home | History | Annotate | Download | only in base32
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package base32
      6 
      7 import (
      8 	"bytes"
      9 	"io"
     10 	"io/ioutil"
     11 	"strings"
     12 	"testing"
     13 )
     14 
     15 type testpair struct {
     16 	decoded, encoded string
     17 }
     18 
     19 var pairs = []testpair{
     20 	// RFC 4648 examples
     21 	{"", ""},
     22 	{"f", "MY======"},
     23 	{"fo", "MZXQ===="},
     24 	{"foo", "MZXW6==="},
     25 	{"foob", "MZXW6YQ="},
     26 	{"fooba", "MZXW6YTB"},
     27 	{"foobar", "MZXW6YTBOI======"},
     28 
     29 	// Wikipedia examples, converted to base32
     30 	{"sure.", "ON2XEZJO"},
     31 	{"sure", "ON2XEZI="},
     32 	{"sur", "ON2XE==="},
     33 	{"su", "ON2Q===="},
     34 	{"leasure.", "NRSWC43VOJSS4==="},
     35 	{"easure.", "MVQXG5LSMUXA===="},
     36 	{"asure.", "MFZXK4TFFY======"},
     37 	{"sure.", "ON2XEZJO"},
     38 }
     39 
     40 var bigtest = testpair{
     41 	"Twas brillig, and the slithy toves",
     42 	"KR3WC4ZAMJZGS3DMNFTSYIDBNZSCA5DIMUQHG3DJORUHSIDUN53GK4Y=",
     43 }
     44 
     45 func testEqual(t *testing.T, msg string, args ...interface{}) bool {
     46 	if args[len(args)-2] != args[len(args)-1] {
     47 		t.Errorf(msg, args...)
     48 		return false
     49 	}
     50 	return true
     51 }
     52 
     53 func TestEncode(t *testing.T) {
     54 	for _, p := range pairs {
     55 		got := StdEncoding.EncodeToString([]byte(p.decoded))
     56 		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, got, p.encoded)
     57 	}
     58 }
     59 
     60 func TestEncoder(t *testing.T) {
     61 	for _, p := range pairs {
     62 		bb := &bytes.Buffer{}
     63 		encoder := NewEncoder(StdEncoding, bb)
     64 		encoder.Write([]byte(p.decoded))
     65 		encoder.Close()
     66 		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, bb.String(), p.encoded)
     67 	}
     68 }
     69 
     70 func TestEncoderBuffering(t *testing.T) {
     71 	input := []byte(bigtest.decoded)
     72 	for bs := 1; bs <= 12; bs++ {
     73 		bb := &bytes.Buffer{}
     74 		encoder := NewEncoder(StdEncoding, bb)
     75 		for pos := 0; pos < len(input); pos += bs {
     76 			end := pos + bs
     77 			if end > len(input) {
     78 				end = len(input)
     79 			}
     80 			n, err := encoder.Write(input[pos:end])
     81 			testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, error(nil))
     82 			testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos)
     83 		}
     84 		err := encoder.Close()
     85 		testEqual(t, "Close gave error %v, want %v", err, error(nil))
     86 		testEqual(t, "Encoding/%d of %q = %q, want %q", bs, bigtest.decoded, bb.String(), bigtest.encoded)
     87 	}
     88 }
     89 
     90 func TestDecode(t *testing.T) {
     91 	for _, p := range pairs {
     92 		dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded)))
     93 		count, end, err := StdEncoding.decode(dbuf, []byte(p.encoded))
     94 		testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, error(nil))
     95 		testEqual(t, "Decode(%q) = length %v, want %v", p.encoded, count, len(p.decoded))
     96 		if len(p.encoded) > 0 {
     97 			testEqual(t, "Decode(%q) = end %v, want %v", p.encoded, end, (p.encoded[len(p.encoded)-1] == '='))
     98 		}
     99 		testEqual(t, "Decode(%q) = %q, want %q", p.encoded,
    100 			string(dbuf[0:count]),
    101 			p.decoded)
    102 
    103 		dbuf, err = StdEncoding.DecodeString(p.encoded)
    104 		testEqual(t, "DecodeString(%q) = error %v, want %v", p.encoded, err, error(nil))
    105 		testEqual(t, "DecodeString(%q) = %q, want %q", p.encoded, string(dbuf), p.decoded)
    106 	}
    107 }
    108 
    109 func TestDecoder(t *testing.T) {
    110 	for _, p := range pairs {
    111 		decoder := NewDecoder(StdEncoding, strings.NewReader(p.encoded))
    112 		dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded)))
    113 		count, err := decoder.Read(dbuf)
    114 		if err != nil && err != io.EOF {
    115 			t.Fatal("Read failed", err)
    116 		}
    117 		testEqual(t, "Read from %q = length %v, want %v", p.encoded, count, len(p.decoded))
    118 		testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded)
    119 		if err != io.EOF {
    120 			count, err = decoder.Read(dbuf)
    121 		}
    122 		testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF)
    123 	}
    124 }
    125 
    126 func TestDecoderBuffering(t *testing.T) {
    127 	for bs := 1; bs <= 12; bs++ {
    128 		decoder := NewDecoder(StdEncoding, strings.NewReader(bigtest.encoded))
    129 		buf := make([]byte, len(bigtest.decoded)+12)
    130 		var total int
    131 		for total = 0; total < len(bigtest.decoded); {
    132 			n, err := decoder.Read(buf[total : total+bs])
    133 			testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", bigtest.encoded, total, n, err, error(nil))
    134 			total += n
    135 		}
    136 		testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded)
    137 	}
    138 }
    139 
    140 func TestDecodeCorrupt(t *testing.T) {
    141 	testCases := []struct {
    142 		input  string
    143 		offset int // -1 means no corruption.
    144 	}{
    145 		{"", -1},
    146 		{"!!!!", 0},
    147 		{"x===", 0},
    148 		{"AA=A====", 2},
    149 		{"AAA=AAAA", 3},
    150 		{"MMMMMMMMM", 8},
    151 		{"MMMMMM", 0},
    152 		{"A=", 1},
    153 		{"AA=", 3},
    154 		{"AA==", 4},
    155 		{"AA===", 5},
    156 		{"AAAA=", 5},
    157 		{"AAAA==", 6},
    158 		{"AAAAA=", 6},
    159 		{"AAAAA==", 7},
    160 		{"A=======", 1},
    161 		{"AA======", -1},
    162 		{"AAA=====", 3},
    163 		{"AAAA====", -1},
    164 		{"AAAAA===", -1},
    165 		{"AAAAAA==", 6},
    166 		{"AAAAAAA=", -1},
    167 		{"AAAAAAAA", -1},
    168 	}
    169 	for _, tc := range testCases {
    170 		dbuf := make([]byte, StdEncoding.DecodedLen(len(tc.input)))
    171 		_, err := StdEncoding.Decode(dbuf, []byte(tc.input))
    172 		if tc.offset == -1 {
    173 			if err != nil {
    174 				t.Error("Decoder wrongly detected coruption in", tc.input)
    175 			}
    176 			continue
    177 		}
    178 		switch err := err.(type) {
    179 		case CorruptInputError:
    180 			testEqual(t, "Corruption in %q at offset %v, want %v", tc.input, int(err), tc.offset)
    181 		default:
    182 			t.Error("Decoder failed to detect corruption in", tc)
    183 		}
    184 	}
    185 }
    186 
    187 func TestBig(t *testing.T) {
    188 	n := 3*1000 + 1
    189 	raw := make([]byte, n)
    190 	const alpha = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    191 	for i := 0; i < n; i++ {
    192 		raw[i] = alpha[i%len(alpha)]
    193 	}
    194 	encoded := new(bytes.Buffer)
    195 	w := NewEncoder(StdEncoding, encoded)
    196 	nn, err := w.Write(raw)
    197 	if nn != n || err != nil {
    198 		t.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn, err, n)
    199 	}
    200 	err = w.Close()
    201 	if err != nil {
    202 		t.Fatalf("Encoder.Close() = %v want nil", err)
    203 	}
    204 	decoded, err := ioutil.ReadAll(NewDecoder(StdEncoding, encoded))
    205 	if err != nil {
    206 		t.Fatalf("ioutil.ReadAll(NewDecoder(...)): %v", err)
    207 	}
    208 
    209 	if !bytes.Equal(raw, decoded) {
    210 		var i int
    211 		for i = 0; i < len(decoded) && i < len(raw); i++ {
    212 			if decoded[i] != raw[i] {
    213 				break
    214 			}
    215 		}
    216 		t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i)
    217 	}
    218 }
    219 
    220 func testStringEncoding(t *testing.T, expected string, examples []string) {
    221 	for _, e := range examples {
    222 		buf, err := StdEncoding.DecodeString(e)
    223 		if err != nil {
    224 			t.Errorf("Decode(%q) failed: %v", e, err)
    225 			continue
    226 		}
    227 		if s := string(buf); s != expected {
    228 			t.Errorf("Decode(%q) = %q, want %q", e, s, expected)
    229 		}
    230 	}
    231 }
    232 
    233 func TestNewLineCharacters(t *testing.T) {
    234 	// Each of these should decode to the string "sure", without errors.
    235 	examples := []string{
    236 		"ON2XEZI=",
    237 		"ON2XEZI=\r",
    238 		"ON2XEZI=\n",
    239 		"ON2XEZI=\r\n",
    240 		"ON2XEZ\r\nI=",
    241 		"ON2X\rEZ\nI=",
    242 		"ON2X\nEZ\rI=",
    243 		"ON2XEZ\nI=",
    244 		"ON2XEZI\n=",
    245 	}
    246 	testStringEncoding(t, "sure", examples)
    247 
    248 	// Each of these should decode to the string "foobar", without errors.
    249 	examples = []string{
    250 		"MZXW6YTBOI======",
    251 		"MZXW6YTBOI=\r\n=====",
    252 	}
    253 	testStringEncoding(t, "foobar", examples)
    254 }
    255 
    256 func TestDecoderIssue4779(t *testing.T) {
    257 	encoded := `JRXXEZLNEBUXA43VNUQGI33MN5ZCA43JOQQGC3LFOQWCAY3PNZZWKY3UMV2HK4
    258 RAMFSGS4DJONUWG2LOM4QGK3DJOQWCA43FMQQGI3YKMVUXK43NN5SCA5DFNVYG64RANFXGG2LENFSH
    259 K3TUEB2XIIDMMFRG64TFEBSXIIDEN5WG64TFEBWWCZ3OMEQGC3DJOF2WCLRAKV2CAZLONFWQUYLEEB
    260 WWS3TJNUQHMZLONFQW2LBAOF2WS4ZANZXXG5DSOVSCAZLYMVZGG2LUMF2GS33OEB2WY3DBNVRW6IDM
    261 MFRG64TJOMQG42LTNEQHK5AKMFWGS4LVNFYCAZLYEBSWCIDDN5WW233EN4QGG33OONSXC5LBOQXCAR
    262 DVNFZSAYLVORSSA2LSOVZGKIDEN5WG64RANFXAU4TFOBZGK2DFNZSGK4TJOQQGS3RAOZXWY5LQORQX
    263 IZJAOZSWY2LUEBSXG43FEBRWS3DMOVWSAZDPNRXXEZJAMV2SAZTVM5UWC5BANZ2WY3DBBJYGC4TJMF
    264 2HK4ROEBCXQY3FOB2GK5LSEBZWS3TUEBXWGY3BMVRWC5BAMN2XA2LEMF2GC5BANZXW4IDQOJXWSZDF
    265 NZ2CYIDTOVXHIIDJNYFGG5LMOBQSA4LVNEQG6ZTGNFRWSYJAMRSXGZLSOVXHIIDNN5WGY2LUEBQW42
    266 LNEBUWIIDFON2CA3DBMJXXE5LNFY==
    267 ====`
    268 	encodedShort := strings.Replace(encoded, "\n", "", -1)
    269 
    270 	dec := NewDecoder(StdEncoding, strings.NewReader(encoded))
    271 	res1, err := ioutil.ReadAll(dec)
    272 	if err != nil {
    273 		t.Errorf("ReadAll failed: %v", err)
    274 	}
    275 
    276 	dec = NewDecoder(StdEncoding, strings.NewReader(encodedShort))
    277 	var res2 []byte
    278 	res2, err = ioutil.ReadAll(dec)
    279 	if err != nil {
    280 		t.Errorf("ReadAll failed: %v", err)
    281 	}
    282 
    283 	if !bytes.Equal(res1, res2) {
    284 		t.Error("Decoded results not equal")
    285 	}
    286 }
    287 
    288 func BenchmarkEncodeToString(b *testing.B) {
    289 	data := make([]byte, 8192)
    290 	b.SetBytes(int64(len(data)))
    291 	for i := 0; i < b.N; i++ {
    292 		StdEncoding.EncodeToString(data)
    293 	}
    294 }
    295 
    296 func BenchmarkDecodeString(b *testing.B) {
    297 	data := StdEncoding.EncodeToString(make([]byte, 8192))
    298 	b.SetBytes(int64(len(data)))
    299 	for i := 0; i < b.N; i++ {
    300 		StdEncoding.DecodeString(data)
    301 	}
    302 }
    303