github.com/kdevb0x/go@v0.0.0-20180115030120-39687051e9e7/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, 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 testEqual(t, "Decode(%q) = %q, want %q", encoded, string(dbuf[0:count]), p.decoded) 159 160 dbuf, err = tt.enc.DecodeString(encoded) 161 testEqual(t, "DecodeString(%q) = error %v, want %v", encoded, err, error(nil)) 162 testEqual(t, "DecodeString(%q) = %q, want %q", string(dbuf), p.decoded) 163 } 164 } 165 } 166 167 func TestDecoder(t *testing.T) { 168 for _, p := range pairs { 169 decoder := NewDecoder(StdEncoding, strings.NewReader(p.encoded)) 170 dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded))) 171 count, err := decoder.Read(dbuf) 172 if err != nil && err != io.EOF { 173 t.Fatal("Read failed", err) 174 } 175 testEqual(t, "Read from %q = length %v, want %v", p.encoded, count, len(p.decoded)) 176 testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded) 177 if err != io.EOF { 178 count, err = decoder.Read(dbuf) 179 } 180 testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF) 181 } 182 } 183 184 func TestDecoderBuffering(t *testing.T) { 185 for bs := 1; bs <= 12; bs++ { 186 decoder := NewDecoder(StdEncoding, strings.NewReader(bigtest.encoded)) 187 buf := make([]byte, len(bigtest.decoded)+12) 188 var total int 189 var n int 190 var err error 191 for total = 0; total < len(bigtest.decoded) && err == nil; { 192 n, err = decoder.Read(buf[total : total+bs]) 193 total += n 194 } 195 if err != nil && err != io.EOF { 196 t.Errorf("Read from %q at pos %d = %d, unexpected error %v", bigtest.encoded, total, n, err) 197 } 198 testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded) 199 } 200 } 201 202 func TestDecodeCorrupt(t *testing.T) { 203 testCases := []struct { 204 input string 205 offset int // -1 means no corruption. 206 }{ 207 {"", -1}, 208 {"\n", -1}, 209 {"AAA=\n", -1}, 210 {"AAAA\n", -1}, 211 {"!!!!", 0}, 212 {"====", 0}, 213 {"x===", 1}, 214 {"=AAA", 0}, 215 {"A=AA", 1}, 216 {"AA=A", 2}, 217 {"AA==A", 4}, 218 {"AAA=AAAA", 4}, 219 {"AAAAA", 4}, 220 {"AAAAAA", 4}, 221 {"A=", 1}, 222 {"A==", 1}, 223 {"AA=", 3}, 224 {"AA==", -1}, 225 {"AAA=", -1}, 226 {"AAAA", -1}, 227 {"AAAAAA=", 7}, 228 {"YWJjZA=====", 8}, 229 {"A!\n", 1}, 230 {"A=\n", 1}, 231 } 232 for _, tc := range testCases { 233 dbuf := make([]byte, StdEncoding.DecodedLen(len(tc.input))) 234 _, err := StdEncoding.Decode(dbuf, []byte(tc.input)) 235 if tc.offset == -1 { 236 if err != nil { 237 t.Error("Decoder wrongly detected corruption in", tc.input) 238 } 239 continue 240 } 241 switch err := err.(type) { 242 case CorruptInputError: 243 testEqual(t, "Corruption in %q at offset %v, want %v", tc.input, int(err), tc.offset) 244 default: 245 t.Error("Decoder failed to detect corruption in", tc) 246 } 247 } 248 } 249 250 func TestEncodedLen(t *testing.T) { 251 for _, tt := range []struct { 252 enc *Encoding 253 n int 254 want int 255 }{ 256 {RawStdEncoding, 0, 0}, 257 {RawStdEncoding, 1, 2}, 258 {RawStdEncoding, 2, 3}, 259 {RawStdEncoding, 3, 4}, 260 {RawStdEncoding, 7, 10}, 261 {StdEncoding, 0, 0}, 262 {StdEncoding, 1, 4}, 263 {StdEncoding, 2, 4}, 264 {StdEncoding, 3, 4}, 265 {StdEncoding, 4, 8}, 266 {StdEncoding, 7, 12}, 267 } { 268 if got := tt.enc.EncodedLen(tt.n); got != tt.want { 269 t.Errorf("EncodedLen(%d): got %d, want %d", tt.n, got, tt.want) 270 } 271 } 272 } 273 274 func TestDecodedLen(t *testing.T) { 275 for _, tt := range []struct { 276 enc *Encoding 277 n int 278 want int 279 }{ 280 {RawStdEncoding, 0, 0}, 281 {RawStdEncoding, 2, 1}, 282 {RawStdEncoding, 3, 2}, 283 {RawStdEncoding, 4, 3}, 284 {RawStdEncoding, 10, 7}, 285 {StdEncoding, 0, 0}, 286 {StdEncoding, 4, 3}, 287 {StdEncoding, 8, 6}, 288 } { 289 if got := tt.enc.DecodedLen(tt.n); got != tt.want { 290 t.Errorf("DecodedLen(%d): got %d, want %d", tt.n, got, tt.want) 291 } 292 } 293 } 294 295 func TestBig(t *testing.T) { 296 n := 3*1000 + 1 297 raw := make([]byte, n) 298 const alpha = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 299 for i := 0; i < n; i++ { 300 raw[i] = alpha[i%len(alpha)] 301 } 302 encoded := new(bytes.Buffer) 303 w := NewEncoder(StdEncoding, encoded) 304 nn, err := w.Write(raw) 305 if nn != n || err != nil { 306 t.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn, err, n) 307 } 308 err = w.Close() 309 if err != nil { 310 t.Fatalf("Encoder.Close() = %v want nil", err) 311 } 312 decoded, err := ioutil.ReadAll(NewDecoder(StdEncoding, encoded)) 313 if err != nil { 314 t.Fatalf("ioutil.ReadAll(NewDecoder(...)): %v", err) 315 } 316 317 if !bytes.Equal(raw, decoded) { 318 var i int 319 for i = 0; i < len(decoded) && i < len(raw); i++ { 320 if decoded[i] != raw[i] { 321 break 322 } 323 } 324 t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i) 325 } 326 } 327 328 func TestNewLineCharacters(t *testing.T) { 329 // Each of these should decode to the string "sure", without errors. 330 const expected = "sure" 331 examples := []string{ 332 "c3VyZQ==", 333 "c3VyZQ==\r", 334 "c3VyZQ==\n", 335 "c3VyZQ==\r\n", 336 "c3VyZ\r\nQ==", 337 "c3V\ryZ\nQ==", 338 "c3V\nyZ\rQ==", 339 "c3VyZ\nQ==", 340 "c3VyZQ\n==", 341 "c3VyZQ=\n=", 342 "c3VyZQ=\r\n\r\n=", 343 } 344 for _, e := range examples { 345 buf, err := StdEncoding.DecodeString(e) 346 if err != nil { 347 t.Errorf("Decode(%q) failed: %v", e, err) 348 continue 349 } 350 if s := string(buf); s != expected { 351 t.Errorf("Decode(%q) = %q, want %q", e, s, expected) 352 } 353 } 354 } 355 356 type nextRead struct { 357 n int // bytes to return 358 err error // error to return 359 } 360 361 // faultInjectReader returns data from source, rate-limited 362 // and with the errors as written to nextc. 363 type faultInjectReader struct { 364 source string 365 nextc <-chan nextRead 366 } 367 368 func (r *faultInjectReader) Read(p []byte) (int, error) { 369 nr := <-r.nextc 370 if len(p) > nr.n { 371 p = p[:nr.n] 372 } 373 n := copy(p, r.source) 374 r.source = r.source[n:] 375 return n, nr.err 376 } 377 378 // tests that we don't ignore errors from our underlying reader 379 func TestDecoderIssue3577(t *testing.T) { 380 next := make(chan nextRead, 10) 381 wantErr := errors.New("my error") 382 next <- nextRead{5, nil} 383 next <- nextRead{10, wantErr} 384 next <- nextRead{0, wantErr} 385 d := NewDecoder(StdEncoding, &faultInjectReader{ 386 source: "VHdhcyBicmlsbGlnLCBhbmQgdGhlIHNsaXRoeSB0b3Zlcw==", // twas brillig... 387 nextc: next, 388 }) 389 errc := make(chan error) 390 go func() { 391 _, err := ioutil.ReadAll(d) 392 errc <- err 393 }() 394 select { 395 case err := <-errc: 396 if err != wantErr { 397 t.Errorf("got error %v; want %v", err, wantErr) 398 } 399 case <-time.After(5 * time.Second): 400 t.Errorf("timeout; Decoder blocked without returning an error") 401 } 402 } 403 404 func TestDecoderIssue4779(t *testing.T) { 405 encoded := `CP/EAT8AAAEF 406 AQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAAB 407 BAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHx 408 Y3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm 409 9jdHV2d3h5ent8fX5/cRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS 410 0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14/NGlKSFtJXE1OT0 411 pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x//aAAwDAQACEQMRAD8A9VSSSSUpJJJJSkkkJ+Tj 412 1kiy1jCJJDnAcCTykpKkuQ6p/jN6FgmxlNduXawwAzaGH+V6jn/R/wCt71zdn+N/qL3kVYFNYB4N 413 ji6PDVjWpKp9TSXnvTf8bFNjg3qOEa2n6VlLpj/rT/pf567DpX1i6L1hs9Py67X8mqdtg/rUWbbf 414 +gkp0kkkklKSSSSUpJJJJT//0PVUkkklKVLq3WMDpGI7KzrNjADtYNXvI/Mqr/Pd/q9W3vaxjnvM 415 NaCXE9gNSvGPrf8AWS3qmba5jjsJhoB0DAf0NDf6sevf+/lf8Hj0JJATfWT6/dV6oXU1uOLQeKKn 416 EQP+Hubtfe/+R7Mf/g7f5xcocp++Z11JMCJPgFBxOg7/AOuqDx8I/ikpkXkmSdU8mJIJA/O8EMAy 417 j+mSARB/17pKVXYWHXjsj7yIex0PadzXMO1zT5KHoNA3HT8ietoGhgjsfA+CSnvvqh/jJtqsrwOv 418 2b6NGNzXfTYexzJ+nU7/ALkf4P8Awv6P9KvTQQ4AgyDqCF85Pho3CTB7eHwXoH+LT65uZbX9X+o2 419 bqbPb06551Y4 420 ` 421 encodedShort := strings.Replace(encoded, "\n", "", -1) 422 423 dec := NewDecoder(StdEncoding, strings.NewReader(encoded)) 424 res1, err := ioutil.ReadAll(dec) 425 if err != nil { 426 t.Errorf("ReadAll failed: %v", err) 427 } 428 429 dec = NewDecoder(StdEncoding, strings.NewReader(encodedShort)) 430 var res2 []byte 431 res2, err = ioutil.ReadAll(dec) 432 if err != nil { 433 t.Errorf("ReadAll failed: %v", err) 434 } 435 436 if !bytes.Equal(res1, res2) { 437 t.Error("Decoded results not equal") 438 } 439 } 440 441 func TestDecoderIssue7733(t *testing.T) { 442 s, err := StdEncoding.DecodeString("YWJjZA=====") 443 want := CorruptInputError(8) 444 if !reflect.DeepEqual(want, err) { 445 t.Errorf("Error = %v; want CorruptInputError(8)", err) 446 } 447 if string(s) != "abcd" { 448 t.Errorf("DecodeString = %q; want abcd", s) 449 } 450 } 451 452 func TestDecoderIssue15656(t *testing.T) { 453 _, err := StdEncoding.Strict().DecodeString("WvLTlMrX9NpYDQlEIFlnDB==") 454 want := CorruptInputError(22) 455 if !reflect.DeepEqual(want, err) { 456 t.Errorf("Error = %v; want CorruptInputError(22)", err) 457 } 458 _, err = StdEncoding.Strict().DecodeString("WvLTlMrX9NpYDQlEIFlnDA==") 459 if err != nil { 460 t.Errorf("Error = %v; want nil", err) 461 } 462 _, err = StdEncoding.DecodeString("WvLTlMrX9NpYDQlEIFlnDB==") 463 if err != nil { 464 t.Errorf("Error = %v; want nil", err) 465 } 466 } 467 468 func BenchmarkEncodeToString(b *testing.B) { 469 data := make([]byte, 8192) 470 b.SetBytes(int64(len(data))) 471 for i := 0; i < b.N; i++ { 472 StdEncoding.EncodeToString(data) 473 } 474 } 475 476 func BenchmarkDecodeString(b *testing.B) { 477 sizes := []int{2, 4, 8, 64, 8192} 478 benchFunc := func(b *testing.B, benchSize int) { 479 data := StdEncoding.EncodeToString(make([]byte, benchSize)) 480 b.SetBytes(int64(len(data))) 481 b.ResetTimer() 482 for i := 0; i < b.N; i++ { 483 StdEncoding.DecodeString(data) 484 } 485 } 486 for _, size := range sizes { 487 b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { 488 benchFunc(b, size) 489 }) 490 } 491 } 492 493 func TestDecoderRaw(t *testing.T) { 494 source := "AAAAAA" 495 want := []byte{0, 0, 0, 0} 496 497 // Direct. 498 dec1, err := RawURLEncoding.DecodeString(source) 499 if err != nil || !bytes.Equal(dec1, want) { 500 t.Errorf("RawURLEncoding.DecodeString(%q) = %x, %v, want %x, nil", source, dec1, err, want) 501 } 502 503 // Through reader. Used to fail. 504 r := NewDecoder(RawURLEncoding, bytes.NewReader([]byte(source))) 505 dec2, err := ioutil.ReadAll(io.LimitReader(r, 100)) 506 if err != nil || !bytes.Equal(dec2, want) { 507 t.Errorf("reading NewDecoder(RawURLEncoding, %q) = %x, %v, want %x, nil", source, dec2, err, want) 508 } 509 510 // Should work with padding. 511 r = NewDecoder(URLEncoding, bytes.NewReader([]byte(source+"=="))) 512 dec3, err := ioutil.ReadAll(r) 513 if err != nil || !bytes.Equal(dec3, want) { 514 t.Errorf("reading NewDecoder(URLEncoding, %q) = %x, %v, want %x, nil", source+"==", dec3, err, want) 515 } 516 }