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.
16 type testpair
struct {
17 decoded
, encoded
string
20 var pairs
= []testpair
{
27 {"fooba", "MZXW6YTB"},
28 {"foobar", "MZXW6YTBOI======"},
30 // Wikipedia examples, converted to base32
31 {"sure.", "ON2XEZJO"},
35 {"leasure.", "NRSWC43VOJSS4==="},
36 {"easure.", "MVQXG5LSMUXA===="},
37 {"asure.", "MFZXK4TFFY======"},
38 {"sure.", "ON2XEZJO"},
41 var bigtest
= testpair
{
42 "Twas brillig, and the slithy toves",
43 "KR3WC4ZAMJZGS3DMNFTSYIDBNZSCA5DIMUQHG3DJORUHSIDUN53GK4Y=",
46 func testEqual(t
*testing
.T
, msg
string, args
...interface{}) bool {
48 if args
[len(args
)-2] != args
[len(args
)-1] {
49 t
.Errorf(msg
, args
...)
55 func TestEncode(t
*testing
.T
) {
56 for _
, p
:= range pairs
{
57 got
:= StdEncoding
.EncodeToString([]byte(p
.decoded
))
58 testEqual(t
, "Encode(%q) = %q, want %q", p
.decoded
, got
, p
.encoded
)
62 func TestEncoder(t
*testing
.T
) {
63 for _
, p
:= range pairs
{
65 encoder
:= NewEncoder(StdEncoding
, bb
)
66 encoder
.Write([]byte(p
.decoded
))
68 testEqual(t
, "Encode(%q) = %q, want %q", p
.decoded
, bb
.String(), p
.encoded
)
72 func TestEncoderBuffering(t
*testing
.T
) {
73 input
:= []byte(bigtest
.decoded
)
74 for bs
:= 1; bs
<= 12; bs
++ {
76 encoder
:= NewEncoder(StdEncoding
, bb
)
77 for pos
:= 0; pos
< len(input
); pos
+= bs
{
82 n
, err
:= encoder
.Write(input
[pos
:end
])
83 testEqual(t
, "Write(%q) gave error %v, want %v", input
[pos
:end
], err
, error(nil))
84 testEqual(t
, "Write(%q) gave length %v, want %v", input
[pos
:end
], n
, end
-pos
)
86 err
:= encoder
.Close()
87 testEqual(t
, "Close gave error %v, want %v", err
, error(nil))
88 testEqual(t
, "Encoding/%d of %q = %q, want %q", bs
, bigtest
.decoded
, bb
.String(), bigtest
.encoded
)
92 func TestDecode(t
*testing
.T
) {
93 for _
, p
:= range pairs
{
94 dbuf
:= make([]byte, StdEncoding
.DecodedLen(len(p
.encoded
)))
95 count
, end
, err
:= StdEncoding
.decode(dbuf
, []byte(p
.encoded
))
96 testEqual(t
, "Decode(%q) = error %v, want %v", p
.encoded
, err
, error(nil))
97 testEqual(t
, "Decode(%q) = length %v, want %v", p
.encoded
, count
, len(p
.decoded
))
98 if len(p
.encoded
) > 0 {
99 testEqual(t
, "Decode(%q) = end %v, want %v", p
.encoded
, end
, (p
.encoded
[len(p
.encoded
)-1] == '='))
101 testEqual(t
, "Decode(%q) = %q, want %q", p
.encoded
,
102 string(dbuf
[0:count
]),
105 dbuf
, err
= StdEncoding
.DecodeString(p
.encoded
)
106 testEqual(t
, "DecodeString(%q) = error %v, want %v", p
.encoded
, err
, error(nil))
107 testEqual(t
, "DecodeString(%q) = %q, want %q", p
.encoded
, string(dbuf
), p
.decoded
)
111 func TestDecoder(t
*testing
.T
) {
112 for _
, p
:= range pairs
{
113 decoder
:= NewDecoder(StdEncoding
, strings
.NewReader(p
.encoded
))
114 dbuf
:= make([]byte, StdEncoding
.DecodedLen(len(p
.encoded
)))
115 count
, err
:= decoder
.Read(dbuf
)
116 if err
!= nil && err
!= io
.EOF
{
117 t
.Fatal("Read failed", err
)
119 testEqual(t
, "Read from %q = length %v, want %v", p
.encoded
, count
, len(p
.decoded
))
120 testEqual(t
, "Decoding of %q = %q, want %q", p
.encoded
, string(dbuf
[0:count
]), p
.decoded
)
122 count
, err
= decoder
.Read(dbuf
)
124 testEqual(t
, "Read from %q = %v, want %v", p
.encoded
, err
, io
.EOF
)
128 type badReader
struct {
135 // Populates p with data, returns a count of the bytes written and an
136 // error. The error returned is taken from badReader.errs, with each
137 // invocation of Read returning the next error in this slice, or io.EOF,
138 // if all errors from the slice have already been returned. The
139 // number of bytes returned is determined by the size of the input buffer
140 // the test passes to decoder.Read and will be a multiple of 8, unless
141 // badReader.limit is non zero.
142 func (b
*badReader
) Read(p
[]byte) (int, error
) {
144 if b
.limit
!= 0 && b
.limit
< lim
{
147 if len(b
.data
) < lim
{
150 for i
:= range p
[:lim
] {
153 b
.data
= b
.data
[lim
:]
155 if b
.called
< len(b
.errs
) {
156 err
= b
.errs
[b
.called
]
162 // TestIssue20044 tests that decoder.Read behaves correctly when the caller
163 // supplied reader returns an error.
164 func TestIssue20044(t
*testing
.T
) {
165 badErr
:= errors
.New("bad reader error")
166 testCases
:= []struct {
172 // Check valid input data accompanied by an error is processed and the error is propagated.
173 {r
: badReader
{data
: []byte("MY======"), errs
: []error
{badErr
}},
174 res
: "f", err
: badErr
},
175 // Check a read error accompanied by input data consisting of newlines only is propagated.
176 {r
: badReader
{data
: []byte("\n\n\n\n\n\n\n\n"), errs
: []error
{badErr
, nil}},
177 res
: "", err
: badErr
},
178 // Reader will be called twice. The first time it will return 8 newline characters. The
179 // second time valid base32 encoded data and an error. The data should be decoded
180 // correctly and the error should be propagated.
181 {r
: badReader
{data
: []byte("\n\n\n\n\n\n\n\nMY======"), errs
: []error
{nil, badErr
}},
182 res
: "f", err
: badErr
, dbuflen
: 8},
183 // Reader returns invalid input data (too short) and an error. Verify the reader
184 // error is returned.
185 {r
: badReader
{data
: []byte("MY====="), errs
: []error
{badErr
}},
186 res
: "", err
: badErr
},
187 // Reader returns invalid input data (too short) but no error. Verify io.ErrUnexpectedEOF
189 {r
: badReader
{data
: []byte("MY====="), errs
: []error
{nil}},
190 res
: "", err
: io
.ErrUnexpectedEOF
},
191 // Reader returns invalid input data and an error. Verify the reader and not the
192 // decoder error is returned.
193 {r
: badReader
{data
: []byte("Ma======"), errs
: []error
{badErr
}},
194 res
: "", err
: badErr
},
195 // Reader returns valid data and io.EOF. Check data is decoded and io.EOF is propagated.
196 {r
: badReader
{data
: []byte("MZXW6YTB"), errs
: []error
{io
.EOF
}},
197 res
: "fooba", err
: io
.EOF
},
198 // Check errors are properly reported when decoder.Read is called multiple times.
199 // decoder.Read will be called 8 times, badReader.Read will be called twice, returning
200 // valid data both times but an error on the second call.
201 {r
: badReader
{data
: []byte("NRSWC43VOJSS4==="), errs
: []error
{nil, badErr
}},
202 res
: "leasure.", err
: badErr
, dbuflen
: 1},
203 // Check io.EOF is properly reported when decoder.Read is called multiple times.
204 // decoder.Read will be called 8 times, badReader.Read will be called twice, returning
205 // valid data both times but io.EOF on the second call.
206 {r
: badReader
{data
: []byte("NRSWC43VOJSS4==="), errs
: []error
{nil, io
.EOF
}},
207 res
: "leasure.", err
: io
.EOF
, dbuflen
: 1},
208 // The following two test cases check that errors are propagated correctly when more than
209 // 8 bytes are read at a time.
210 {r
: badReader
{data
: []byte("NRSWC43VOJSS4==="), errs
: []error
{io
.EOF
}},
211 res
: "leasure.", err
: io
.EOF
, dbuflen
: 11},
212 {r
: badReader
{data
: []byte("NRSWC43VOJSS4==="), errs
: []error
{badErr
}},
213 res
: "leasure.", err
: badErr
, dbuflen
: 11},
214 // Check that errors are correctly propagated when the reader returns valid bytes in
215 // groups that are not divisible by 8. The first read will return 11 bytes and no
216 // error. The second will return 7 and an error. The data should be decoded correctly
217 // and the error should be propagated.
218 {r
: badReader
{data
: []byte("NRSWC43VOJSS4==="), errs
: []error
{nil, badErr
}, limit
: 11},
219 res
: "leasure.", err
: badErr
},
222 for _
, tc
:= range testCases
{
224 decoder
:= NewDecoder(StdEncoding
, &tc
.r
)
229 dbuflen
= StdEncoding
.DecodedLen(len(input
))
231 dbuf
:= make([]byte, dbuflen
)
236 n
, err
= decoder
.Read(dbuf
)
238 res
= append(res
, dbuf
[:n
]...)
242 testEqual(t
, "Decoding of %q = %q, want %q", string(input
), string(res
), tc
.res
)
243 testEqual(t
, "Decoding of %q err = %v, expected %v", string(input
), err
, tc
.err
)
247 // TestDecoderError verifies decode errors are propagated when there are no read
249 func TestDecoderError(t
*testing
.T
) {
250 for _
, readErr
:= range []error
{io
.EOF
, nil} {
252 dbuf
:= make([]byte, StdEncoding
.DecodedLen(len(input
)))
253 br
:= badReader
{data
: []byte(input
), errs
: []error
{readErr
}}
254 decoder
:= NewDecoder(StdEncoding
, &br
)
255 n
, err
:= decoder
.Read(dbuf
)
256 testEqual(t
, "Read after EOF, n = %d, expected %d", n
, 0)
257 if _
, ok
:= err
.(CorruptInputError
); !ok
{
258 t
.Errorf("Corrupt input error expected. Found %T", err
)
263 // TestReaderEOF ensures decoder.Read behaves correctly when input data is
265 func TestReaderEOF(t
*testing
.T
) {
266 for _
, readErr
:= range []error
{io
.EOF
, nil} {
268 br
:= badReader
{data
: []byte(input
), errs
: []error
{nil, readErr
}}
269 decoder
:= NewDecoder(StdEncoding
, &br
)
270 dbuf
:= make([]byte, StdEncoding
.DecodedLen(len(input
)))
271 n
, err
:= decoder
.Read(dbuf
)
272 testEqual(t
, "Decoding of %q err = %v, expected %v", string(input
), err
, error(nil))
273 n
, err
= decoder
.Read(dbuf
)
274 testEqual(t
, "Read after EOF, n = %d, expected %d", n
, 0)
275 testEqual(t
, "Read after EOF, err = %v, expected %v", err
, io
.EOF
)
276 n
, err
= decoder
.Read(dbuf
)
277 testEqual(t
, "Read after EOF, n = %d, expected %d", n
, 0)
278 testEqual(t
, "Read after EOF, err = %v, expected %v", err
, io
.EOF
)
282 func TestDecoderBuffering(t
*testing
.T
) {
283 for bs
:= 1; bs
<= 12; bs
++ {
284 decoder
:= NewDecoder(StdEncoding
, strings
.NewReader(bigtest
.encoded
))
285 buf
:= make([]byte, len(bigtest
.decoded
)+12)
289 for total
= 0; total
< len(bigtest
.decoded
) && err
== nil; {
290 n
, err
= decoder
.Read(buf
[total
: total
+bs
])
293 if err
!= nil && err
!= io
.EOF
{
294 t
.Errorf("Read from %q at pos %d = %d, unexpected error %v", bigtest
.encoded
, total
, n
, err
)
296 testEqual(t
, "Decoding/%d of %q = %q, want %q", bs
, bigtest
.encoded
, string(buf
[0:total
]), bigtest
.decoded
)
300 func TestDecodeCorrupt(t
*testing
.T
) {
301 testCases
:= []struct {
303 offset
int // -1 means no corruption.
329 for _
, tc
:= range testCases
{
330 dbuf
:= make([]byte, StdEncoding
.DecodedLen(len(tc
.input
)))
331 _
, err
:= StdEncoding
.Decode(dbuf
, []byte(tc
.input
))
334 t
.Error("Decoder wrongly detected corruption in", tc
.input
)
338 switch err
:= err
.(type) {
339 case CorruptInputError
:
340 testEqual(t
, "Corruption in %q at offset %v, want %v", tc
.input
, int(err
), tc
.offset
)
342 t
.Error("Decoder failed to detect corruption in", tc
)
347 func TestBig(t
*testing
.T
) {
349 raw
:= make([]byte, n
)
350 const alpha
= "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
351 for i
:= 0; i
< n
; i
++ {
352 raw
[i
] = alpha
[i%len
(alpha
)]
354 encoded
:= new(bytes
.Buffer
)
355 w
:= NewEncoder(StdEncoding
, encoded
)
356 nn
, err
:= w
.Write(raw
)
357 if nn
!= n || err
!= nil {
358 t
.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn
, err
, n
)
362 t
.Fatalf("Encoder.Close() = %v want nil", err
)
364 decoded
, err
:= ioutil
.ReadAll(NewDecoder(StdEncoding
, encoded
))
366 t
.Fatalf("ioutil.ReadAll(NewDecoder(...)): %v", err
)
369 if !bytes
.Equal(raw
, decoded
) {
371 for i
= 0; i
< len(decoded
) && i
< len(raw
); i
++ {
372 if decoded
[i
] != raw
[i
] {
376 t
.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n
, i
)
380 func testStringEncoding(t
*testing
.T
, expected
string, examples
[]string) {
381 for _
, e
:= range examples
{
382 buf
, err
:= StdEncoding
.DecodeString(e
)
384 t
.Errorf("Decode(%q) failed: %v", e
, err
)
387 if s
:= string(buf
); s
!= expected
{
388 t
.Errorf("Decode(%q) = %q, want %q", e
, s
, expected
)
393 func TestNewLineCharacters(t
*testing
.T
) {
394 // Each of these should decode to the string "sure", without errors.
395 examples
:= []string{
406 testStringEncoding(t
, "sure", examples
)
408 // Each of these should decode to the string "foobar", without errors.
411 "MZXW6YTBOI=\r\n=====",
413 testStringEncoding(t
, "foobar", examples
)
416 func TestDecoderIssue4779(t
*testing
.T
) {
417 encoded
:= `JRXXEZLNEBUXA43VNUQGI33MN5ZCA43JOQQGC3LFOQWCAY3PNZZWKY3UMV2HK4
418 RAMFSGS4DJONUWG2LOM4QGK3DJOQWCA43FMQQGI3YKMVUXK43NN5SCA5DFNVYG64RANFXGG2LENFSH
419 K3TUEB2XIIDMMFRG64TFEBSXIIDEN5WG64TFEBWWCZ3OMEQGC3DJOF2WCLRAKV2CAZLONFWQUYLEEB
420 WWS3TJNUQHMZLONFQW2LBAOF2WS4ZANZXXG5DSOVSCAZLYMVZGG2LUMF2GS33OEB2WY3DBNVRW6IDM
421 MFRG64TJOMQG42LTNEQHK5AKMFWGS4LVNFYCAZLYEBSWCIDDN5WW233EN4QGG33OONSXC5LBOQXCAR
422 DVNFZSAYLVORSSA2LSOVZGKIDEN5WG64RANFXAU4TFOBZGK2DFNZSGK4TJOQQGS3RAOZXWY5LQORQX
423 IZJAOZSWY2LUEBSXG43FEBRWS3DMOVWSAZDPNRXXEZJAMV2SAZTVM5UWC5BANZ2WY3DBBJYGC4TJMF
424 2HK4ROEBCXQY3FOB2GK5LSEBZWS3TUEBXWGY3BMVRWC5BAMN2XA2LEMF2GC5BANZXW4IDQOJXWSZDF
425 NZ2CYIDTOVXHIIDJNYFGG5LMOBQSA4LVNEQG6ZTGNFRWSYJAMRSXGZLSOVXHIIDNN5WGY2LUEBQW42
426 LNEBUWIIDFON2CA3DBMJXXE5LNFY==
428 encodedShort
:= strings
.Replace(encoded
, "\n", "", -1)
430 dec
:= NewDecoder(StdEncoding
, strings
.NewReader(encoded
))
431 res1
, err
:= ioutil
.ReadAll(dec
)
433 t
.Errorf("ReadAll failed: %v", err
)
436 dec
= NewDecoder(StdEncoding
, strings
.NewReader(encodedShort
))
438 res2
, err
= ioutil
.ReadAll(dec
)
440 t
.Errorf("ReadAll failed: %v", err
)
443 if !bytes
.Equal(res1
, res2
) {
444 t
.Error("Decoded results not equal")
448 func BenchmarkEncodeToString(b
*testing
.B
) {
449 data
:= make([]byte, 8192)
450 b
.SetBytes(int64(len(data
)))
451 for i
:= 0; i
< b
.N
; i
++ {
452 StdEncoding
.EncodeToString(data
)
456 func BenchmarkDecodeString(b
*testing
.B
) {
457 data
:= StdEncoding
.EncodeToString(make([]byte, 8192))
458 b
.SetBytes(int64(len(data
)))
459 for i
:= 0; i
< b
.N
; i
++ {
460 StdEncoding
.DecodeString(data
)
464 func TestWithCustomPadding(t
*testing
.T
) {
465 for _
, testcase
:= range pairs
{
466 defaultPadding
:= StdEncoding
.EncodeToString([]byte(testcase
.decoded
))
467 customPadding
:= StdEncoding
.WithPadding('@').EncodeToString([]byte(testcase
.decoded
))
468 expected
:= strings
.Replace(defaultPadding
, "=", "@", -1)
470 if expected
!= customPadding
{
471 t
.Errorf("Expected custom %s, got %s", expected
, customPadding
)
473 if testcase
.encoded
!= defaultPadding
{
474 t
.Errorf("Expected %s, got %s", testcase
.encoded
, defaultPadding
)
479 func TestWithoutPadding(t
*testing
.T
) {
480 for _
, testcase
:= range pairs
{
481 defaultPadding
:= StdEncoding
.EncodeToString([]byte(testcase
.decoded
))
482 customPadding
:= StdEncoding
.WithPadding(NoPadding
).EncodeToString([]byte(testcase
.decoded
))
483 expected
:= strings
.TrimRight(defaultPadding
, "=")
485 if expected
!= customPadding
{
486 t
.Errorf("Expected custom %s, got %s", expected
, customPadding
)
488 if testcase
.encoded
!= defaultPadding
{
489 t
.Errorf("Expected %s, got %s", testcase
.encoded
, defaultPadding
)
494 func TestDecodeWithPadding(t
*testing
.T
) {
495 encodings
:= []*Encoding
{
497 StdEncoding
.WithPadding('-'),
498 StdEncoding
.WithPadding(NoPadding
),
501 for i
, enc
:= range encodings
{
502 for _
, pair
:= range pairs
{
504 input
:= pair
.decoded
505 encoded
:= enc
.EncodeToString([]byte(input
))
507 decoded
, err
:= enc
.DecodeString(encoded
)
509 t
.Errorf("DecodeString Error for encoding %d (%q): %v", i
, input
, err
)
512 if input
!= string(decoded
) {
513 t
.Errorf("Unexpected result for encoding %d: got %q; want %q", i
, decoded
, input
)
519 func TestDecodeWithWrongPadding(t
*testing
.T
) {
520 encoded
:= StdEncoding
.EncodeToString([]byte("foobar"))
522 _
, err
:= StdEncoding
.WithPadding('-').DecodeString(encoded
)
524 t
.Error("expected error")
527 _
, err
= StdEncoding
.WithPadding(NoPadding
).DecodeString(encoded
)
529 t
.Error("expected error")
533 func TestEncodedDecodedLen(t
*testing
.T
) {
539 data
:= bytes
.Repeat([]byte("x"), 100)
540 for _
, test
:= range []struct {
545 {"StdEncoding", StdEncoding
, []test
{
552 {"NoPadding", StdEncoding
.WithPadding(NoPadding
), []test
{
563 t
.Run(test
.name
, func(t
*testing
.T
) {
564 for _
, tc
:= range test
.cases
{
565 encLen
:= test
.enc
.EncodedLen(tc
.in
)
566 decLen
:= test
.enc
.DecodedLen(encLen
)
567 enc
:= test
.enc
.EncodeToString(data
[:tc
.in
])
568 if len(enc
) != encLen
{
569 t
.Fatalf("EncodedLen(%d) = %d but encoded to %q (%d)", tc
.in
, encLen
, enc
, len(enc
))
571 if encLen
!= tc
.wantEnc
{
572 t
.Fatalf("EncodedLen(%d) = %d; want %d", tc
.in
, encLen
, tc
.wantEnc
)
574 if decLen
!= tc
.wantDec
{
575 t
.Fatalf("DecodedLen(%d) = %d; want %d", encLen
, decLen
, tc
.wantDec
)