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