123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- package ioutils
- import (
- "crypto/sha1"
- "encoding/hex"
- "math/rand"
- "testing"
- "time"
- )
- func TestBytesPipeRead(t *testing.T) {
- buf := NewBytesPipe()
- buf.Write([]byte("12"))
- buf.Write([]byte("34"))
- buf.Write([]byte("56"))
- buf.Write([]byte("78"))
- buf.Write([]byte("90"))
- rd := make([]byte, 4)
- n, err := buf.Read(rd)
- if err != nil {
- t.Fatal(err)
- }
- if n != 4 {
- t.Fatalf("Wrong number of bytes read: %d, should be %d", n, 4)
- }
- if string(rd) != "1234" {
- t.Fatalf("Read %s, but must be %s", rd, "1234")
- }
- n, err = buf.Read(rd)
- if err != nil {
- t.Fatal(err)
- }
- if n != 4 {
- t.Fatalf("Wrong number of bytes read: %d, should be %d", n, 4)
- }
- if string(rd) != "5678" {
- t.Fatalf("Read %s, but must be %s", rd, "5679")
- }
- n, err = buf.Read(rd)
- if err != nil {
- t.Fatal(err)
- }
- if n != 2 {
- t.Fatalf("Wrong number of bytes read: %d, should be %d", n, 2)
- }
- if string(rd[:n]) != "90" {
- t.Fatalf("Read %s, but must be %s", rd, "90")
- }
- }
- func TestBytesPipeWrite(t *testing.T) {
- buf := NewBytesPipe()
- buf.Write([]byte("12"))
- buf.Write([]byte("34"))
- buf.Write([]byte("56"))
- buf.Write([]byte("78"))
- buf.Write([]byte("90"))
- if buf.buf[0].String() != "1234567890" {
- t.Fatalf("Buffer %q, must be %q", buf.buf[0].String(), "1234567890")
- }
- }
- // Write and read in different speeds/chunk sizes and check valid data is read.
- func TestBytesPipeWriteRandomChunks(t *testing.T) {
- cases := []struct{ iterations, writesPerLoop, readsPerLoop int }{
- {100, 10, 1},
- {1000, 10, 5},
- {1000, 100, 0},
- {1000, 5, 6},
- {10000, 50, 25},
- }
- testMessage := []byte("this is a random string for testing")
- // random slice sizes to read and write
- writeChunks := []int{25, 35, 15, 20}
- readChunks := []int{5, 45, 20, 25}
- for _, c := range cases {
- // first pass: write directly to hash
- hash := sha1.New()
- for i := 0; i < c.iterations*c.writesPerLoop; i++ {
- if _, err := hash.Write(testMessage[:writeChunks[i%len(writeChunks)]]); err != nil {
- t.Fatal(err)
- }
- }
- expected := hex.EncodeToString(hash.Sum(nil))
- // write/read through buffer
- buf := NewBytesPipe()
- hash.Reset()
- done := make(chan struct{})
- go func() {
- // random delay before read starts
- <-time.After(time.Duration(rand.Intn(10)) * time.Millisecond)
- for i := 0; ; i++ {
- p := make([]byte, readChunks[(c.iterations*c.readsPerLoop+i)%len(readChunks)])
- n, _ := buf.Read(p)
- if n == 0 {
- break
- }
- hash.Write(p[:n])
- }
- close(done)
- }()
- for i := 0; i < c.iterations; i++ {
- for w := 0; w < c.writesPerLoop; w++ {
- buf.Write(testMessage[:writeChunks[(i*c.writesPerLoop+w)%len(writeChunks)]])
- }
- }
- buf.Close()
- <-done
- actual := hex.EncodeToString(hash.Sum(nil))
- if expected != actual {
- t.Fatalf("BytesPipe returned invalid data. Expected checksum %v, got %v", expected, actual)
- }
- }
- }
- func BenchmarkBytesPipeWrite(b *testing.B) {
- testData := []byte("pretty short line, because why not?")
- for i := 0; i < b.N; i++ {
- readBuf := make([]byte, 1024)
- buf := NewBytesPipe()
- go func() {
- var err error
- for err == nil {
- _, err = buf.Read(readBuf)
- }
- }()
- for j := 0; j < 1000; j++ {
- buf.Write(testData)
- }
- buf.Close()
- }
- }
- func BenchmarkBytesPipeRead(b *testing.B) {
- rd := make([]byte, 512)
- for i := 0; i < b.N; i++ {
- b.StopTimer()
- buf := NewBytesPipe()
- for j := 0; j < 500; j++ {
- buf.Write(make([]byte, 1024))
- }
- b.StartTimer()
- for j := 0; j < 1000; j++ {
- if n, _ := buf.Read(rd); n != 512 {
- b.Fatalf("Wrong number of bytes: %d", n)
- }
- }
- }
- }
|