github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/klauspost/compress/snappy/snappy_test.go (about) 1 // Copyright 2011 The Snappy-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 //+build go1.4 6 7 package snappy 8 9 import ( 10 "bytes" 11 "flag" 12 "fmt" 13 "io" 14 "io/ioutil" 15 "math/rand" 16 "net/http" 17 "os" 18 "path/filepath" 19 "strings" 20 "testing" 21 22 old "github.com/insionng/yougam/libraries/golang/snappy" 23 ) 24 25 var ( 26 download = flag.Bool("download", false, "If true, download any missing files before running benchmarks") 27 testdata = flag.String("testdata", "testdata", "Directory containing the test data") 28 ) 29 30 func TestMaxEncodedLenOfMaxUncompressedChunkLen(t *testing.T) { 31 got := maxEncodedLenOfMaxUncompressedChunkLen 32 want := MaxEncodedLen(maxUncompressedChunkLen) 33 if got != want { 34 t.Fatalf("got %d, want %d", got, want) 35 } 36 } 37 38 func roundtrip(b, ebuf, dbuf []byte) error { 39 d, err := Decode(dbuf, Encode(ebuf, b)) 40 if err != nil { 41 return fmt.Errorf("decoding error: %v", err) 42 } 43 if !bytes.Equal(b, d) { 44 return fmt.Errorf("roundtrip mismatch:\n\twant %v\n\tgot %v", b, d) 45 } 46 return nil 47 } 48 49 func TestEmpty(t *testing.T) { 50 if err := roundtrip(nil, nil, nil); err != nil { 51 t.Fatal(err) 52 } 53 } 54 55 func TestSmallCopy(t *testing.T) { 56 for _, ebuf := range [][]byte{nil, make([]byte, 20), make([]byte, 64)} { 57 for _, dbuf := range [][]byte{nil, make([]byte, 20), make([]byte, 64)} { 58 for i := 0; i < 32; i++ { 59 s := "aaaa" + strings.Repeat("b", i) + "aaaabbbb" 60 if err := roundtrip([]byte(s), ebuf, dbuf); err != nil { 61 t.Errorf("len(ebuf)=%d, len(dbuf)=%d, i=%d: %v", len(ebuf), len(dbuf), i, err) 62 } 63 } 64 } 65 } 66 } 67 68 func TestSmallRand(t *testing.T) { 69 rng := rand.New(rand.NewSource(1)) 70 for n := 1; n < 20000; n += 23 { 71 b := make([]byte, n) 72 for i := range b { 73 b[i] = uint8(rng.Uint32()) 74 } 75 if err := roundtrip(b, nil, nil); err != nil { 76 t.Fatal(err) 77 } 78 } 79 } 80 81 func TestSmallRegular(t *testing.T) { 82 for n := 1; n < 20000; n += 23 { 83 b := make([]byte, n) 84 for i := range b { 85 b[i] = uint8(i%10 + 'a') 86 } 87 if err := roundtrip(b, nil, nil); err != nil { 88 t.Fatal(err) 89 } 90 } 91 } 92 93 func TestInvalidVarint(t *testing.T) { 94 data := []byte("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00") 95 if _, err := DecodedLen(data); err != ErrCorrupt { 96 t.Errorf("DecodedLen: got %v, want ErrCorrupt", err) 97 } 98 if _, err := Decode(nil, data); err != ErrCorrupt { 99 t.Errorf("Decode: got %v, want ErrCorrupt", err) 100 } 101 102 // The encoded varint overflows 32 bits 103 data = []byte("\xff\xff\xff\xff\xff\x00") 104 105 if _, err := DecodedLen(data); err != ErrCorrupt { 106 t.Errorf("DecodedLen: got %v, want ErrCorrupt", err) 107 } 108 if _, err := Decode(nil, data); err != ErrCorrupt { 109 t.Errorf("Decode: got %v, want ErrCorrupt", err) 110 } 111 } 112 113 func TestDecode(t *testing.T) { 114 testCases := []struct { 115 desc string 116 input string 117 want string 118 wantErr error 119 }{{ 120 `decodedLen=0x100000000 is too long`, 121 "\x80\x80\x80\x80\x10" + "\x00\x41", 122 "", 123 ErrCorrupt, 124 }, { 125 `decodedLen=3; tagLiteral, 0-byte length; length=3; valid input`, 126 "\x03" + "\x08\xff\xff\xff", 127 "\xff\xff\xff", 128 nil, 129 }, { 130 `decodedLen=1; tagLiteral, 1-byte length; not enough length bytes`, 131 "\x01" + "\xf0", 132 "", 133 ErrCorrupt, 134 }, { 135 `decodedLen=3; tagLiteral, 1-byte length; length=3; valid input`, 136 "\x03" + "\xf0\x02\xff\xff\xff", 137 "\xff\xff\xff", 138 nil, 139 }, { 140 `decodedLen=1; tagLiteral, 2-byte length; not enough length bytes`, 141 "\x01" + "\xf4\x00", 142 "", 143 ErrCorrupt, 144 }, { 145 `decodedLen=3; tagLiteral, 2-byte length; length=3; valid input`, 146 "\x03" + "\xf4\x02\x00\xff\xff\xff", 147 "\xff\xff\xff", 148 nil, 149 }, { 150 `decodedLen=1; tagLiteral, 3-byte length; not enough length bytes`, 151 "\x01" + "\xf8\x00\x00", 152 "", 153 ErrCorrupt, 154 }, { 155 `decodedLen=3; tagLiteral, 3-byte length; length=3; valid input`, 156 "\x03" + "\xf8\x02\x00\x00\xff\xff\xff", 157 "\xff\xff\xff", 158 nil, 159 }, { 160 `decodedLen=1; tagLiteral, 4-byte length; not enough length bytes`, 161 "\x01" + "\xfc\x00\x00\x00", 162 "", 163 ErrCorrupt, 164 }, { 165 `decodedLen=1; tagLiteral, 4-byte length; length=3; not enough dst bytes`, 166 "\x01" + "\xfc\x02\x00\x00\x00\xff\xff\xff", 167 "", 168 ErrCorrupt, 169 }, { 170 `decodedLen=4; tagLiteral, 4-byte length; length=3; not enough src bytes`, 171 "\x04" + "\xfc\x02\x00\x00\x00\xff", 172 "", 173 ErrCorrupt, 174 }, { 175 `decodedLen=3; tagLiteral, 4-byte length; length=3; valid input`, 176 "\x03" + "\xfc\x02\x00\x00\x00\xff\xff\xff", 177 "\xff\xff\xff", 178 nil, 179 }, { 180 `decodedLen=4; tagCopy1, 1 extra length|offset byte; not enough extra bytes`, 181 "\x04" + "\x01", 182 "", 183 ErrCorrupt, 184 }, { 185 `decodedLen=4; tagCopy2, 2 extra length|offset bytes; not enough extra bytes`, 186 "\x04" + "\x02\x00", 187 "", 188 ErrCorrupt, 189 }, { 190 `decodedLen=4; tagCopy4; unsupported COPY_4 tag`, 191 "\x04" + "\x03\x00\x00\x00\x00", 192 "", 193 errUnsupportedCopy4Tag, 194 }, { 195 `decodedLen=4; tagLiteral (4 bytes "abcd"); valid input`, 196 "\x04" + "\x0cabcd", 197 "abcd", 198 nil, 199 }, { 200 `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=4; valid input`, 201 "\x08" + "\x0cabcd" + "\x01\x04", 202 "abcdabcd", 203 nil, 204 }, { 205 `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=2; valid input`, 206 "\x08" + "\x0cabcd" + "\x01\x02", 207 "abcdcdcd", 208 nil, 209 }, { 210 `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=1; valid input`, 211 "\x08" + "\x0cabcd" + "\x01\x01", 212 "abcddddd", 213 nil, 214 }, { 215 `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=0; zero offset`, 216 "\x08" + "\x0cabcd" + "\x01\x00", 217 "", 218 ErrCorrupt, 219 }, { 220 `decodedLen=9; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=4; inconsistent dLen`, 221 "\x09" + "\x0cabcd" + "\x01\x04", 222 "", 223 ErrCorrupt, 224 }, { 225 `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=5; offset too large`, 226 "\x08" + "\x0cabcd" + "\x01\x05", 227 "", 228 ErrCorrupt, 229 }, { 230 `decodedLen=7; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=4; length too large`, 231 "\x07" + "\x0cabcd" + "\x01\x04", 232 "", 233 ErrCorrupt, 234 }} 235 236 for _, tc := range testCases { 237 g, gotErr := Decode(nil, []byte(tc.input)) 238 if got := string(g); got != tc.want || gotErr != tc.wantErr { 239 t.Errorf("%s:\ngot %q, %v\nwant %q, %v", tc.desc, got, gotErr, tc.want, tc.wantErr) 240 } 241 } 242 } 243 244 // TestEncodeNoiseThenRepeats encodes a 32K block for which the first half is 245 // very incompressible and the second half is very compressible. The encoded 246 // form's length should be closer to 50% of the original length than 100%. 247 func TestEncodeNoiseThenRepeats(t *testing.T) { 248 const origLen = 32768 249 src := make([]byte, origLen) 250 rng := rand.New(rand.NewSource(1)) 251 firstHalf, secondHalf := src[:origLen/2], src[origLen/2:] 252 for i := range firstHalf { 253 firstHalf[i] = uint8(rng.Intn(256)) 254 } 255 for i := range secondHalf { 256 secondHalf[i] = uint8(i >> 8) 257 } 258 dst := Encode(nil, src) 259 if got, want := len(dst), origLen*3/4; got >= want { 260 t.Fatalf("got %d encoded bytes, want less than %d", got, want) 261 } 262 } 263 264 // TestEncodeNoiseThenRepeats encodes a 8GB block for which the first half is 265 // very incompressible and the second half is very compressible. The encoded 266 // form's length should be closer to 50% of the original length than 100%. 267 func TestEncodeNoiseThenRepeatsBig(t *testing.T) { 268 const origLen = 8 << 20 269 src := make([]byte, origLen) 270 rng := rand.New(rand.NewSource(1)) 271 firstHalf, secondHalf := src[:origLen/2], src[origLen/2:] 272 for i := range firstHalf { 273 firstHalf[i] = uint8(rng.Intn(256)) 274 } 275 for i := range secondHalf { 276 secondHalf[i] = uint8(i >> 8) 277 } 278 dst := Encode(nil, src) 279 if got, want := len(dst), origLen*3/4; got >= want { 280 t.Fatalf("got %d encoded bytes, want less than %d", got, want) 281 } 282 } 283 284 func cmp(a, b []byte) error { 285 if len(a) != len(b) { 286 return fmt.Errorf("got %d bytes, want %d", len(a), len(b)) 287 } 288 for i := range a { 289 if a[i] != b[i] { 290 return fmt.Errorf("byte #%d: got 0x%02x, want 0x%02x", i, a[i], b[i]) 291 } 292 } 293 return nil 294 } 295 296 func TestFramingFormat(t *testing.T) { 297 // src is comprised of alternating 1e5-sized sequences of random 298 // (incompressible) bytes and repeated (compressible) bytes. 1e5 was chosen 299 // because it is larger than maxUncompressedChunkLen (64k). 300 src := make([]byte, 1e6) 301 rng := rand.New(rand.NewSource(1)) 302 for i := 0; i < 10; i++ { 303 if i%2 == 0 { 304 for j := 0; j < 1e5; j++ { 305 src[1e5*i+j] = uint8(rng.Intn(256)) 306 } 307 } else { 308 for j := 0; j < 1e5; j++ { 309 src[1e5*i+j] = uint8(i) 310 } 311 } 312 } 313 314 buf := new(bytes.Buffer) 315 if _, err := NewWriter(buf).Write(src); err != nil { 316 t.Fatalf("Write: encoding: %v", err) 317 } 318 dst, err := ioutil.ReadAll(NewReader(buf)) 319 if err != nil { 320 t.Fatalf("ReadAll: decoding: %v", err) 321 } 322 if err := cmp(dst, src); err != nil { 323 t.Fatal(err) 324 } 325 } 326 327 func TestWriterGoldenOutput(t *testing.T) { 328 buf := new(bytes.Buffer) 329 w := NewBufferedWriter(buf) 330 defer w.Close() 331 w.Write([]byte("abcd")) // Not compressible. 332 w.Flush() 333 w.Write(bytes.Repeat([]byte{'A'}, 100)) // Compressible. 334 w.Flush() 335 got := buf.String() 336 want := strings.Join([]string{ 337 magicChunk, 338 "\x01\x08\x00\x00", // Uncompressed chunk, 8 bytes long (including 4 byte checksum). 339 "\x68\x10\xe6\xb6", // Checksum. 340 "\x61\x62\x63\x64", // Uncompressed payload: "abcd". 341 "\x00\x0d\x00\x00", // Compressed chunk, 13 bytes long (including 4 byte checksum). 342 "\x37\xcb\xbc\x9d", // Checksum. 343 "\x64", // Compressed payload: Uncompressed length (varint encoded): 100. 344 "\x00\x41", // Compressed payload: tagLiteral, length=1, "A". 345 "\xfe\x01\x00", // Compressed payload: tagCopy2, length=64, offset=1. 346 "\x8a\x01\x00", // Compressed payload: tagCopy2, length=35, offset=1. 347 }, "") 348 if got != want { 349 t.Fatalf("\ngot: % x\nwant: % x", got, want) 350 } 351 } 352 353 func TestNewBufferedWriter(t *testing.T) { 354 // Test all 32 possible sub-sequences of these 5 input slices. 355 // 356 // Their lengths sum to 400,000, which is over 6 times the Writer ibuf 357 // capacity: 6 * maxUncompressedChunkLen is 393,216. 358 inputs := [][]byte{ 359 bytes.Repeat([]byte{'a'}, 40000), 360 bytes.Repeat([]byte{'b'}, 150000), 361 bytes.Repeat([]byte{'c'}, 60000), 362 bytes.Repeat([]byte{'d'}, 120000), 363 bytes.Repeat([]byte{'e'}, 30000), 364 } 365 loop: 366 for i := 0; i < 1<<uint(len(inputs)); i++ { 367 var want []byte 368 buf := new(bytes.Buffer) 369 w := NewBufferedWriter(buf) 370 for j, input := range inputs { 371 if i&(1<<uint(j)) == 0 { 372 continue 373 } 374 if _, err := w.Write(input); err != nil { 375 t.Errorf("i=%#02x: j=%d: Write: %v", i, j, err) 376 continue loop 377 } 378 want = append(want, input...) 379 } 380 if err := w.Close(); err != nil { 381 t.Errorf("i=%#02x: Close: %v", i, err) 382 continue 383 } 384 got, err := ioutil.ReadAll(NewReader(buf)) 385 if err != nil { 386 t.Errorf("i=%#02x: ReadAll: %v", i, err) 387 continue 388 } 389 if err := cmp(got, want); err != nil { 390 t.Errorf("i=%#02x: %v", i, err) 391 continue 392 } 393 } 394 } 395 396 func TestFlush(t *testing.T) { 397 buf := new(bytes.Buffer) 398 w := NewBufferedWriter(buf) 399 defer w.Close() 400 if _, err := w.Write(bytes.Repeat([]byte{'x'}, 20)); err != nil { 401 t.Fatalf("Write: %v", err) 402 } 403 if n := buf.Len(); n != 0 { 404 t.Fatalf("before Flush: %d bytes were written to the underlying io.Writer, want 0", n) 405 } 406 if err := w.Flush(); err != nil { 407 t.Fatalf("Flush: %v", err) 408 } 409 if n := buf.Len(); n == 0 { 410 t.Fatalf("after Flush: %d bytes were written to the underlying io.Writer, want non-0", n) 411 } 412 } 413 414 func TestReaderReset(t *testing.T) { 415 gold := bytes.Repeat([]byte("All that is gold does not glitter,\n"), 10000) 416 buf := new(bytes.Buffer) 417 if _, err := NewWriter(buf).Write(gold); err != nil { 418 t.Fatalf("Write: %v", err) 419 } 420 encoded, invalid, partial := buf.String(), "invalid", "partial" 421 r := NewReader(nil) 422 for i, s := range []string{encoded, invalid, partial, encoded, partial, invalid, encoded, encoded} { 423 if s == partial { 424 r.Reset(strings.NewReader(encoded)) 425 if _, err := r.Read(make([]byte, 101)); err != nil { 426 t.Errorf("#%d: %v", i, err) 427 continue 428 } 429 continue 430 } 431 r.Reset(strings.NewReader(s)) 432 got, err := ioutil.ReadAll(r) 433 switch s { 434 case encoded: 435 if err != nil { 436 t.Errorf("#%d: %v", i, err) 437 continue 438 } 439 if err := cmp(got, gold); err != nil { 440 t.Errorf("#%d: %v", i, err) 441 continue 442 } 443 case invalid: 444 if err == nil { 445 t.Errorf("#%d: got nil error, want non-nil", i) 446 continue 447 } 448 } 449 } 450 } 451 452 func TestWriterReset(t *testing.T) { 453 gold := bytes.Repeat([]byte("Not all those who wander are lost;\n"), 10000) 454 const n = 20 455 for _, buffered := range []bool{false, true} { 456 var w *Writer 457 if buffered { 458 w = NewBufferedWriter(nil) 459 defer w.Close() 460 } else { 461 w = NewWriter(nil) 462 } 463 464 var gots, wants [][]byte 465 failed := false 466 for i := 0; i <= n; i++ { 467 buf := new(bytes.Buffer) 468 w.Reset(buf) 469 want := gold[:len(gold)*i/n] 470 if _, err := w.Write(want); err != nil { 471 t.Errorf("#%d: Write: %v", i, err) 472 failed = true 473 continue 474 } 475 if buffered { 476 if err := w.Flush(); err != nil { 477 t.Errorf("#%d: Flush: %v", i, err) 478 failed = true 479 continue 480 } 481 } 482 got, err := ioutil.ReadAll(NewReader(buf)) 483 if err != nil { 484 t.Errorf("#%d: ReadAll: %v", i, err) 485 failed = true 486 continue 487 } 488 gots = append(gots, got) 489 wants = append(wants, want) 490 } 491 if failed { 492 continue 493 } 494 for i := range gots { 495 if err := cmp(gots[i], wants[i]); err != nil { 496 t.Errorf("#%d: %v", i, err) 497 } 498 } 499 } 500 } 501 502 func TestWriterResetWithoutFlush(t *testing.T) { 503 buf0 := new(bytes.Buffer) 504 buf1 := new(bytes.Buffer) 505 w := NewBufferedWriter(buf0) 506 if _, err := w.Write([]byte("xxx")); err != nil { 507 t.Fatalf("Write #0: %v", err) 508 } 509 // Note that we don't Flush the Writer before calling Reset. 510 w.Reset(buf1) 511 if _, err := w.Write([]byte("yyy")); err != nil { 512 t.Fatalf("Write #1: %v", err) 513 } 514 if err := w.Flush(); err != nil { 515 t.Fatalf("Flush: %v", err) 516 } 517 got, err := ioutil.ReadAll(NewReader(buf1)) 518 if err != nil { 519 t.Fatalf("ReadAll: %v", err) 520 } 521 if err := cmp(got, []byte("yyy")); err != nil { 522 t.Fatal(err) 523 } 524 } 525 526 type writeCounter int 527 528 func (c *writeCounter) Write(p []byte) (int, error) { 529 *c++ 530 return len(p), nil 531 } 532 533 // TestNumUnderlyingWrites tests that each Writer flush only makes one or two 534 // Write calls on its underlying io.Writer, depending on whether or not the 535 // flushed buffer was compressible. 536 func TestNumUnderlyingWrites(t *testing.T) { 537 testCases := []struct { 538 input []byte 539 want int 540 }{ 541 {bytes.Repeat([]byte{'x'}, 100), 1}, 542 {bytes.Repeat([]byte{'y'}, 100), 1}, 543 {[]byte("ABCDEFGHIJKLMNOPQRST"), 2}, 544 } 545 546 var c writeCounter 547 w := NewBufferedWriter(&c) 548 defer w.Close() 549 for i, tc := range testCases { 550 c = 0 551 if _, err := w.Write(tc.input); err != nil { 552 t.Errorf("#%d: Write: %v", i, err) 553 continue 554 } 555 if err := w.Flush(); err != nil { 556 t.Errorf("#%d: Flush: %v", i, err) 557 continue 558 } 559 if int(c) != tc.want { 560 t.Errorf("#%d: got %d underlying writes, want %d", i, c, tc.want) 561 continue 562 } 563 } 564 } 565 566 func benchDecode(b *testing.B, src []byte) { 567 encoded := Encode(nil, src) 568 // Bandwidth is in amount of uncompressed data. 569 b.SetBytes(int64(len(src))) 570 b.ResetTimer() 571 for i := 0; i < b.N; i++ { 572 Decode(src, encoded) 573 } 574 } 575 576 func benchEncode(b *testing.B, src []byte) { 577 // Bandwidth is in amount of uncompressed data. 578 b.SetBytes(int64(len(src))) 579 dst := make([]byte, MaxEncodedLen(len(src))) 580 b.ResetTimer() 581 for i := 0; i < b.N; i++ { 582 Encode(dst, src) 583 } 584 } 585 586 func readFile(b testing.TB, filename string) []byte { 587 src, err := ioutil.ReadFile(filename) 588 if err != nil { 589 b.Skipf("skipping benchmark: %v", err) 590 } 591 if len(src) == 0 { 592 b.Fatalf("%s has zero length", filename) 593 } 594 return src 595 } 596 597 // expand returns a slice of length n containing repeated copies of src. 598 func expand(src []byte, n int) []byte { 599 dst := make([]byte, n) 600 for x := dst; len(x) > 0; { 601 i := copy(x, src) 602 x = x[i:] 603 } 604 return dst 605 } 606 607 func benchWords(b *testing.B, n int, decode bool) { 608 // Note: the file is OS-language dependent so the resulting values are not 609 // directly comparable for non-US-English OS installations. 610 data := expand(readFile(b, "/usr/share/dict/words"), n) 611 if decode { 612 benchDecode(b, data) 613 } else { 614 benchEncode(b, data) 615 } 616 } 617 618 func BenchmarkWordsDecode1e1(b *testing.B) { benchWords(b, 1e1, true) } 619 func BenchmarkWordsDecode1e2(b *testing.B) { benchWords(b, 1e2, true) } 620 func BenchmarkWordsDecode1e3(b *testing.B) { benchWords(b, 1e3, true) } 621 func BenchmarkWordsDecode1e4(b *testing.B) { benchWords(b, 1e4, true) } 622 func BenchmarkWordsDecode1e5(b *testing.B) { benchWords(b, 1e5, true) } 623 func BenchmarkWordsDecode1e6(b *testing.B) { benchWords(b, 1e6, true) } 624 func BenchmarkWordsEncode1e1(b *testing.B) { benchWords(b, 1e1, false) } 625 func BenchmarkWordsEncode1e2(b *testing.B) { benchWords(b, 1e2, false) } 626 func BenchmarkWordsEncode1e3(b *testing.B) { benchWords(b, 1e3, false) } 627 func BenchmarkWordsEncode1e4(b *testing.B) { benchWords(b, 1e4, false) } 628 func BenchmarkWordsEncode1e5(b *testing.B) { benchWords(b, 1e5, false) } 629 func BenchmarkWordsEncode1e6(b *testing.B) { benchWords(b, 1e6, false) } 630 631 func BenchmarkRandomEncode(b *testing.B) { 632 rng := rand.New(rand.NewSource(1)) 633 data := make([]byte, 1<<20) 634 for i := range data { 635 data[i] = uint8(rng.Intn(256)) 636 } 637 benchEncode(b, data) 638 } 639 640 // testFiles' values are copied directly from 641 // https://raw.githubusercontent.com/google/snappy/master/snappy_unittest.cc 642 // The label field is unused in snappy-go. 643 // 644 // If this list changes (due to the upstream C++ list changing), remember to 645 // update the .gitignore file in this repository. 646 var testFiles = []struct { 647 label string 648 filename string 649 sizeLimit int 650 }{ 651 {"html", "html", 0}, 652 {"urls", "urls.10K", 0}, 653 {"jpg", "fireworks.jpeg", 0}, 654 {"jpg_200", "fireworks.jpeg", 200}, 655 {"pdf", "paper-100k.pdf", 0}, 656 {"html4", "html_x_4", 0}, 657 {"txt1", "alice29.txt", 0}, 658 {"txt2", "asyoulik.txt", 0}, 659 {"txt3", "lcet10.txt", 0}, 660 {"txt4", "plrabn12.txt", 0}, 661 {"pb", "geo.protodata", 0}, 662 {"gaviota", "kppkn.gtb", 0}, 663 } 664 665 // The test data files are present at this canonical URL. 666 const baseURL = "https://raw.githubusercontent.com/google/snappy/master/testdata/" 667 668 func downloadTestdata(b *testing.B, basename string) (errRet error) { 669 filename := filepath.Join(*testdata, basename) 670 if stat, err := os.Stat(filename); err == nil && stat.Size() != 0 { 671 return nil 672 } 673 674 if !*download { 675 b.Skipf("test data not found; skipping benchmark without the -download flag") 676 } 677 // Download the official snappy C++ implementation reference test data 678 // files for benchmarking. 679 if err := os.Mkdir(*testdata, 0777); err != nil && !os.IsExist(err) { 680 return fmt.Errorf("failed to create testdata: %s", err) 681 } 682 683 f, err := os.Create(filename) 684 if err != nil { 685 return fmt.Errorf("failed to create %s: %s", filename, err) 686 } 687 defer f.Close() 688 defer func() { 689 if errRet != nil { 690 os.Remove(filename) 691 } 692 }() 693 url := baseURL + basename 694 resp, err := http.Get(url) 695 if err != nil { 696 return fmt.Errorf("failed to download %s: %s", url, err) 697 } 698 defer resp.Body.Close() 699 if s := resp.StatusCode; s != http.StatusOK { 700 return fmt.Errorf("downloading %s: HTTP status code %d (%s)", url, s, http.StatusText(s)) 701 } 702 _, err = io.Copy(f, resp.Body) 703 if err != nil { 704 return fmt.Errorf("failed to download %s to %s: %s", url, filename, err) 705 } 706 return nil 707 } 708 709 func benchFile(b *testing.B, n int, decode bool) { 710 if err := downloadTestdata(b, testFiles[n].filename); err != nil { 711 b.Fatalf("failed to download testdata: %s", err) 712 } 713 data := readFile(b, filepath.Join(*testdata, testFiles[n].filename)) 714 if n := testFiles[n].sizeLimit; 0 < n && n < len(data) { 715 data = data[:n] 716 } 717 if decode { 718 benchDecode(b, data) 719 } else { 720 benchEncode(b, data) 721 } 722 } 723 724 // Naming convention is kept similar to what snappy's C++ implementation uses. 725 func Benchmark_UFlat0(b *testing.B) { benchFile(b, 0, true) } 726 func Benchmark_UFlat1(b *testing.B) { benchFile(b, 1, true) } 727 func Benchmark_UFlat2(b *testing.B) { benchFile(b, 2, true) } 728 func Benchmark_UFlat3(b *testing.B) { benchFile(b, 3, true) } 729 func Benchmark_UFlat4(b *testing.B) { benchFile(b, 4, true) } 730 func Benchmark_UFlat5(b *testing.B) { benchFile(b, 5, true) } 731 func Benchmark_UFlat6(b *testing.B) { benchFile(b, 6, true) } 732 func Benchmark_UFlat7(b *testing.B) { benchFile(b, 7, true) } 733 func Benchmark_UFlat8(b *testing.B) { benchFile(b, 8, true) } 734 func Benchmark_UFlat9(b *testing.B) { benchFile(b, 9, true) } 735 func Benchmark_UFlat10(b *testing.B) { benchFile(b, 10, true) } 736 func Benchmark_UFlat11(b *testing.B) { benchFile(b, 11, true) } 737 func Benchmark_ZFlat0(b *testing.B) { benchFile(b, 0, false) } 738 func Benchmark_ZFlat1(b *testing.B) { benchFile(b, 1, false) } 739 func Benchmark_ZFlat2(b *testing.B) { benchFile(b, 2, false) } 740 func Benchmark_ZFlat3(b *testing.B) { benchFile(b, 3, false) } 741 func Benchmark_ZFlat4(b *testing.B) { benchFile(b, 4, false) } 742 func Benchmark_ZFlat5(b *testing.B) { benchFile(b, 5, false) } 743 func Benchmark_ZFlat6(b *testing.B) { benchFile(b, 6, false) } 744 func Benchmark_ZFlat7(b *testing.B) { benchFile(b, 7, false) } 745 func Benchmark_ZFlat8(b *testing.B) { benchFile(b, 8, false) } 746 func Benchmark_ZFlat9(b *testing.B) { benchFile(b, 9, false) } 747 func Benchmark_ZFlat10(b *testing.B) { benchFile(b, 10, false) } 748 func Benchmark_ZFlat11(b *testing.B) { benchFile(b, 11, false) } 749 750 // Prints compression size and ratio. 751 func BenchmarkCompressionSize(b *testing.B) { 752 fmt.Println("\ndata\tinsize\toutsize\treference\treduction\tref-red\tr-delta") 753 for i, tf := range testFiles { 754 if err := downloadTestdata(b, tf.filename); err != nil { 755 b.Fatalf("failed to download testdata: %s", err) 756 } 757 src := readFile(b, filepath.Join(*testdata, tf.filename)) 758 dst := Encode(nil, src) 759 odst := old.Encode(nil, src) 760 761 rthis := 100 - float64(len(dst))/float64(len(src))*100 762 rold := 100 - float64(len(odst))/float64(len(src))*100 763 fmt.Printf("Flat%d:\t%s\t%d\t%d\t%d\t%.2f%%\t%.2f%%\t%.2f%%\n", i, tf.label, len(src), len(dst), len(odst), rthis, rthis, rthis-rold) 764 } 765 // BenchmarkCompressionSize isn't really a benchmark, in the sense of "I 766 // want to run some code b.N times and see how long it takes". Instead, it 767 // prints out compressed sizes for the set of testFiles. Like the ns/op or 768 // MB/s metrics that the Benchmark_Z* benchmarks above give, this 769 // compression metric is also useful to know when tweaking the encoding 770 // algorithm, so this function is also run as a 'benchmark'. 771 b.Skip("ok") 772 } 773 774 func benchFileStream(b *testing.B, n int, decode bool) { 775 if err := downloadTestdata(b, testFiles[n].filename); err != nil { 776 b.Fatalf("failed to download testdata: %s", err) 777 } 778 data := readFile(b, filepath.Join(*testdata, testFiles[n].filename)) 779 if decode { 780 benchDecodeStream(b, data) 781 } else { 782 benchEncodeStream(b, data) 783 } 784 } 785 786 func benchDecodeStream(b *testing.B, src []byte) { 787 in := bytes.NewBuffer(nil) 788 _, _ = NewWriter(in).Write(src) 789 encoded := in.Bytes() 790 r := NewReader(in) 791 792 // Bandwidth is in amount of uncompressed data. 793 b.SetBytes(int64(len(src))) 794 b.ResetTimer() 795 for i := 0; i < b.N; i++ { 796 r.Reset(bytes.NewBuffer(encoded)) 797 io.Copy(ioutil.Discard, r) 798 } 799 } 800 801 func benchEncodeStream(b *testing.B, src []byte) { 802 r := NewWriter(ioutil.Discard) 803 // Bandwidth is in amount of uncompressed data. 804 b.SetBytes(int64(len(src))) 805 b.ResetTimer() 806 for i := 0; i < b.N; i++ { 807 _, err := r.Write(src) 808 if err != nil { 809 b.Fatal(err) 810 } 811 } 812 } 813 814 /* 815 func Benchmark_Stream_UFlat0(b *testing.B) { benchFileStream(b, 0, true) } 816 func Benchmark_Stream_UFlat1(b *testing.B) { benchFileStream(b, 1, true) } 817 func Benchmark_Stream_UFlat2(b *testing.B) { benchFileStream(b, 2, true) } 818 func Benchmark_Stream_UFlat3(b *testing.B) { benchFileStream(b, 3, true) } 819 func Benchmark_Stream_UFlat4(b *testing.B) { benchFileStream(b, 4, true) } 820 func Benchmark_Stream_UFlat5(b *testing.B) { benchFileStream(b, 5, true) } 821 func Benchmark_Stream_UFlat6(b *testing.B) { benchFileStream(b, 6, true) } 822 func Benchmark_Stream_UFlat7(b *testing.B) { benchFileStream(b, 7, true) } 823 func Benchmark_Stream_UFlat8(b *testing.B) { benchFileStream(b, 8, true) } 824 func Benchmark_Stream_UFlat9(b *testing.B) { benchFileStream(b, 9, true) } 825 func Benchmark_Stream_UFlat10(b *testing.B) { benchFileStream(b, 10, true) } 826 func Benchmark_Stream_UFlat11(b *testing.B) { benchFileStream(b, 11, true) } 827 func Benchmark_Stream_ZFlat0(b *testing.B) { benchFileStream(b, 0, false) } 828 func Benchmark_Stream_ZFlat1(b *testing.B) { benchFileStream(b, 1, false) } 829 func Benchmark_Stream_ZFlat2(b *testing.B) { benchFileStream(b, 2, false) } 830 func Benchmark_Stream_ZFlat3(b *testing.B) { benchFileStream(b, 3, false) } 831 func Benchmark_Stream_ZFlat4(b *testing.B) { benchFileStream(b, 4, false) } 832 func Benchmark_Stream_ZFlat5(b *testing.B) { benchFileStream(b, 5, false) } 833 func Benchmark_Stream_ZFlat6(b *testing.B) { benchFileStream(b, 6, false) } 834 func Benchmark_Stream_ZFlat7(b *testing.B) { benchFileStream(b, 7, false) } 835 func Benchmark_Stream_ZFlat8(b *testing.B) { benchFileStream(b, 8, false) } 836 func Benchmark_Stream_ZFlat9(b *testing.B) { benchFileStream(b, 9, false) } 837 func Benchmark_Stream_ZFlat10(b *testing.B) { benchFileStream(b, 10, false) } 838 func Benchmark_Stream_ZFlat11(b *testing.B) { benchFileStream(b, 11, false) } 839 */