github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/pkg/ioutils/bytespipe_test.go (about)

     1  package ioutils
     2  
     3  import (
     4  	"crypto/sha1"
     5  	"encoding/hex"
     6  	"math/rand"
     7  	"testing"
     8  	"time"
     9  )
    10  
    11  func TestBytesPipeRead(t *testing.T) {
    12  	buf := NewBytesPipe()
    13  	buf.Write([]byte("12"))
    14  	buf.Write([]byte("34"))
    15  	buf.Write([]byte("56"))
    16  	buf.Write([]byte("78"))
    17  	buf.Write([]byte("90"))
    18  	rd := make([]byte, 4)
    19  	n, err := buf.Read(rd)
    20  	if err != nil {
    21  		t.Fatal(err)
    22  	}
    23  	if n != 4 {
    24  		t.Fatalf("Wrong number of bytes read: %d, should be %d", n, 4)
    25  	}
    26  	if string(rd) != "1234" {
    27  		t.Fatalf("Read %s, but must be %s", rd, "1234")
    28  	}
    29  	n, err = buf.Read(rd)
    30  	if err != nil {
    31  		t.Fatal(err)
    32  	}
    33  	if n != 4 {
    34  		t.Fatalf("Wrong number of bytes read: %d, should be %d", n, 4)
    35  	}
    36  	if string(rd) != "5678" {
    37  		t.Fatalf("Read %s, but must be %s", rd, "5679")
    38  	}
    39  	n, err = buf.Read(rd)
    40  	if err != nil {
    41  		t.Fatal(err)
    42  	}
    43  	if n != 2 {
    44  		t.Fatalf("Wrong number of bytes read: %d, should be %d", n, 2)
    45  	}
    46  	if string(rd[:n]) != "90" {
    47  		t.Fatalf("Read %s, but must be %s", rd, "90")
    48  	}
    49  }
    50  
    51  func TestBytesPipeWrite(t *testing.T) {
    52  	buf := NewBytesPipe()
    53  	buf.Write([]byte("12"))
    54  	buf.Write([]byte("34"))
    55  	buf.Write([]byte("56"))
    56  	buf.Write([]byte("78"))
    57  	buf.Write([]byte("90"))
    58  	if buf.buf[0].String() != "1234567890" {
    59  		t.Fatalf("Buffer %q, must be %q", buf.buf[0].String(), "1234567890")
    60  	}
    61  }
    62  
    63  // Write and read in different speeds/chunk sizes and check valid data is read.
    64  func TestBytesPipeWriteRandomChunks(t *testing.T) {
    65  	cases := []struct{ iterations, writesPerLoop, readsPerLoop int }{
    66  		{100, 10, 1},
    67  		{1000, 10, 5},
    68  		{1000, 100, 0},
    69  		{1000, 5, 6},
    70  		{10000, 50, 25},
    71  	}
    72  
    73  	testMessage := []byte("this is a random string for testing")
    74  	// random slice sizes to read and write
    75  	writeChunks := []int{25, 35, 15, 20}
    76  	readChunks := []int{5, 45, 20, 25}
    77  
    78  	for _, c := range cases {
    79  		// first pass: write directly to hash
    80  		hash := sha1.New()
    81  		for i := 0; i < c.iterations*c.writesPerLoop; i++ {
    82  			if _, err := hash.Write(testMessage[:writeChunks[i%len(writeChunks)]]); err != nil {
    83  				t.Fatal(err)
    84  			}
    85  		}
    86  		expected := hex.EncodeToString(hash.Sum(nil))
    87  
    88  		// write/read through buffer
    89  		buf := NewBytesPipe()
    90  		hash.Reset()
    91  
    92  		done := make(chan struct{})
    93  
    94  		go func() {
    95  			// random delay before read starts
    96  			<-time.After(time.Duration(rand.Intn(10)) * time.Millisecond)
    97  			for i := 0; ; i++ {
    98  				p := make([]byte, readChunks[(c.iterations*c.readsPerLoop+i)%len(readChunks)])
    99  				n, _ := buf.Read(p)
   100  				if n == 0 {
   101  					break
   102  				}
   103  				hash.Write(p[:n])
   104  			}
   105  
   106  			close(done)
   107  		}()
   108  
   109  		for i := 0; i < c.iterations; i++ {
   110  			for w := 0; w < c.writesPerLoop; w++ {
   111  				buf.Write(testMessage[:writeChunks[(i*c.writesPerLoop+w)%len(writeChunks)]])
   112  			}
   113  		}
   114  		buf.Close()
   115  		<-done
   116  
   117  		actual := hex.EncodeToString(hash.Sum(nil))
   118  
   119  		if expected != actual {
   120  			t.Fatalf("BytesPipe returned invalid data. Expected checksum %v, got %v", expected, actual)
   121  		}
   122  
   123  	}
   124  }
   125  
   126  func BenchmarkBytesPipeWrite(b *testing.B) {
   127  	testData := []byte("pretty short line, because why not?")
   128  	for i := 0; i < b.N; i++ {
   129  		readBuf := make([]byte, 1024)
   130  		buf := NewBytesPipe()
   131  		go func() {
   132  			var err error
   133  			for err == nil {
   134  				_, err = buf.Read(readBuf)
   135  			}
   136  		}()
   137  		for j := 0; j < 1000; j++ {
   138  			buf.Write(testData)
   139  		}
   140  		buf.Close()
   141  	}
   142  }
   143  
   144  func BenchmarkBytesPipeRead(b *testing.B) {
   145  	rd := make([]byte, 512)
   146  	for i := 0; i < b.N; i++ {
   147  		b.StopTimer()
   148  		buf := NewBytesPipe()
   149  		for j := 0; j < 500; j++ {
   150  			buf.Write(make([]byte, 1024))
   151  		}
   152  		b.StartTimer()
   153  		for j := 0; j < 1000; j++ {
   154  			if n, _ := buf.Read(rd); n != 512 {
   155  				b.Fatalf("Wrong number of bytes: %d", n)
   156  			}
   157  		}
   158  	}
   159  }