github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/encoding/base32/base32_test.go (about) 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 "errors" 10 "io" 11 "math" 12 "strconv" 13 "strings" 14 "testing" 15 ) 16 17 type testpair struct { 18 decoded, encoded string 19 } 20 21 var pairs = []testpair{ 22 // RFC 4648 examples 23 {"", ""}, 24 {"f", "MY======"}, 25 {"fo", "MZXQ===="}, 26 {"foo", "MZXW6==="}, 27 {"foob", "MZXW6YQ="}, 28 {"fooba", "MZXW6YTB"}, 29 {"foobar", "MZXW6YTBOI======"}, 30 31 // Wikipedia examples, converted to base32 32 {"sure.", "ON2XEZJO"}, 33 {"sure", "ON2XEZI="}, 34 {"sur", "ON2XE==="}, 35 {"su", "ON2Q===="}, 36 {"leasure.", "NRSWC43VOJSS4==="}, 37 {"easure.", "MVQXG5LSMUXA===="}, 38 {"asure.", "MFZXK4TFFY======"}, 39 {"sure.", "ON2XEZJO"}, 40 } 41 42 var bigtest = testpair{ 43 "Twas brillig, and the slithy toves", 44 "KR3WC4ZAMJZGS3DMNFTSYIDBNZSCA5DIMUQHG3DJORUHSIDUN53GK4Y=", 45 } 46 47 func testEqual(t *testing.T, msg string, args ...any) bool { 48 t.Helper() 49 if args[len(args)-2] != args[len(args)-1] { 50 t.Errorf(msg, args...) 51 return false 52 } 53 return true 54 } 55 56 func TestEncode(t *testing.T) { 57 for _, p := range pairs { 58 got := StdEncoding.EncodeToString([]byte(p.decoded)) 59 testEqual(t, "Encode(%q) = %q, want %q", p.decoded, got, p.encoded) 60 dst := StdEncoding.AppendEncode([]byte("lead"), []byte(p.decoded)) 61 testEqual(t, `AppendEncode("lead", %q) = %q, want %q`, p.decoded, string(dst), "lead"+p.encoded) 62 } 63 } 64 65 func TestEncoder(t *testing.T) { 66 for _, p := range pairs { 67 bb := &strings.Builder{} 68 encoder := NewEncoder(StdEncoding, bb) 69 encoder.Write([]byte(p.decoded)) 70 encoder.Close() 71 testEqual(t, "Encode(%q) = %q, want %q", p.decoded, bb.String(), p.encoded) 72 } 73 } 74 75 func TestEncoderBuffering(t *testing.T) { 76 input := []byte(bigtest.decoded) 77 for bs := 1; bs <= 12; bs++ { 78 bb := &strings.Builder{} 79 encoder := NewEncoder(StdEncoding, bb) 80 for pos := 0; pos < len(input); pos += bs { 81 end := pos + bs 82 if end > len(input) { 83 end = len(input) 84 } 85 n, err := encoder.Write(input[pos:end]) 86 testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, error(nil)) 87 testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos) 88 } 89 err := encoder.Close() 90 testEqual(t, "Close gave error %v, want %v", err, error(nil)) 91 testEqual(t, "Encoding/%d of %q = %q, want %q", bs, bigtest.decoded, bb.String(), bigtest.encoded) 92 } 93 } 94 95 func TestDecode(t *testing.T) { 96 for _, p := range pairs { 97 dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded))) 98 count, end, err := StdEncoding.decode(dbuf, []byte(p.encoded)) 99 testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, error(nil)) 100 testEqual(t, "Decode(%q) = length %v, want %v", p.encoded, count, len(p.decoded)) 101 if len(p.encoded) > 0 { 102 testEqual(t, "Decode(%q) = end %v, want %v", p.encoded, end, (p.encoded[len(p.encoded)-1] == '=')) 103 } 104 testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded) 105 106 dbuf, err = StdEncoding.DecodeString(p.encoded) 107 testEqual(t, "DecodeString(%q) = error %v, want %v", p.encoded, err, error(nil)) 108 testEqual(t, "DecodeString(%q) = %q, want %q", p.encoded, string(dbuf), p.decoded) 109 110 dst, err := StdEncoding.AppendDecode([]byte("lead"), []byte(p.encoded)) 111 testEqual(t, "AppendDecode(%q) = error %v, want %v", p.encoded, err, error(nil)) 112 testEqual(t, `AppendDecode("lead", %q) = %q, want %q`, p.encoded, string(dst), "lead"+p.decoded) 113 114 dst2, err := StdEncoding.AppendDecode(dst[:0:len(p.decoded)], []byte(p.encoded)) 115 testEqual(t, "AppendDecode(%q) = error %v, want %v", p.encoded, err, error(nil)) 116 testEqual(t, `AppendDecode("", %q) = %q, want %q`, p.encoded, string(dst2), p.decoded) 117 if len(dst) > 0 && len(dst2) > 0 && &dst[0] != &dst2[0] { 118 t.Errorf("unexpected capacity growth: got %d, want %d", cap(dst2), cap(dst)) 119 } 120 } 121 } 122 123 func TestDecoder(t *testing.T) { 124 for _, p := range pairs { 125 decoder := NewDecoder(StdEncoding, strings.NewReader(p.encoded)) 126 dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded))) 127 count, err := decoder.Read(dbuf) 128 if err != nil && err != io.EOF { 129 t.Fatal("Read failed", err) 130 } 131 testEqual(t, "Read from %q = length %v, want %v", p.encoded, count, len(p.decoded)) 132 testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded) 133 if err != io.EOF { 134 _, err = decoder.Read(dbuf) 135 } 136 testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF) 137 } 138 } 139 140 type badReader struct { 141 data []byte 142 errs []error 143 called int 144 limit int 145 } 146 147 // Populates p with data, returns a count of the bytes written and an 148 // error. The error returned is taken from badReader.errs, with each 149 // invocation of Read returning the next error in this slice, or io.EOF, 150 // if all errors from the slice have already been returned. The 151 // number of bytes returned is determined by the size of the input buffer 152 // the test passes to decoder.Read and will be a multiple of 8, unless 153 // badReader.limit is non zero. 154 func (b *badReader) Read(p []byte) (int, error) { 155 lim := len(p) 156 if b.limit != 0 && b.limit < lim { 157 lim = b.limit 158 } 159 if len(b.data) < lim { 160 lim = len(b.data) 161 } 162 for i := range p[:lim] { 163 p[i] = b.data[i] 164 } 165 b.data = b.data[lim:] 166 err := io.EOF 167 if b.called < len(b.errs) { 168 err = b.errs[b.called] 169 } 170 b.called++ 171 return lim, err 172 } 173 174 // TestIssue20044 tests that decoder.Read behaves correctly when the caller 175 // supplied reader returns an error. 176 func TestIssue20044(t *testing.T) { 177 badErr := errors.New("bad reader error") 178 testCases := []struct { 179 r badReader 180 res string 181 err error 182 dbuflen int 183 }{ 184 // Check valid input data accompanied by an error is processed and the error is propagated. 185 {r: badReader{data: []byte("MY======"), errs: []error{badErr}}, 186 res: "f", err: badErr}, 187 // Check a read error accompanied by input data consisting of newlines only is propagated. 188 {r: badReader{data: []byte("\n\n\n\n\n\n\n\n"), errs: []error{badErr, nil}}, 189 res: "", err: badErr}, 190 // Reader will be called twice. The first time it will return 8 newline characters. The 191 // second time valid base32 encoded data and an error. The data should be decoded 192 // correctly and the error should be propagated. 193 {r: badReader{data: []byte("\n\n\n\n\n\n\n\nMY======"), errs: []error{nil, badErr}}, 194 res: "f", err: badErr, dbuflen: 8}, 195 // Reader returns invalid input data (too short) and an error. Verify the reader 196 // error is returned. 197 {r: badReader{data: []byte("MY====="), errs: []error{badErr}}, 198 res: "", err: badErr}, 199 // Reader returns invalid input data (too short) but no error. Verify io.ErrUnexpectedEOF 200 // is returned. 201 {r: badReader{data: []byte("MY====="), errs: []error{nil}}, 202 res: "", err: io.ErrUnexpectedEOF}, 203 // Reader returns invalid input data and an error. Verify the reader and not the 204 // decoder error is returned. 205 {r: badReader{data: []byte("Ma======"), errs: []error{badErr}}, 206 res: "", err: badErr}, 207 // Reader returns valid data and io.EOF. Check data is decoded and io.EOF is propagated. 208 {r: badReader{data: []byte("MZXW6YTB"), errs: []error{io.EOF}}, 209 res: "fooba", err: io.EOF}, 210 // Check errors are properly reported when decoder.Read is called multiple times. 211 // decoder.Read will be called 8 times, badReader.Read will be called twice, returning 212 // valid data both times but an error on the second call. 213 {r: badReader{data: []byte("NRSWC43VOJSS4==="), errs: []error{nil, badErr}}, 214 res: "leasure.", err: badErr, dbuflen: 1}, 215 // Check io.EOF is properly reported when decoder.Read is called multiple times. 216 // decoder.Read will be called 8 times, badReader.Read will be called twice, returning 217 // valid data both times but io.EOF on the second call. 218 {r: badReader{data: []byte("NRSWC43VOJSS4==="), errs: []error{nil, io.EOF}}, 219 res: "leasure.", err: io.EOF, dbuflen: 1}, 220 // The following two test cases check that errors are propagated correctly when more than 221 // 8 bytes are read at a time. 222 {r: badReader{data: []byte("NRSWC43VOJSS4==="), errs: []error{io.EOF}}, 223 res: "leasure.", err: io.EOF, dbuflen: 11}, 224 {r: badReader{data: []byte("NRSWC43VOJSS4==="), errs: []error{badErr}}, 225 res: "leasure.", err: badErr, dbuflen: 11}, 226 // Check that errors are correctly propagated when the reader returns valid bytes in 227 // groups that are not divisible by 8. The first read will return 11 bytes and no 228 // error. The second will return 7 and an error. The data should be decoded correctly 229 // and the error should be propagated. 230 {r: badReader{data: []byte("NRSWC43VOJSS4==="), errs: []error{nil, badErr}, limit: 11}, 231 res: "leasure.", err: badErr}, 232 } 233 234 for _, tc := range testCases { 235 input := tc.r.data 236 decoder := NewDecoder(StdEncoding, &tc.r) 237 var dbuflen int 238 if tc.dbuflen > 0 { 239 dbuflen = tc.dbuflen 240 } else { 241 dbuflen = StdEncoding.DecodedLen(len(input)) 242 } 243 dbuf := make([]byte, dbuflen) 244 var err error 245 var res []byte 246 for err == nil { 247 var n int 248 n, err = decoder.Read(dbuf) 249 if n > 0 { 250 res = append(res, dbuf[:n]...) 251 } 252 } 253 254 testEqual(t, "Decoding of %q = %q, want %q", string(input), string(res), tc.res) 255 testEqual(t, "Decoding of %q err = %v, expected %v", string(input), err, tc.err) 256 } 257 } 258 259 // TestDecoderError verifies decode errors are propagated when there are no read 260 // errors. 261 func TestDecoderError(t *testing.T) { 262 for _, readErr := range []error{io.EOF, nil} { 263 input := "MZXW6YTb" 264 dbuf := make([]byte, StdEncoding.DecodedLen(len(input))) 265 br := badReader{data: []byte(input), errs: []error{readErr}} 266 decoder := NewDecoder(StdEncoding, &br) 267 n, err := decoder.Read(dbuf) 268 testEqual(t, "Read after EOF, n = %d, expected %d", n, 0) 269 if _, ok := err.(CorruptInputError); !ok { 270 t.Errorf("Corrupt input error expected. Found %T", err) 271 } 272 } 273 } 274 275 // TestReaderEOF ensures decoder.Read behaves correctly when input data is 276 // exhausted. 277 func TestReaderEOF(t *testing.T) { 278 for _, readErr := range []error{io.EOF, nil} { 279 input := "MZXW6YTB" 280 br := badReader{data: []byte(input), errs: []error{nil, readErr}} 281 decoder := NewDecoder(StdEncoding, &br) 282 dbuf := make([]byte, StdEncoding.DecodedLen(len(input))) 283 n, err := decoder.Read(dbuf) 284 testEqual(t, "Decoding of %q err = %v, expected %v", input, err, error(nil)) 285 n, err = decoder.Read(dbuf) 286 testEqual(t, "Read after EOF, n = %d, expected %d", n, 0) 287 testEqual(t, "Read after EOF, err = %v, expected %v", err, io.EOF) 288 n, err = decoder.Read(dbuf) 289 testEqual(t, "Read after EOF, n = %d, expected %d", n, 0) 290 testEqual(t, "Read after EOF, err = %v, expected %v", err, io.EOF) 291 } 292 } 293 294 func TestDecoderBuffering(t *testing.T) { 295 for bs := 1; bs <= 12; bs++ { 296 decoder := NewDecoder(StdEncoding, strings.NewReader(bigtest.encoded)) 297 buf := make([]byte, len(bigtest.decoded)+12) 298 var total int 299 var n int 300 var err error 301 for total = 0; total < len(bigtest.decoded) && err == nil; { 302 n, err = decoder.Read(buf[total : total+bs]) 303 total += n 304 } 305 if err != nil && err != io.EOF { 306 t.Errorf("Read from %q at pos %d = %d, unexpected error %v", bigtest.encoded, total, n, err) 307 } 308 testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded) 309 } 310 } 311 312 func TestDecodeCorrupt(t *testing.T) { 313 testCases := []struct { 314 input string 315 offset int // -1 means no corruption. 316 }{ 317 {"", -1}, 318 {"!!!!", 0}, 319 {"x===", 0}, 320 {"AA=A====", 2}, 321 {"AAA=AAAA", 3}, 322 {"MMMMMMMMM", 8}, 323 {"MMMMMM", 0}, 324 {"A=", 1}, 325 {"AA=", 3}, 326 {"AA==", 4}, 327 {"AA===", 5}, 328 {"AAAA=", 5}, 329 {"AAAA==", 6}, 330 {"AAAAA=", 6}, 331 {"AAAAA==", 7}, 332 {"A=======", 1}, 333 {"AA======", -1}, 334 {"AAA=====", 3}, 335 {"AAAA====", -1}, 336 {"AAAAA===", -1}, 337 {"AAAAAA==", 6}, 338 {"AAAAAAA=", -1}, 339 {"AAAAAAAA", -1}, 340 } 341 for _, tc := range testCases { 342 dbuf := make([]byte, StdEncoding.DecodedLen(len(tc.input))) 343 _, err := StdEncoding.Decode(dbuf, []byte(tc.input)) 344 if tc.offset == -1 { 345 if err != nil { 346 t.Error("Decoder wrongly detected corruption in", tc.input) 347 } 348 continue 349 } 350 switch err := err.(type) { 351 case CorruptInputError: 352 testEqual(t, "Corruption in %q at offset %v, want %v", tc.input, int(err), tc.offset) 353 default: 354 t.Error("Decoder failed to detect corruption in", tc) 355 } 356 } 357 } 358 359 func TestBig(t *testing.T) { 360 n := 3*1000 + 1 361 raw := make([]byte, n) 362 const alpha = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 363 for i := 0; i < n; i++ { 364 raw[i] = alpha[i%len(alpha)] 365 } 366 encoded := new(bytes.Buffer) 367 w := NewEncoder(StdEncoding, encoded) 368 nn, err := w.Write(raw) 369 if nn != n || err != nil { 370 t.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn, err, n) 371 } 372 err = w.Close() 373 if err != nil { 374 t.Fatalf("Encoder.Close() = %v want nil", err) 375 } 376 decoded, err := io.ReadAll(NewDecoder(StdEncoding, encoded)) 377 if err != nil { 378 t.Fatalf("io.ReadAll(NewDecoder(...)): %v", err) 379 } 380 381 if !bytes.Equal(raw, decoded) { 382 var i int 383 for i = 0; i < len(decoded) && i < len(raw); i++ { 384 if decoded[i] != raw[i] { 385 break 386 } 387 } 388 t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i) 389 } 390 } 391 392 func testStringEncoding(t *testing.T, expected string, examples []string) { 393 for _, e := range examples { 394 buf, err := StdEncoding.DecodeString(e) 395 if err != nil { 396 t.Errorf("Decode(%q) failed: %v", e, err) 397 continue 398 } 399 if s := string(buf); s != expected { 400 t.Errorf("Decode(%q) = %q, want %q", e, s, expected) 401 } 402 } 403 } 404 405 func TestNewLineCharacters(t *testing.T) { 406 // Each of these should decode to the string "sure", without errors. 407 examples := []string{ 408 "ON2XEZI=", 409 "ON2XEZI=\r", 410 "ON2XEZI=\n", 411 "ON2XEZI=\r\n", 412 "ON2XEZ\r\nI=", 413 "ON2X\rEZ\nI=", 414 "ON2X\nEZ\rI=", 415 "ON2XEZ\nI=", 416 "ON2XEZI\n=", 417 } 418 testStringEncoding(t, "sure", examples) 419 420 // Each of these should decode to the string "foobar", without errors. 421 examples = []string{ 422 "MZXW6YTBOI======", 423 "MZXW6YTBOI=\r\n=====", 424 } 425 testStringEncoding(t, "foobar", examples) 426 } 427 428 func TestDecoderIssue4779(t *testing.T) { 429 encoded := `JRXXEZLNEBUXA43VNUQGI33MN5ZCA43JOQQGC3LFOQWCAY3PNZZWKY3UMV2HK4 430 RAMFSGS4DJONUWG2LOM4QGK3DJOQWCA43FMQQGI3YKMVUXK43NN5SCA5DFNVYG64RANFXGG2LENFSH 431 K3TUEB2XIIDMMFRG64TFEBSXIIDEN5WG64TFEBWWCZ3OMEQGC3DJOF2WCLRAKV2CAZLONFWQUYLEEB 432 WWS3TJNUQHMZLONFQW2LBAOF2WS4ZANZXXG5DSOVSCAZLYMVZGG2LUMF2GS33OEB2WY3DBNVRW6IDM 433 MFRG64TJOMQG42LTNEQHK5AKMFWGS4LVNFYCAZLYEBSWCIDDN5WW233EN4QGG33OONSXC5LBOQXCAR 434 DVNFZSAYLVORSSA2LSOVZGKIDEN5WG64RANFXAU4TFOBZGK2DFNZSGK4TJOQQGS3RAOZXWY5LQORQX 435 IZJAOZSWY2LUEBSXG43FEBRWS3DMOVWSAZDPNRXXEZJAMV2SAZTVM5UWC5BANZ2WY3DBBJYGC4TJMF 436 2HK4ROEBCXQY3FOB2GK5LSEBZWS3TUEBXWGY3BMVRWC5BAMN2XA2LEMF2GC5BANZXW4IDQOJXWSZDF 437 NZ2CYIDTOVXHIIDJNYFGG5LMOBQSA4LVNEQG6ZTGNFRWSYJAMRSXGZLSOVXHIIDNN5WGY2LUEBQW42 438 LNEBUWIIDFON2CA3DBMJXXE5LNFY== 439 ====` 440 encodedShort := strings.ReplaceAll(encoded, "\n", "") 441 442 dec := NewDecoder(StdEncoding, strings.NewReader(encoded)) 443 res1, err := io.ReadAll(dec) 444 if err != nil { 445 t.Errorf("ReadAll failed: %v", err) 446 } 447 448 dec = NewDecoder(StdEncoding, strings.NewReader(encodedShort)) 449 var res2 []byte 450 res2, err = io.ReadAll(dec) 451 if err != nil { 452 t.Errorf("ReadAll failed: %v", err) 453 } 454 455 if !bytes.Equal(res1, res2) { 456 t.Error("Decoded results not equal") 457 } 458 } 459 460 func BenchmarkEncode(b *testing.B) { 461 data := make([]byte, 8192) 462 buf := make([]byte, StdEncoding.EncodedLen(len(data))) 463 b.SetBytes(int64(len(data))) 464 for i := 0; i < b.N; i++ { 465 StdEncoding.Encode(buf, data) 466 } 467 } 468 469 func BenchmarkEncodeToString(b *testing.B) { 470 data := make([]byte, 8192) 471 b.SetBytes(int64(len(data))) 472 for i := 0; i < b.N; i++ { 473 StdEncoding.EncodeToString(data) 474 } 475 } 476 477 func BenchmarkDecode(b *testing.B) { 478 data := make([]byte, StdEncoding.EncodedLen(8192)) 479 StdEncoding.Encode(data, make([]byte, 8192)) 480 buf := make([]byte, 8192) 481 b.SetBytes(int64(len(data))) 482 for i := 0; i < b.N; i++ { 483 StdEncoding.Decode(buf, data) 484 } 485 } 486 func BenchmarkDecodeString(b *testing.B) { 487 data := StdEncoding.EncodeToString(make([]byte, 8192)) 488 b.SetBytes(int64(len(data))) 489 for i := 0; i < b.N; i++ { 490 StdEncoding.DecodeString(data) 491 } 492 } 493 494 func TestWithCustomPadding(t *testing.T) { 495 for _, testcase := range pairs { 496 defaultPadding := StdEncoding.EncodeToString([]byte(testcase.decoded)) 497 customPadding := StdEncoding.WithPadding('@').EncodeToString([]byte(testcase.decoded)) 498 expected := strings.ReplaceAll(defaultPadding, "=", "@") 499 500 if expected != customPadding { 501 t.Errorf("Expected custom %s, got %s", expected, customPadding) 502 } 503 if testcase.encoded != defaultPadding { 504 t.Errorf("Expected %s, got %s", testcase.encoded, defaultPadding) 505 } 506 } 507 } 508 509 func TestWithoutPadding(t *testing.T) { 510 for _, testcase := range pairs { 511 defaultPadding := StdEncoding.EncodeToString([]byte(testcase.decoded)) 512 customPadding := StdEncoding.WithPadding(NoPadding).EncodeToString([]byte(testcase.decoded)) 513 expected := strings.TrimRight(defaultPadding, "=") 514 515 if expected != customPadding { 516 t.Errorf("Expected custom %s, got %s", expected, customPadding) 517 } 518 if testcase.encoded != defaultPadding { 519 t.Errorf("Expected %s, got %s", testcase.encoded, defaultPadding) 520 } 521 } 522 } 523 524 func TestDecodeWithPadding(t *testing.T) { 525 encodings := []*Encoding{ 526 StdEncoding, 527 StdEncoding.WithPadding('-'), 528 StdEncoding.WithPadding(NoPadding), 529 } 530 531 for i, enc := range encodings { 532 for _, pair := range pairs { 533 534 input := pair.decoded 535 encoded := enc.EncodeToString([]byte(input)) 536 537 decoded, err := enc.DecodeString(encoded) 538 if err != nil { 539 t.Errorf("DecodeString Error for encoding %d (%q): %v", i, input, err) 540 } 541 542 if input != string(decoded) { 543 t.Errorf("Unexpected result for encoding %d: got %q; want %q", i, decoded, input) 544 } 545 } 546 } 547 } 548 549 func TestDecodeWithWrongPadding(t *testing.T) { 550 encoded := StdEncoding.EncodeToString([]byte("foobar")) 551 552 _, err := StdEncoding.WithPadding('-').DecodeString(encoded) 553 if err == nil { 554 t.Error("expected error") 555 } 556 557 _, err = StdEncoding.WithPadding(NoPadding).DecodeString(encoded) 558 if err == nil { 559 t.Error("expected error") 560 } 561 } 562 563 func TestBufferedDecodingSameError(t *testing.T) { 564 testcases := []struct { 565 prefix string 566 chunkCombinations [][]string 567 expected error 568 }{ 569 // NBSWY3DPO5XXE3DE == helloworld 570 // Test with "ZZ" as extra input 571 {"helloworld", [][]string{ 572 {"NBSW", "Y3DP", "O5XX", "E3DE", "ZZ"}, 573 {"NBSWY3DPO5XXE3DE", "ZZ"}, 574 {"NBSWY3DPO5XXE3DEZZ"}, 575 {"NBS", "WY3", "DPO", "5XX", "E3D", "EZZ"}, 576 {"NBSWY3DPO5XXE3", "DEZZ"}, 577 }, io.ErrUnexpectedEOF}, 578 579 // Test with "ZZY" as extra input 580 {"helloworld", [][]string{ 581 {"NBSW", "Y3DP", "O5XX", "E3DE", "ZZY"}, 582 {"NBSWY3DPO5XXE3DE", "ZZY"}, 583 {"NBSWY3DPO5XXE3DEZZY"}, 584 {"NBS", "WY3", "DPO", "5XX", "E3D", "EZZY"}, 585 {"NBSWY3DPO5XXE3", "DEZZY"}, 586 }, io.ErrUnexpectedEOF}, 587 588 // Normal case, this is valid input 589 {"helloworld", [][]string{ 590 {"NBSW", "Y3DP", "O5XX", "E3DE"}, 591 {"NBSWY3DPO5XXE3DE"}, 592 {"NBS", "WY3", "DPO", "5XX", "E3D", "E"}, 593 {"NBSWY3DPO5XXE3", "DE"}, 594 }, nil}, 595 596 // MZXW6YTB = fooba 597 {"fooba", [][]string{ 598 {"MZXW6YTBZZ"}, 599 {"MZXW6YTBZ", "Z"}, 600 {"MZXW6YTB", "ZZ"}, 601 {"MZXW6YT", "BZZ"}, 602 {"MZXW6Y", "TBZZ"}, 603 {"MZXW6Y", "TB", "ZZ"}, 604 {"MZXW6", "YTBZZ"}, 605 {"MZXW6", "YTB", "ZZ"}, 606 {"MZXW6", "YT", "BZZ"}, 607 }, io.ErrUnexpectedEOF}, 608 609 // Normal case, this is valid input 610 {"fooba", [][]string{ 611 {"MZXW6YTB"}, 612 {"MZXW6YT", "B"}, 613 {"MZXW6Y", "TB"}, 614 {"MZXW6", "YTB"}, 615 {"MZXW6", "YT", "B"}, 616 {"MZXW", "6YTB"}, 617 {"MZXW", "6Y", "TB"}, 618 }, nil}, 619 } 620 621 for _, testcase := range testcases { 622 for _, chunks := range testcase.chunkCombinations { 623 pr, pw := io.Pipe() 624 625 // Write the encoded chunks into the pipe 626 go func() { 627 for _, chunk := range chunks { 628 pw.Write([]byte(chunk)) 629 } 630 pw.Close() 631 }() 632 633 decoder := NewDecoder(StdEncoding, pr) 634 _, err := io.ReadAll(decoder) 635 636 if err != testcase.expected { 637 t.Errorf("Expected %v, got %v; case %s %+v", testcase.expected, err, testcase.prefix, chunks) 638 } 639 } 640 } 641 } 642 643 func TestBufferedDecodingPadding(t *testing.T) { 644 testcases := []struct { 645 chunks []string 646 expectedError string 647 }{ 648 {[]string{ 649 "I4======", 650 "==", 651 }, "unexpected EOF"}, 652 653 {[]string{ 654 "I4======N4======", 655 }, "illegal base32 data at input byte 2"}, 656 657 {[]string{ 658 "I4======", 659 "N4======", 660 }, "illegal base32 data at input byte 0"}, 661 662 {[]string{ 663 "I4======", 664 "========", 665 }, "illegal base32 data at input byte 0"}, 666 667 {[]string{ 668 "I4I4I4I4", 669 "I4======", 670 "I4======", 671 }, "illegal base32 data at input byte 0"}, 672 } 673 674 for _, testcase := range testcases { 675 testcase := testcase 676 pr, pw := io.Pipe() 677 go func() { 678 for _, chunk := range testcase.chunks { 679 _, _ = pw.Write([]byte(chunk)) 680 } 681 _ = pw.Close() 682 }() 683 684 decoder := NewDecoder(StdEncoding, pr) 685 _, err := io.ReadAll(decoder) 686 687 if err == nil && len(testcase.expectedError) != 0 { 688 t.Errorf("case %q: got nil error, want %v", testcase.chunks, testcase.expectedError) 689 } else if err.Error() != testcase.expectedError { 690 t.Errorf("case %q: got %v, want %v", testcase.chunks, err, testcase.expectedError) 691 } 692 } 693 } 694 695 func TestEncodedLen(t *testing.T) { 696 var rawStdEncoding = StdEncoding.WithPadding(NoPadding) 697 type test struct { 698 enc *Encoding 699 n int 700 want int64 701 } 702 tests := []test{ 703 {StdEncoding, 0, 0}, 704 {StdEncoding, 1, 8}, 705 {StdEncoding, 2, 8}, 706 {StdEncoding, 3, 8}, 707 {StdEncoding, 4, 8}, 708 {StdEncoding, 5, 8}, 709 {StdEncoding, 6, 16}, 710 {StdEncoding, 10, 16}, 711 {StdEncoding, 11, 24}, 712 {rawStdEncoding, 0, 0}, 713 {rawStdEncoding, 1, 2}, 714 {rawStdEncoding, 2, 4}, 715 {rawStdEncoding, 3, 5}, 716 {rawStdEncoding, 4, 7}, 717 {rawStdEncoding, 5, 8}, 718 {rawStdEncoding, 6, 10}, 719 {rawStdEncoding, 7, 12}, 720 {rawStdEncoding, 10, 16}, 721 {rawStdEncoding, 11, 18}, 722 } 723 // check overflow 724 switch strconv.IntSize { 725 case 32: 726 tests = append(tests, test{rawStdEncoding, (math.MaxInt-4)/8 + 1, 429496730}) 727 tests = append(tests, test{rawStdEncoding, math.MaxInt/8*5 + 4, math.MaxInt}) 728 case 64: 729 tests = append(tests, test{rawStdEncoding, (math.MaxInt-4)/8 + 1, 1844674407370955162}) 730 tests = append(tests, test{rawStdEncoding, math.MaxInt/8*5 + 4, math.MaxInt}) 731 } 732 for _, tt := range tests { 733 if got := tt.enc.EncodedLen(tt.n); int64(got) != tt.want { 734 t.Errorf("EncodedLen(%d): got %d, want %d", tt.n, got, tt.want) 735 } 736 } 737 } 738 739 func TestDecodedLen(t *testing.T) { 740 var rawStdEncoding = StdEncoding.WithPadding(NoPadding) 741 type test struct { 742 enc *Encoding 743 n int 744 want int64 745 } 746 tests := []test{ 747 {StdEncoding, 0, 0}, 748 {StdEncoding, 8, 5}, 749 {StdEncoding, 16, 10}, 750 {StdEncoding, 24, 15}, 751 {rawStdEncoding, 0, 0}, 752 {rawStdEncoding, 2, 1}, 753 {rawStdEncoding, 4, 2}, 754 {rawStdEncoding, 5, 3}, 755 {rawStdEncoding, 7, 4}, 756 {rawStdEncoding, 8, 5}, 757 {rawStdEncoding, 10, 6}, 758 {rawStdEncoding, 12, 7}, 759 {rawStdEncoding, 16, 10}, 760 {rawStdEncoding, 18, 11}, 761 } 762 // check overflow 763 switch strconv.IntSize { 764 case 32: 765 tests = append(tests, test{rawStdEncoding, math.MaxInt/5 + 1, 268435456}) 766 tests = append(tests, test{rawStdEncoding, math.MaxInt, 1342177279}) 767 case 64: 768 tests = append(tests, test{rawStdEncoding, math.MaxInt/5 + 1, 1152921504606846976}) 769 tests = append(tests, test{rawStdEncoding, math.MaxInt, 5764607523034234879}) 770 } 771 for _, tt := range tests { 772 if got := tt.enc.DecodedLen(tt.n); int64(got) != tt.want { 773 t.Errorf("DecodedLen(%d): got %d, want %d", tt.n, got, tt.want) 774 } 775 } 776 } 777 778 func TestWithoutPaddingClose(t *testing.T) { 779 encodings := []*Encoding{ 780 StdEncoding, 781 StdEncoding.WithPadding(NoPadding), 782 } 783 784 for _, encoding := range encodings { 785 for _, testpair := range pairs { 786 787 var buf strings.Builder 788 encoder := NewEncoder(encoding, &buf) 789 encoder.Write([]byte(testpair.decoded)) 790 encoder.Close() 791 792 expected := testpair.encoded 793 if encoding.padChar == NoPadding { 794 expected = strings.ReplaceAll(expected, "=", "") 795 } 796 797 res := buf.String() 798 799 if res != expected { 800 t.Errorf("Expected %s got %s; padChar=%d", expected, res, encoding.padChar) 801 } 802 } 803 } 804 } 805 806 func TestDecodeReadAll(t *testing.T) { 807 encodings := []*Encoding{ 808 StdEncoding, 809 StdEncoding.WithPadding(NoPadding), 810 } 811 812 for _, pair := range pairs { 813 for encIndex, encoding := range encodings { 814 encoded := pair.encoded 815 if encoding.padChar == NoPadding { 816 encoded = strings.ReplaceAll(encoded, "=", "") 817 } 818 819 decReader, err := io.ReadAll(NewDecoder(encoding, strings.NewReader(encoded))) 820 if err != nil { 821 t.Errorf("NewDecoder error: %v", err) 822 } 823 824 if pair.decoded != string(decReader) { 825 t.Errorf("Expected %s got %s; Encoding %d", pair.decoded, decReader, encIndex) 826 } 827 } 828 } 829 } 830 831 func TestDecodeSmallBuffer(t *testing.T) { 832 encodings := []*Encoding{ 833 StdEncoding, 834 StdEncoding.WithPadding(NoPadding), 835 } 836 837 for bufferSize := 1; bufferSize < 200; bufferSize++ { 838 for _, pair := range pairs { 839 for encIndex, encoding := range encodings { 840 encoded := pair.encoded 841 if encoding.padChar == NoPadding { 842 encoded = strings.ReplaceAll(encoded, "=", "") 843 } 844 845 decoder := NewDecoder(encoding, strings.NewReader(encoded)) 846 847 var allRead []byte 848 849 for { 850 buf := make([]byte, bufferSize) 851 n, err := decoder.Read(buf) 852 allRead = append(allRead, buf[0:n]...) 853 if err == io.EOF { 854 break 855 } 856 if err != nil { 857 t.Error(err) 858 } 859 } 860 861 if pair.decoded != string(allRead) { 862 t.Errorf("Expected %s got %s; Encoding %d; bufferSize %d", pair.decoded, allRead, encIndex, bufferSize) 863 } 864 } 865 } 866 } 867 }