github.com/fawick/restic@v0.1.1-0.20171126184616-c02923fbfc79/internal/cache/file_test.go (about) 1 package cache 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "math/rand" 9 "testing" 10 "time" 11 12 "github.com/restic/restic/internal/restic" 13 "github.com/restic/restic/internal/test" 14 ) 15 16 func generateRandomFiles(t testing.TB, tpe restic.FileType, c *Cache) restic.IDSet { 17 ids := restic.NewIDSet() 18 for i := 0; i < rand.Intn(15)+10; i++ { 19 buf := test.Random(rand.Int(), 1<<19) 20 id := restic.Hash(buf) 21 h := restic.Handle{Type: tpe, Name: id.String()} 22 23 if c.Has(h) { 24 t.Errorf("index %v present before save", id) 25 } 26 27 err := c.Save(h, bytes.NewReader(buf)) 28 if err != nil { 29 t.Fatal(err) 30 } 31 ids.Insert(id) 32 } 33 return ids 34 } 35 36 // randomID returns a random ID from s. 37 func randomID(s restic.IDSet) restic.ID { 38 for id := range s { 39 return id 40 } 41 panic("set is empty") 42 } 43 44 func load(t testing.TB, c *Cache, h restic.Handle) []byte { 45 rd, err := c.Load(h, 0, 0) 46 if err != nil { 47 t.Fatal(err) 48 } 49 50 if rd == nil { 51 t.Fatalf("Load() returned nil reader") 52 } 53 54 buf, err := ioutil.ReadAll(rd) 55 if err != nil { 56 t.Fatal(err) 57 } 58 59 if err = rd.Close(); err != nil { 60 t.Fatal(err) 61 } 62 63 return buf 64 } 65 66 func listFiles(t testing.TB, c *Cache, tpe restic.FileType) restic.IDSet { 67 list, err := c.list(tpe) 68 if err != nil { 69 t.Errorf("listing failed: %v", err) 70 } 71 72 return list 73 } 74 75 func clearFiles(t testing.TB, c *Cache, tpe restic.FileType, valid restic.IDSet) { 76 if err := c.Clear(tpe, valid); err != nil { 77 t.Error(err) 78 } 79 } 80 81 func TestFiles(t *testing.T) { 82 seed := time.Now().Unix() 83 t.Logf("seed is %v", seed) 84 rand.Seed(seed) 85 86 c, cleanup := TestNewCache(t) 87 defer cleanup() 88 89 var tests = []restic.FileType{ 90 restic.SnapshotFile, 91 restic.DataFile, 92 restic.IndexFile, 93 } 94 95 for _, tpe := range tests { 96 t.Run(fmt.Sprintf("%v", tpe), func(t *testing.T) { 97 ids := generateRandomFiles(t, tpe, c) 98 id := randomID(ids) 99 100 h := restic.Handle{Type: tpe, Name: id.String()} 101 id2 := restic.Hash(load(t, c, h)) 102 103 if !id.Equal(id2) { 104 t.Errorf("wrong data returned, want %v, got %v", id.Str(), id2.Str()) 105 } 106 107 if !c.Has(h) { 108 t.Errorf("cache thinks index %v isn't present", id.Str()) 109 } 110 111 list := listFiles(t, c, tpe) 112 if !ids.Equals(list) { 113 t.Errorf("wrong list of index IDs returned, want:\n %v\ngot:\n %v", ids, list) 114 } 115 116 clearFiles(t, c, tpe, restic.NewIDSet(id)) 117 list2 := listFiles(t, c, tpe) 118 ids.Delete(id) 119 want := restic.NewIDSet(id) 120 if !list2.Equals(want) { 121 t.Errorf("ClearIndexes removed indexes, want:\n %v\ngot:\n %v", list2, want) 122 } 123 124 clearFiles(t, c, tpe, restic.NewIDSet()) 125 want = restic.NewIDSet() 126 list3 := listFiles(t, c, tpe) 127 if !list3.Equals(want) { 128 t.Errorf("ClearIndexes returned a wrong list, want:\n %v\ngot:\n %v", want, list3) 129 } 130 }) 131 } 132 } 133 134 func TestFileSaveWriter(t *testing.T) { 135 seed := time.Now().Unix() 136 t.Logf("seed is %v", seed) 137 rand.Seed(seed) 138 139 c, cleanup := TestNewCache(t) 140 defer cleanup() 141 142 // save about 5 MiB of data in the cache 143 data := test.Random(rand.Int(), 5234142) 144 id := restic.ID{} 145 copy(id[:], data) 146 h := restic.Handle{ 147 Type: restic.DataFile, 148 Name: id.String(), 149 } 150 151 wr, err := c.SaveWriter(h) 152 if err != nil { 153 t.Fatal(err) 154 } 155 156 n, err := io.Copy(wr, bytes.NewReader(data)) 157 if err != nil { 158 t.Fatal(err) 159 } 160 161 if n != int64(len(data)) { 162 t.Fatalf("wrong number of bytes written, want %v, got %v", len(data), n) 163 } 164 165 if err = wr.Close(); err != nil { 166 t.Fatal(err) 167 } 168 169 rd, err := c.Load(h, 0, 0) 170 if err != nil { 171 t.Fatal(err) 172 } 173 174 buf, err := ioutil.ReadAll(rd) 175 if err != nil { 176 t.Fatal(err) 177 } 178 179 if len(buf) != len(data) { 180 t.Fatalf("wrong number of bytes read, want %v, got %v", len(data), len(buf)) 181 } 182 183 if !bytes.Equal(buf, data) { 184 t.Fatalf("wrong data returned, want:\n %02x\ngot:\n %02x", data[:16], buf[:16]) 185 } 186 187 if err = rd.Close(); err != nil { 188 t.Fatal(err) 189 } 190 } 191 192 func TestFileLoad(t *testing.T) { 193 seed := time.Now().Unix() 194 t.Logf("seed is %v", seed) 195 rand.Seed(seed) 196 197 c, cleanup := TestNewCache(t) 198 defer cleanup() 199 200 // save about 5 MiB of data in the cache 201 data := test.Random(rand.Int(), 5234142) 202 id := restic.ID{} 203 copy(id[:], data) 204 h := restic.Handle{ 205 Type: restic.DataFile, 206 Name: id.String(), 207 } 208 if err := c.Save(h, bytes.NewReader(data)); err != nil { 209 t.Fatalf("Save() returned error: %v", err) 210 } 211 212 var tests = []struct { 213 offset int64 214 length int 215 }{ 216 {0, 0}, 217 {5, 0}, 218 {32*1024 + 5, 0}, 219 {0, 123}, 220 {0, 64*1024 + 234}, 221 {100, 5234142}, 222 } 223 224 for _, test := range tests { 225 t.Run(fmt.Sprintf("%v/%v", test.length, test.offset), func(t *testing.T) { 226 rd, err := c.Load(h, test.length, test.offset) 227 if err != nil { 228 t.Fatal(err) 229 } 230 231 buf, err := ioutil.ReadAll(rd) 232 if err != nil { 233 t.Fatal(err) 234 } 235 236 if err = rd.Close(); err != nil { 237 t.Fatal(err) 238 } 239 240 o := int(test.offset) 241 l := test.length 242 if test.length == 0 { 243 l = len(data) - o 244 } 245 246 if l > len(data)-o { 247 l = len(data) - o 248 } 249 250 if len(buf) != l { 251 t.Fatalf("wrong number of bytes returned: want %d, got %d", l, len(buf)) 252 } 253 254 if !bytes.Equal(buf, data[o:o+l]) { 255 t.Fatalf("wrong data returned, want:\n %02x\ngot:\n %02x", data[o:o+16], buf[:16]) 256 } 257 }) 258 } 259 }