Tizen_4.0 base
[platform/upstream/docker-engine.git] / pkg / ioutils / bytespipe_test.go
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 }