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