github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/encoding/base64/base64_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 base64 6 7 import ( 8 "bytes" 9 "errors" 10 "fmt" 11 "io" 12 "io/ioutil" 13 "reflect" 14 "runtime/debug" 15 "strings" 16 "testing" 17 "time" 18 ) 19 20 type testpair struct { 21 decoded, encoded string 22 } 23 24 var pairs = []testpair{ 25 // RFC 3548 examples 26 {"\x14\xfb\x9c\x03\xd9\x7e", "FPucA9l+"}, 27 {"\x14\xfb\x9c\x03\xd9", "FPucA9k="}, 28 {"\x14\xfb\x9c\x03", "FPucAw=="}, 29 30 // RFC 4648 examples 31 {"", ""}, 32 {"f", "Zg=="}, 33 {"fo", "Zm8="}, 34 {"foo", "Zm9v"}, 35 {"foob", "Zm9vYg=="}, 36 {"fooba", "Zm9vYmE="}, 37 {"foobar", "Zm9vYmFy"}, 38 39 // Wikipedia examples 40 {"sure.", "c3VyZS4="}, 41 {"sure", "c3VyZQ=="}, 42 {"sur", "c3Vy"}, 43 {"su", "c3U="}, 44 {"leasure.", "bGVhc3VyZS4="}, 45 {"easure.", "ZWFzdXJlLg=="}, 46 {"asure.", "YXN1cmUu"}, 47 {"sure.", "c3VyZS4="}, 48 } 49 50 // Do nothing to a reference base64 string (leave in standard format) 51 func stdRef(ref string) string { 52 return ref 53 } 54 55 // Convert a reference string to URL-encoding 56 func urlRef(ref string) string { 57 ref = strings.ReplaceAll(ref, "+", "-") 58 ref = strings.ReplaceAll(ref, "/", "_") 59 return ref 60 } 61 62 // Convert a reference string to raw, unpadded format 63 func rawRef(ref string) string { 64 return strings.TrimRight(ref, "=") 65 } 66 67 // Both URL and unpadding conversions 68 func rawURLRef(ref string) string { 69 return rawRef(urlRef(ref)) 70 } 71 72 // A nonstandard encoding with a funny padding character, for testing 73 var funnyEncoding = NewEncoding(encodeStd).WithPadding(rune('@')) 74 75 func funnyRef(ref string) string { 76 return strings.ReplaceAll(ref, "=", "@") 77 } 78 79 type encodingTest struct { 80 enc *Encoding // Encoding to test 81 conv func(string) string // Reference string converter 82 } 83 84 var encodingTests = []encodingTest{ 85 {StdEncoding, stdRef}, 86 {URLEncoding, urlRef}, 87 {RawStdEncoding, rawRef}, 88 {RawURLEncoding, rawURLRef}, 89 {funnyEncoding, funnyRef}, 90 {StdEncoding.Strict(), stdRef}, 91 {URLEncoding.Strict(), urlRef}, 92 {RawStdEncoding.Strict(), rawRef}, 93 {RawURLEncoding.Strict(), rawURLRef}, 94 {funnyEncoding.Strict(), funnyRef}, 95 } 96 97 var bigtest = testpair{ 98 "Twas brillig, and the slithy toves", 99 "VHdhcyBicmlsbGlnLCBhbmQgdGhlIHNsaXRoeSB0b3Zlcw==", 100 } 101 102 func testEqual(t *testing.T, msg string, args ...interface{}) bool { 103 t.Helper() 104 if args[len(args)-2] != args[len(args)-1] { 105 t.Errorf(msg, args...) 106 return false 107 } 108 return true 109 } 110 111 func TestEncode(t *testing.T) { 112 for _, p := range pairs { 113 for _, tt := range encodingTests { 114 got := tt.enc.EncodeToString([]byte(p.decoded)) 115 testEqual(t, "Encode(%q) = %q, want %q", p.decoded, 116 got, tt.conv(p.encoded)) 117 } 118 } 119 } 120 121 func TestEncoder(t *testing.T) { 122 for _, p := range pairs { 123 bb := &bytes.Buffer{} 124 encoder := NewEncoder(StdEncoding, bb) 125 encoder.Write([]byte(p.decoded)) 126 encoder.Close() 127 testEqual(t, "Encode(%q) = %q, want %q", p.decoded, bb.String(), p.encoded) 128 } 129 } 130 131 func TestEncoderBuffering(t *testing.T) { 132 input := []byte(bigtest.decoded) 133 for bs := 1; bs <= 12; bs++ { 134 bb := &bytes.Buffer{} 135 encoder := NewEncoder(StdEncoding, bb) 136 for pos := 0; pos < len(input); pos += bs { 137 end := pos + bs 138 if end > len(input) { 139 end = len(input) 140 } 141 n, err := encoder.Write(input[pos:end]) 142 testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, error(nil)) 143 testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos) 144 } 145 err := encoder.Close() 146 testEqual(t, "Close gave error %v, want %v", err, error(nil)) 147 testEqual(t, "Encoding/%d of %q = %q, want %q", bs, bigtest.decoded, bb.String(), bigtest.encoded) 148 } 149 } 150 151 func TestDecode(t *testing.T) { 152 for _, p := range pairs { 153 for _, tt := range encodingTests { 154 encoded := tt.conv(p.encoded) 155 dbuf := make([]byte, tt.enc.DecodedLen(len(encoded))) 156 count, err := tt.enc.Decode(dbuf, []byte(encoded)) 157 testEqual(t, "Decode(%q) = error %v, want %v", encoded, err, error(nil)) 158 testEqual(t, "Decode(%q) = length %v, want %v", encoded, count, len(p.decoded)) 159 testEqual(t, "Decode(%q) = %q, want %q", encoded, string(dbuf[0:count]), p.decoded) 160 161 dbuf, err = tt.enc.DecodeString(encoded) 162 testEqual(t, "DecodeString(%q) = error %v, want %v", encoded, err, error(nil)) 163 testEqual(t, "DecodeString(%q) = %q, want %q", encoded, string(dbuf), p.decoded) 164 } 165 } 166 } 167 168 func TestDecoder(t *testing.T) { 169 for _, p := range pairs { 170 decoder := NewDecoder(StdEncoding, strings.NewReader(p.encoded)) 171 dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded))) 172 count, err := decoder.Read(dbuf) 173 if err != nil && err != io.EOF { 174 t.Fatal("Read failed", err) 175 } 176 testEqual(t, "Read from %q = length %v, want %v", p.encoded, count, len(p.decoded)) 177 testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded) 178 if err != io.EOF { 179 _, err = decoder.Read(dbuf) 180 } 181 testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF) 182 } 183 } 184 185 func TestDecoderBuffering(t *testing.T) { 186 for bs := 1; bs <= 12; bs++ { 187 decoder := NewDecoder(StdEncoding, strings.NewReader(bigtest.encoded)) 188 buf := make([]byte, len(bigtest.decoded)+12) 189 var total int 190 var n int 191 var err error 192 for total = 0; total < len(bigtest.decoded) && err == nil; { 193 n, err = decoder.Read(buf[total : total+bs]) 194 total += n 195 } 196 if err != nil && err != io.EOF { 197 t.Errorf("Read from %q at pos %d = %d, unexpected error %v", bigtest.encoded, total, n, err) 198 } 199 testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded) 200 } 201 } 202 203 func TestDecodeCorrupt(t *testing.T) { 204 testCases := []struct { 205 input string 206 offset int // -1 means no corruption. 207 }{ 208 {"", -1}, 209 {"\n", -1}, 210 {"AAA=\n", -1}, 211 {"AAAA\n", -1}, 212 {"!!!!", 0}, 213 {"====", 0}, 214 {"x===", 1}, 215 {"=AAA", 0}, 216 {"A=AA", 1}, 217 {"AA=A", 2}, 218 {"AA==A", 4}, 219 {"AAA=AAAA", 4}, 220 {"AAAAA", 4}, 221 {"AAAAAA", 4}, 222 {"A=", 1}, 223 {"A==", 1}, 224 {"AA=", 3}, 225 {"AA==", -1}, 226 {"AAA=", -1}, 227 {"AAAA", -1}, 228 {"AAAAAA=", 7}, 229 {"YWJjZA=====", 8}, 230 {"A!\n", 1}, 231 {"A=\n", 1}, 232 } 233 for _, tc := range testCases { 234 dbuf := make([]byte, StdEncoding.DecodedLen(len(tc.input))) 235 _, err := StdEncoding.Decode(dbuf, []byte(tc.input)) 236 if tc.offset == -1 { 237 if err != nil { 238 t.Error("Decoder wrongly detected corruption in", tc.input) 239 } 240 continue 241 } 242 switch err := err.(type) { 243 case CorruptInputError: 244 testEqual(t, "Corruption in %q at offset %v, want %v", tc.input, int(err), tc.offset) 245 default: 246 t.Error("Decoder failed to detect corruption in", tc) 247 } 248 } 249 } 250 251 func TestDecodeBounds(t *testing.T) { 252 var buf [32]byte 253 s := StdEncoding.EncodeToString(buf[:]) 254 defer func() { 255 if err := recover(); err != nil { 256 t.Fatalf("Decode panicked unexpectedly: %v\n%s", err, debug.Stack()) 257 } 258 }() 259 n, err := StdEncoding.Decode(buf[:], []byte(s)) 260 if n != len(buf) || err != nil { 261 t.Fatalf("StdEncoding.Decode = %d, %v, want %d, nil", n, err, len(buf)) 262 } 263 } 264 265 func TestEncodedLen(t *testing.T) { 266 for _, tt := range []struct { 267 enc *Encoding 268 n int 269 want int 270 }{ 271 {RawStdEncoding, 0, 0}, 272 {RawStdEncoding, 1, 2}, 273 {RawStdEncoding, 2, 3}, 274 {RawStdEncoding, 3, 4}, 275 {RawStdEncoding, 7, 10}, 276 {StdEncoding, 0, 0}, 277 {StdEncoding, 1, 4}, 278 {StdEncoding, 2, 4}, 279 {StdEncoding, 3, 4}, 280 {StdEncoding, 4, 8}, 281 {StdEncoding, 7, 12}, 282 } { 283 if got := tt.enc.EncodedLen(tt.n); got != tt.want { 284 t.Errorf("EncodedLen(%d): got %d, want %d", tt.n, got, tt.want) 285 } 286 } 287 } 288 289 func TestDecodedLen(t *testing.T) { 290 for _, tt := range []struct { 291 enc *Encoding 292 n int 293 want int 294 }{ 295 {RawStdEncoding, 0, 0}, 296 {RawStdEncoding, 2, 1}, 297 {RawStdEncoding, 3, 2}, 298 {RawStdEncoding, 4, 3}, 299 {RawStdEncoding, 10, 7}, 300 {StdEncoding, 0, 0}, 301 {StdEncoding, 4, 3}, 302 {StdEncoding, 8, 6}, 303 } { 304 if got := tt.enc.DecodedLen(tt.n); got != tt.want { 305 t.Errorf("DecodedLen(%d): got %d, want %d", tt.n, got, tt.want) 306 } 307 } 308 } 309 310 func TestBig(t *testing.T) { 311 n := 3*1000 + 1 312 raw := make([]byte, n) 313 const alpha = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 314 for i := 0; i < n; i++ { 315 raw[i] = alpha[i%len(alpha)] 316 } 317 encoded := new(bytes.Buffer) 318 w := NewEncoder(StdEncoding, encoded) 319 nn, err := w.Write(raw) 320 if nn != n || err != nil { 321 t.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn, err, n) 322 } 323 err = w.Close() 324 if err != nil { 325 t.Fatalf("Encoder.Close() = %v want nil", err) 326 } 327 decoded, err := ioutil.ReadAll(NewDecoder(StdEncoding, encoded)) 328 if err != nil { 329 t.Fatalf("ioutil.ReadAll(NewDecoder(...)): %v", err) 330 } 331 332 if !bytes.Equal(raw, decoded) { 333 var i int 334 for i = 0; i < len(decoded) && i < len(raw); i++ { 335 if decoded[i] != raw[i] { 336 break 337 } 338 } 339 t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i) 340 } 341 } 342 343 func TestNewLineCharacters(t *testing.T) { 344 // Each of these should decode to the string "sure", without errors. 345 const expected = "sure" 346 examples := []string{ 347 "c3VyZQ==", 348 "c3VyZQ==\r", 349 "c3VyZQ==\n", 350 "c3VyZQ==\r\n", 351 "c3VyZ\r\nQ==", 352 "c3V\ryZ\nQ==", 353 "c3V\nyZ\rQ==", 354 "c3VyZ\nQ==", 355 "c3VyZQ\n==", 356 "c3VyZQ=\n=", 357 "c3VyZQ=\r\n\r\n=", 358 } 359 for _, e := range examples { 360 buf, err := StdEncoding.DecodeString(e) 361 if err != nil { 362 t.Errorf("Decode(%q) failed: %v", e, err) 363 continue 364 } 365 if s := string(buf); s != expected { 366 t.Errorf("Decode(%q) = %q, want %q", e, s, expected) 367 } 368 } 369 } 370 371 type nextRead struct { 372 n int // bytes to return 373 err error // error to return 374 } 375 376 // faultInjectReader returns data from source, rate-limited 377 // and with the errors as written to nextc. 378 type faultInjectReader struct { 379 source string 380 nextc <-chan nextRead 381 } 382 383 func (r *faultInjectReader) Read(p []byte) (int, error) { 384 nr := <-r.nextc 385 if len(p) > nr.n { 386 p = p[:nr.n] 387 } 388 n := copy(p, r.source) 389 r.source = r.source[n:] 390 return n, nr.err 391 } 392 393 // tests that we don't ignore errors from our underlying reader 394 func TestDecoderIssue3577(t *testing.T) { 395 next := make(chan nextRead, 10) 396 wantErr := errors.New("my error") 397 next <- nextRead{5, nil} 398 next <- nextRead{10, wantErr} 399 next <- nextRead{0, wantErr} 400 d := NewDecoder(StdEncoding, &faultInjectReader{ 401 source: "VHdhcyBicmlsbGlnLCBhbmQgdGhlIHNsaXRoeSB0b3Zlcw==", // twas brillig... 402 nextc: next, 403 }) 404 errc := make(chan error) 405 go func() { 406 _, err := ioutil.ReadAll(d) 407 errc <- err 408 }() 409 select { 410 case err := <-errc: 411 if err != wantErr { 412 t.Errorf("got error %v; want %v", err, wantErr) 413 } 414 case <-time.After(5 * time.Second): 415 t.Errorf("timeout; Decoder blocked without returning an error") 416 } 417 } 418 419 func TestDecoderIssue4779(t *testing.T) { 420 encoded := `CP/EAT8AAAEF 421 AQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAAB 422 BAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHx 423 Y3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm 424 9jdHV2d3h5ent8fX5/cRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS 425 0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14/NGlKSFtJXE1OT0 426 pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x//aAAwDAQACEQMRAD8A9VSSSSUpJJJJSkkkJ+Tj 427 1kiy1jCJJDnAcCTykpKkuQ6p/jN6FgmxlNduXawwAzaGH+V6jn/R/wCt71zdn+N/qL3kVYFNYB4N 428 ji6PDVjWpKp9TSXnvTf8bFNjg3qOEa2n6VlLpj/rT/pf567DpX1i6L1hs9Py67X8mqdtg/rUWbbf 429 +gkp0kkkklKSSSSUpJJJJT//0PVUkkklKVLq3WMDpGI7KzrNjADtYNXvI/Mqr/Pd/q9W3vaxjnvM 430 NaCXE9gNSvGPrf8AWS3qmba5jjsJhoB0DAf0NDf6sevf+/lf8Hj0JJATfWT6/dV6oXU1uOLQeKKn 431 EQP+Hubtfe/+R7Mf/g7f5xcocp++Z11JMCJPgFBxOg7/AOuqDx8I/ikpkXkmSdU8mJIJA/O8EMAy 432 j+mSARB/17pKVXYWHXjsj7yIex0PadzXMO1zT5KHoNA3HT8ietoGhgjsfA+CSnvvqh/jJtqsrwOv 433 2b6NGNzXfTYexzJ+nU7/ALkf4P8Awv6P9KvTQQ4AgyDqCF85Pho3CTB7eHwXoH+LT65uZbX9X+o2 434 bqbPb06551Y4 435 ` 436 encodedShort := strings.ReplaceAll(encoded, "\n", "") 437 438 dec := NewDecoder(StdEncoding, strings.NewReader(encoded)) 439 res1, err := ioutil.ReadAll(dec) 440 if err != nil { 441 t.Errorf("ReadAll failed: %v", err) 442 } 443 444 dec = NewDecoder(StdEncoding, strings.NewReader(encodedShort)) 445 var res2 []byte 446 res2, err = ioutil.ReadAll(dec) 447 if err != nil { 448 t.Errorf("ReadAll failed: %v", err) 449 } 450 451 if !bytes.Equal(res1, res2) { 452 t.Error("Decoded results not equal") 453 } 454 } 455 456 func TestDecoderIssue7733(t *testing.T) { 457 s, err := StdEncoding.DecodeString("YWJjZA=====") 458 want := CorruptInputError(8) 459 if !reflect.DeepEqual(want, err) { 460 t.Errorf("Error = %v; want CorruptInputError(8)", err) 461 } 462 if string(s) != "abcd" { 463 t.Errorf("DecodeString = %q; want abcd", s) 464 } 465 } 466 467 func TestDecoderIssue15656(t *testing.T) { 468 _, err := StdEncoding.Strict().DecodeString("WvLTlMrX9NpYDQlEIFlnDB==") 469 want := CorruptInputError(22) 470 if !reflect.DeepEqual(want, err) { 471 t.Errorf("Error = %v; want CorruptInputError(22)", err) 472 } 473 _, err = StdEncoding.Strict().DecodeString("WvLTlMrX9NpYDQlEIFlnDA==") 474 if err != nil { 475 t.Errorf("Error = %v; want nil", err) 476 } 477 _, err = StdEncoding.DecodeString("WvLTlMrX9NpYDQlEIFlnDB==") 478 if err != nil { 479 t.Errorf("Error = %v; want nil", err) 480 } 481 } 482 483 func BenchmarkEncodeToString(b *testing.B) { 484 data := make([]byte, 8192) 485 b.SetBytes(int64(len(data))) 486 for i := 0; i < b.N; i++ { 487 StdEncoding.EncodeToString(data) 488 } 489 } 490 491 func BenchmarkDecodeString(b *testing.B) { 492 sizes := []int{2, 4, 8, 64, 8192} 493 benchFunc := func(b *testing.B, benchSize int) { 494 data := StdEncoding.EncodeToString(make([]byte, benchSize)) 495 b.SetBytes(int64(len(data))) 496 b.ResetTimer() 497 for i := 0; i < b.N; i++ { 498 StdEncoding.DecodeString(data) 499 } 500 } 501 for _, size := range sizes { 502 b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { 503 benchFunc(b, size) 504 }) 505 } 506 } 507 508 func TestDecoderRaw(t *testing.T) { 509 source := "AAAAAA" 510 want := []byte{0, 0, 0, 0} 511 512 // Direct. 513 dec1, err := RawURLEncoding.DecodeString(source) 514 if err != nil || !bytes.Equal(dec1, want) { 515 t.Errorf("RawURLEncoding.DecodeString(%q) = %x, %v, want %x, nil", source, dec1, err, want) 516 } 517 518 // Through reader. Used to fail. 519 r := NewDecoder(RawURLEncoding, bytes.NewReader([]byte(source))) 520 dec2, err := ioutil.ReadAll(io.LimitReader(r, 100)) 521 if err != nil || !bytes.Equal(dec2, want) { 522 t.Errorf("reading NewDecoder(RawURLEncoding, %q) = %x, %v, want %x, nil", source, dec2, err, want) 523 } 524 525 // Should work with padding. 526 r = NewDecoder(URLEncoding, bytes.NewReader([]byte(source+"=="))) 527 dec3, err := ioutil.ReadAll(r) 528 if err != nil || !bytes.Equal(dec3, want) { 529 t.Errorf("reading NewDecoder(URLEncoding, %q) = %x, %v, want %x, nil", source+"==", dec3, err, want) 530 } 531 }