github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+incompatible/registry/storage/filereader_test.go (about) 1 package storage 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "io" 7 mrand "math/rand" 8 "os" 9 "testing" 10 11 "github.com/docker/distribution/context" 12 "github.com/docker/distribution/digest" 13 "github.com/docker/distribution/registry/storage/driver/inmemory" 14 ) 15 16 func TestSimpleRead(t *testing.T) { 17 ctx := context.Background() 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 didn'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 if err := driver.PutContent(ctx, path, content); err != nil { 37 t.Fatalf("error putting patterned content: %v", err) 38 } 39 40 fr, err := newFileReader(ctx, driver, path, int64(len(content))) 41 if err != nil { 42 t.Fatalf("error allocating file reader: %v", err) 43 } 44 45 verifier, err := digest.NewDigestVerifier(dgst) 46 if err != nil { 47 t.Fatalf("error getting digest verifier: %s", err) 48 } 49 50 io.Copy(verifier, fr) 51 52 if !verifier.Verified() { 53 t.Fatalf("unable to verify read data") 54 } 55 } 56 57 func TestFileReaderSeek(t *testing.T) { 58 driver := inmemory.New() 59 pattern := "01234567890ab" // prime length block 60 repititions := 1024 61 path := "/patterned" 62 content := bytes.Repeat([]byte(pattern), repititions) 63 ctx := context.Background() 64 65 if err := driver.PutContent(ctx, path, content); err != nil { 66 t.Fatalf("error putting patterned content: %v", err) 67 } 68 69 fr, err := newFileReader(ctx, driver, path, int64(len(content))) 70 71 if err != nil { 72 t.Fatalf("unexpected error creating file reader: %v", err) 73 } 74 75 // Seek all over the place, in blocks of pattern size and make sure we get 76 // the right data. 77 for _, repitition := range mrand.Perm(repititions - 1) { 78 targetOffset := int64(len(pattern) * repitition) 79 // Seek to a multiple of pattern size and read pattern size bytes 80 offset, err := fr.Seek(targetOffset, os.SEEK_SET) 81 if err != nil { 82 t.Fatalf("unexpected error seeking: %v", err) 83 } 84 85 if offset != targetOffset { 86 t.Fatalf("did not seek to correct offset: %d != %d", offset, targetOffset) 87 } 88 89 p := make([]byte, len(pattern)) 90 91 n, err := fr.Read(p) 92 if err != nil { 93 t.Fatalf("error reading pattern: %v", err) 94 } 95 96 if n != len(pattern) { 97 t.Fatalf("incorrect read length: %d != %d", n, len(pattern)) 98 } 99 100 if string(p) != pattern { 101 t.Fatalf("incorrect read content: %q != %q", p, pattern) 102 } 103 104 // Check offset 105 current, err := fr.Seek(0, os.SEEK_CUR) 106 if err != nil { 107 t.Fatalf("error checking current offset: %v", err) 108 } 109 110 if current != targetOffset+int64(len(pattern)) { 111 t.Fatalf("unexpected offset after read: %v", err) 112 } 113 } 114 115 start, err := fr.Seek(0, os.SEEK_SET) 116 if err != nil { 117 t.Fatalf("error seeking to start: %v", err) 118 } 119 120 if start != 0 { 121 t.Fatalf("expected to seek to start: %v != 0", start) 122 } 123 124 end, err := fr.Seek(0, os.SEEK_END) 125 if err != nil { 126 t.Fatalf("error checking current offset: %v", err) 127 } 128 129 if end != int64(len(content)) { 130 t.Fatalf("expected to seek to end: %v != %v", end, len(content)) 131 } 132 133 // 4. Seek before start, ensure error. 134 135 // seek before start 136 before, err := fr.Seek(-1, os.SEEK_SET) 137 if err == nil { 138 t.Fatalf("error expected, returned offset=%v", before) 139 } 140 141 // 5. Seek after end, 142 after, err := fr.Seek(1, os.SEEK_END) 143 if err != nil { 144 t.Fatalf("unexpected error expected, returned offset=%v", after) 145 } 146 147 p := make([]byte, 16) 148 n, err := fr.Read(p) 149 150 if n != 0 { 151 t.Fatalf("bytes reads %d != %d", n, 0) 152 } 153 154 if err != io.EOF { 155 t.Fatalf("expected io.EOF, got %v", err) 156 } 157 } 158 159 // TestFileReaderNonExistentFile ensures the reader behaves as expected with a 160 // missing or zero-length remote file. While the file may not exist, the 161 // reader should not error out on creation and should return 0-bytes from the 162 // read method, with an io.EOF error. 163 func TestFileReaderNonExistentFile(t *testing.T) { 164 driver := inmemory.New() 165 fr, err := newFileReader(context.Background(), driver, "/doesnotexist", 10) 166 if err != nil { 167 t.Fatalf("unexpected error initializing reader: %v", err) 168 } 169 170 var buf [1024]byte 171 172 n, err := fr.Read(buf[:]) 173 if n != 0 { 174 t.Fatalf("non-zero byte read reported: %d != 0", n) 175 } 176 177 if err != io.EOF { 178 t.Fatalf("read on missing file should return io.EOF, got %v", err) 179 } 180 } 181 182 // TestLayerReadErrors covers the various error return type for different 183 // conditions that can arise when reading a layer. 184 func TestFileReaderErrors(t *testing.T) { 185 // TODO(stevvooe): We need to cover error return types, driven by the 186 // errors returned via the HTTP API. For now, here is a incomplete list: 187 // 188 // 1. Layer Not Found: returned when layer is not found or access is 189 // denied. 190 // 2. Layer Unavailable: returned when link references are unresolved, 191 // but layer is known to the registry. 192 // 3. Layer Invalid: This may more split into more errors, but should be 193 // returned when name or tarsum does not reference a valid error. We 194 // may also need something to communication layer verification errors 195 // for the inline tarsum check. 196 // 4. Timeout: timeouts to backend. Need to better understand these 197 // failure cases and how the storage driver propagates these errors 198 // up the stack. 199 }