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