github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+incompatible/registry/storage/filewriter_test.go (about) 1 package storage 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "io" 7 "os" 8 "testing" 9 10 "github.com/docker/distribution/context" 11 "github.com/docker/distribution/digest" 12 storagedriver "github.com/docker/distribution/registry/storage/driver" 13 "github.com/docker/distribution/registry/storage/driver/inmemory" 14 ) 15 16 // TestSimpleWrite takes the fileWriter through common write operations 17 // ensuring data integrity. 18 func TestSimpleWrite(t *testing.T) { 19 content := make([]byte, 1<<20) 20 n, err := rand.Read(content) 21 if err != nil { 22 t.Fatalf("unexpected error building random data: %v", err) 23 } 24 25 if n != len(content) { 26 t.Fatalf("random read did't fill buffer") 27 } 28 29 dgst, err := digest.FromReader(bytes.NewReader(content)) 30 if err != nil { 31 t.Fatalf("unexpected error digesting random content: %v", err) 32 } 33 34 driver := inmemory.New() 35 path := "/random" 36 ctx := context.Background() 37 38 fw, err := newFileWriter(ctx, driver, path) 39 if err != nil { 40 t.Fatalf("unexpected error creating fileWriter: %v", err) 41 } 42 defer fw.Close() 43 44 n, err = fw.Write(content) 45 if err != nil { 46 t.Fatalf("unexpected error writing content: %v", err) 47 } 48 fw.Flush() 49 50 if n != len(content) { 51 t.Fatalf("unexpected write length: %d != %d", n, len(content)) 52 } 53 54 fr, err := newFileReader(ctx, driver, path, int64(len(content))) 55 if err != nil { 56 t.Fatalf("unexpected error creating fileReader: %v", err) 57 } 58 defer fr.Close() 59 60 verifier, err := digest.NewDigestVerifier(dgst) 61 if err != nil { 62 t.Fatalf("unexpected error getting digest verifier: %s", err) 63 } 64 65 io.Copy(verifier, fr) 66 67 if !verifier.Verified() { 68 t.Fatalf("unable to verify write data") 69 } 70 71 // Check the seek position is equal to the content length 72 end, err := fw.Seek(0, os.SEEK_END) 73 if err != nil { 74 t.Fatalf("unexpected error seeking: %v", err) 75 } 76 77 if end != int64(len(content)) { 78 t.Fatalf("write did not advance offset: %d != %d", end, len(content)) 79 } 80 81 // Double the content 82 doubled := append(content, content...) 83 doubledgst, err := digest.FromReader(bytes.NewReader(doubled)) 84 if err != nil { 85 t.Fatalf("unexpected error digesting doubled content: %v", err) 86 } 87 88 nn, err := fw.ReadFrom(bytes.NewReader(content)) 89 if err != nil { 90 t.Fatalf("unexpected error doubling content: %v", err) 91 } 92 93 if nn != int64(len(content)) { 94 t.Fatalf("writeat was short: %d != %d", n, len(content)) 95 } 96 97 fr, err = newFileReader(ctx, driver, path, int64(len(doubled))) 98 if err != nil { 99 t.Fatalf("unexpected error creating fileReader: %v", err) 100 } 101 defer fr.Close() 102 103 verifier, err = digest.NewDigestVerifier(doubledgst) 104 if err != nil { 105 t.Fatalf("unexpected error getting digest verifier: %s", err) 106 } 107 108 io.Copy(verifier, fr) 109 110 if !verifier.Verified() { 111 t.Fatalf("unable to verify write data") 112 } 113 114 // Check that Write updated the offset. 115 end, err = fw.Seek(0, os.SEEK_END) 116 if err != nil { 117 t.Fatalf("unexpected error seeking: %v", err) 118 } 119 120 if end != int64(len(doubled)) { 121 t.Fatalf("write did not advance offset: %d != %d", end, len(doubled)) 122 } 123 124 // Now, we copy from one path to another, running the data through the 125 // fileReader to fileWriter, rather than the driver.Move command to ensure 126 // everything is working correctly. 127 fr, err = newFileReader(ctx, driver, path, int64(len(doubled))) 128 if err != nil { 129 t.Fatalf("unexpected error creating fileReader: %v", err) 130 } 131 defer fr.Close() 132 133 fw, err = newFileWriter(ctx, driver, "/copied") 134 if err != nil { 135 t.Fatalf("unexpected error creating fileWriter: %v", err) 136 } 137 defer fw.Close() 138 139 nn, err = io.Copy(fw, fr) 140 if err != nil { 141 t.Fatalf("unexpected error copying data: %v", err) 142 } 143 144 if nn != int64(len(doubled)) { 145 t.Fatalf("unexpected copy length: %d != %d", nn, len(doubled)) 146 } 147 148 fr, err = newFileReader(ctx, driver, "/copied", int64(len(doubled))) 149 if err != nil { 150 t.Fatalf("unexpected error creating fileReader: %v", err) 151 } 152 defer fr.Close() 153 154 verifier, err = digest.NewDigestVerifier(doubledgst) 155 if err != nil { 156 t.Fatalf("unexpected error getting digest verifier: %s", err) 157 } 158 159 io.Copy(verifier, fr) 160 161 if !verifier.Verified() { 162 t.Fatalf("unable to verify write data") 163 } 164 } 165 166 func TestBufferedFileWriter(t *testing.T) { 167 ctx := context.Background() 168 writer, err := newFileWriter(ctx, inmemory.New(), "/random") 169 170 if err != nil { 171 t.Fatalf("Failed to initialize bufferedFileWriter: %v", err.Error()) 172 } 173 174 // write one byte and ensure the offset hasn't been incremented. 175 // offset will only get incremented when the buffer gets flushed 176 short := []byte{byte(1)} 177 178 writer.Write(short) 179 180 if writer.offset > 0 { 181 t.Fatalf("WriteStream called prematurely") 182 } 183 184 // write enough data to cause the buffer to flush and confirm 185 // the offset has been incremented 186 long := make([]byte, fileWriterBufferSize) 187 _, err = rand.Read(long) 188 if err != nil { 189 t.Fatalf("unexpected error building random data: %v", err) 190 } 191 for i := range long { 192 long[i] = byte(i) 193 } 194 writer.Write(long) 195 writer.Close() 196 if writer.offset != (fileWriterBufferSize + 1) { 197 t.Fatalf("WriteStream not called when buffer capacity reached") 198 } 199 } 200 201 func BenchmarkFileWriter(b *testing.B) { 202 b.StopTimer() // not sure how long setup above will take 203 for i := 0; i < b.N; i++ { 204 // Start basic fileWriter initialization 205 fw := fileWriter{ 206 driver: inmemory.New(), 207 path: "/random", 208 } 209 ctx := context.Background() 210 if fi, err := fw.driver.Stat(ctx, fw.path); err != nil { 211 switch err := err.(type) { 212 case storagedriver.PathNotFoundError: 213 // ignore, offset is zero 214 default: 215 b.Fatalf("Failed to initialize fileWriter: %v", err.Error()) 216 } 217 } else { 218 if fi.IsDir() { 219 b.Fatalf("Cannot write to a directory") 220 } 221 222 fw.size = fi.Size() 223 } 224 225 randomBytes := make([]byte, 1<<20) 226 _, err := rand.Read(randomBytes) 227 if err != nil { 228 b.Fatalf("unexpected error building random data: %v", err) 229 } 230 // End basic file writer initialization 231 232 b.StartTimer() 233 for j := 0; j < 100; j++ { 234 fw.Write(randomBytes) 235 } 236 b.StopTimer() 237 } 238 } 239 240 func BenchmarkBufferedFileWriter(b *testing.B) { 241 b.StopTimer() // not sure how long setup above will take 242 ctx := context.Background() 243 for i := 0; i < b.N; i++ { 244 bfw, err := newFileWriter(ctx, inmemory.New(), "/random") 245 246 if err != nil { 247 b.Fatalf("Failed to initialize bufferedFileWriter: %v", err.Error()) 248 } 249 250 randomBytes := make([]byte, 1<<20) 251 _, err = rand.Read(randomBytes) 252 if err != nil { 253 b.Fatalf("unexpected error building random data: %v", err) 254 } 255 256 b.StartTimer() 257 for j := 0; j < 100; j++ { 258 bfw.Write(randomBytes) 259 } 260 b.StopTimer() 261 } 262 }