github.com/mferrell/afero@v1.8.3-0.20220319163648-1d8d1d1d8040/composite_test.go (about) 1 package afero 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "os" 9 "testing" 10 "time" 11 ) 12 13 var tempDirs []string 14 15 func NewTempOsBaseFs(t *testing.T) Fs { 16 name, err := TempDir(NewOsFs(), "", "") 17 if err != nil { 18 t.Error("error creating tempDir", err) 19 } 20 21 tempDirs = append(tempDirs, name) 22 23 return NewBasePathFs(NewOsFs(), name) 24 } 25 26 func CleanupTempDirs(t *testing.T) { 27 osfs := NewOsFs() 28 type ev struct { 29 path string 30 e error 31 } 32 33 errs := []ev{} 34 35 for _, x := range tempDirs { 36 err := osfs.RemoveAll(x) 37 if err != nil { 38 errs = append(errs, ev{path: x, e: err}) 39 } 40 } 41 42 for _, e := range errs { 43 fmt.Println("error removing tempDir", e.path, e.e) 44 } 45 46 if len(errs) > 0 { 47 t.Error("error cleaning up tempDirs") 48 } 49 tempDirs = []string{} 50 } 51 52 func TestUnionCreateExisting(t *testing.T) { 53 base := &MemMapFs{} 54 roBase := &ReadOnlyFs{source: base} 55 ufs := NewCopyOnWriteFs(roBase, &MemMapFs{}) 56 57 base.MkdirAll("/home/test", 0777) 58 fh, _ := base.Create("/home/test/file.txt") 59 fh.WriteString("This is a test") 60 fh.Close() 61 62 fh, err := ufs.OpenFile("/home/test/file.txt", os.O_RDWR, 0666) 63 if err != nil { 64 t.Errorf("Failed to open file r/w: %s", err) 65 } 66 67 _, err = fh.Write([]byte("####")) 68 if err != nil { 69 t.Errorf("Failed to write file: %s", err) 70 } 71 fh.Seek(0, 0) 72 data, err := ioutil.ReadAll(fh) 73 if err != nil { 74 t.Errorf("Failed to read file: %s", err) 75 } 76 if string(data) != "#### is a test" { 77 t.Errorf("Got wrong data") 78 } 79 fh.Close() 80 81 fh, _ = base.Open("/home/test/file.txt") 82 data, err = ioutil.ReadAll(fh) 83 if string(data) != "This is a test" { 84 t.Errorf("Got wrong data in base file") 85 } 86 fh.Close() 87 88 fh, err = ufs.Create("/home/test/file.txt") 89 switch err { 90 case nil: 91 if fi, _ := fh.Stat(); fi.Size() != 0 { 92 t.Errorf("Create did not truncate file") 93 } 94 fh.Close() 95 default: 96 t.Errorf("Create failed on existing file") 97 } 98 99 } 100 101 func TestUnionMergeReaddir(t *testing.T) { 102 base := &MemMapFs{} 103 roBase := &ReadOnlyFs{source: base} 104 105 ufs := &CopyOnWriteFs{base: roBase, layer: &MemMapFs{}} 106 107 base.MkdirAll("/home/test", 0777) 108 fh, _ := base.Create("/home/test/file.txt") 109 fh.WriteString("This is a test") 110 fh.Close() 111 112 fh, _ = ufs.Create("/home/test/file2.txt") 113 fh.WriteString("This is a test") 114 fh.Close() 115 116 fh, _ = ufs.Open("/home/test") 117 files, err := fh.Readdirnames(-1) 118 if err != nil { 119 t.Errorf("Readdirnames failed") 120 } 121 if len(files) != 2 { 122 t.Errorf("Got wrong number of files: %v", files) 123 } 124 } 125 126 func TestExistingDirectoryCollisionReaddir(t *testing.T) { 127 base := &MemMapFs{} 128 roBase := &ReadOnlyFs{source: base} 129 overlay := &MemMapFs{} 130 131 ufs := &CopyOnWriteFs{base: roBase, layer: overlay} 132 133 base.MkdirAll("/home/test", 0777) 134 fh, _ := base.Create("/home/test/file.txt") 135 fh.WriteString("This is a test") 136 fh.Close() 137 138 overlay.MkdirAll("home/test", 0777) 139 fh, _ = overlay.Create("/home/test/file2.txt") 140 fh.WriteString("This is a test") 141 fh.Close() 142 143 fh, _ = ufs.Create("/home/test/file3.txt") 144 fh.WriteString("This is a test") 145 fh.Close() 146 147 fh, _ = ufs.Open("/home/test") 148 files, err := fh.Readdirnames(-1) 149 if err != nil { 150 t.Errorf("Readdirnames failed") 151 } 152 if len(files) != 3 { 153 t.Errorf("Got wrong number of files in union: %v", files) 154 } 155 156 fh, _ = overlay.Open("/home/test") 157 files, err = fh.Readdirnames(-1) 158 if err != nil { 159 t.Errorf("Readdirnames failed") 160 } 161 if len(files) != 2 { 162 t.Errorf("Got wrong number of files in overlay: %v", files) 163 } 164 } 165 166 func TestNestedDirBaseReaddir(t *testing.T) { 167 base := &MemMapFs{} 168 roBase := &ReadOnlyFs{source: base} 169 overlay := &MemMapFs{} 170 171 ufs := &CopyOnWriteFs{base: roBase, layer: overlay} 172 173 base.MkdirAll("/home/test/foo/bar", 0777) 174 fh, _ := base.Create("/home/test/file.txt") 175 fh.WriteString("This is a test") 176 fh.Close() 177 178 fh, _ = base.Create("/home/test/foo/file2.txt") 179 fh.WriteString("This is a test") 180 fh.Close() 181 fh, _ = base.Create("/home/test/foo/bar/file3.txt") 182 fh.WriteString("This is a test") 183 fh.Close() 184 185 overlay.MkdirAll("/", 0777) 186 187 // Opening something only in the base 188 fh, _ = ufs.Open("/home/test/foo") 189 list, err := fh.Readdir(-1) 190 if err != nil { 191 t.Errorf("Readdir failed %s", err) 192 } 193 if len(list) != 2 { 194 for _, x := range list { 195 fmt.Println(x.Name()) 196 } 197 t.Errorf("Got wrong number of files in union: %v", len(list)) 198 } 199 } 200 201 func TestNestedDirOverlayReaddir(t *testing.T) { 202 base := &MemMapFs{} 203 roBase := &ReadOnlyFs{source: base} 204 overlay := &MemMapFs{} 205 206 ufs := &CopyOnWriteFs{base: roBase, layer: overlay} 207 208 base.MkdirAll("/", 0777) 209 overlay.MkdirAll("/home/test/foo/bar", 0777) 210 fh, _ := overlay.Create("/home/test/file.txt") 211 fh.WriteString("This is a test") 212 fh.Close() 213 fh, _ = overlay.Create("/home/test/foo/file2.txt") 214 fh.WriteString("This is a test") 215 fh.Close() 216 fh, _ = overlay.Create("/home/test/foo/bar/file3.txt") 217 fh.WriteString("This is a test") 218 fh.Close() 219 220 // Opening nested dir only in the overlay 221 fh, _ = ufs.Open("/home/test/foo") 222 list, err := fh.Readdir(-1) 223 if err != nil { 224 t.Errorf("Readdir failed %s", err) 225 } 226 if len(list) != 2 { 227 for _, x := range list { 228 fmt.Println(x.Name()) 229 } 230 t.Errorf("Got wrong number of files in union: %v", len(list)) 231 } 232 } 233 234 func TestNestedDirOverlayOsFsReaddir(t *testing.T) { 235 defer CleanupTempDirs(t) 236 base := NewTempOsBaseFs(t) 237 roBase := &ReadOnlyFs{source: base} 238 overlay := NewTempOsBaseFs(t) 239 240 ufs := &CopyOnWriteFs{base: roBase, layer: overlay} 241 242 base.MkdirAll("/", 0777) 243 overlay.MkdirAll("/home/test/foo/bar", 0777) 244 fh, _ := overlay.Create("/home/test/file.txt") 245 fh.WriteString("This is a test") 246 fh.Close() 247 fh, _ = overlay.Create("/home/test/foo/file2.txt") 248 fh.WriteString("This is a test") 249 fh.Close() 250 fh, _ = overlay.Create("/home/test/foo/bar/file3.txt") 251 fh.WriteString("This is a test") 252 fh.Close() 253 254 // Opening nested dir only in the overlay 255 fh, _ = ufs.Open("/home/test/foo") 256 list, err := fh.Readdir(-1) 257 fh.Close() 258 if err != nil { 259 t.Errorf("Readdir failed %s", err) 260 } 261 if len(list) != 2 { 262 for _, x := range list { 263 fmt.Println(x.Name()) 264 } 265 t.Errorf("Got wrong number of files in union: %v", len(list)) 266 } 267 } 268 269 func TestCopyOnWriteFsWithOsFs(t *testing.T) { 270 defer CleanupTempDirs(t) 271 base := NewTempOsBaseFs(t) 272 roBase := &ReadOnlyFs{source: base} 273 overlay := NewTempOsBaseFs(t) 274 275 ufs := &CopyOnWriteFs{base: roBase, layer: overlay} 276 277 base.MkdirAll("/home/test", 0777) 278 fh, _ := base.Create("/home/test/file.txt") 279 fh.WriteString("This is a test") 280 fh.Close() 281 282 overlay.MkdirAll("home/test", 0777) 283 fh, _ = overlay.Create("/home/test/file2.txt") 284 fh.WriteString("This is a test") 285 fh.Close() 286 287 fh, _ = ufs.Create("/home/test/file3.txt") 288 fh.WriteString("This is a test") 289 fh.Close() 290 291 fh, _ = ufs.Open("/home/test") 292 files, err := fh.Readdirnames(-1) 293 fh.Close() 294 if err != nil { 295 t.Errorf("Readdirnames failed") 296 } 297 if len(files) != 3 { 298 t.Errorf("Got wrong number of files in union: %v", files) 299 } 300 301 fh, _ = overlay.Open("/home/test") 302 files, err = fh.Readdirnames(-1) 303 fh.Close() 304 if err != nil { 305 t.Errorf("Readdirnames failed") 306 } 307 if len(files) != 2 { 308 t.Errorf("Got wrong number of files in overlay: %v", files) 309 } 310 } 311 312 func TestUnionCacheWrite(t *testing.T) { 313 base := &MemMapFs{} 314 layer := &MemMapFs{} 315 316 ufs := NewCacheOnReadFs(base, layer, 0) 317 318 base.Mkdir("/data", 0777) 319 320 fh, err := ufs.Create("/data/file.txt") 321 if err != nil { 322 t.Errorf("Failed to create file") 323 } 324 _, err = fh.Write([]byte("This is a test")) 325 if err != nil { 326 t.Errorf("Failed to write file") 327 } 328 329 fh.Seek(0, os.SEEK_SET) 330 buf := make([]byte, 4) 331 _, err = fh.Read(buf) 332 fh.Write([]byte(" IS A")) 333 fh.Close() 334 335 baseData, _ := ReadFile(base, "/data/file.txt") 336 layerData, _ := ReadFile(layer, "/data/file.txt") 337 if string(baseData) != string(layerData) { 338 t.Errorf("Different data: %s <=> %s", baseData, layerData) 339 } 340 } 341 342 func TestUnionCacheExpire(t *testing.T) { 343 base := &MemMapFs{} 344 layer := &MemMapFs{} 345 ufs := &CacheOnReadFs{base: base, layer: layer, cacheTime: 1 * time.Second} 346 347 base.Mkdir("/data", 0777) 348 349 fh, err := ufs.Create("/data/file.txt") 350 if err != nil { 351 t.Errorf("Failed to create file") 352 } 353 _, err = fh.Write([]byte("This is a test")) 354 if err != nil { 355 t.Errorf("Failed to write file") 356 } 357 fh.Close() 358 359 fh, _ = base.Create("/data/file.txt") 360 // sleep some time, so we really get a different time.Now() on write... 361 time.Sleep(2 * time.Second) 362 fh.WriteString("Another test") 363 fh.Close() 364 365 data, _ := ReadFile(ufs, "/data/file.txt") 366 if string(data) != "Another test" { 367 t.Errorf("cache time failed: <%s>", data) 368 } 369 } 370 371 func TestCacheOnReadFsNotInLayer(t *testing.T) { 372 base := NewMemMapFs() 373 layer := NewMemMapFs() 374 fs := NewCacheOnReadFs(base, layer, 0) 375 376 fh, err := base.Create("/file.txt") 377 if err != nil { 378 t.Fatal("unable to create file: ", err) 379 } 380 381 txt := []byte("This is a test") 382 fh.Write(txt) 383 fh.Close() 384 385 fh, err = fs.Open("/file.txt") 386 if err != nil { 387 t.Fatal("could not open file: ", err) 388 } 389 390 b, err := ReadAll(fh) 391 fh.Close() 392 393 if err != nil { 394 t.Fatal("could not read file: ", err) 395 } else if !bytes.Equal(txt, b) { 396 t.Fatalf("wanted file text %q, got %q", txt, b) 397 } 398 399 fh, err = layer.Open("/file.txt") 400 if err != nil { 401 t.Fatal("could not open file from layer: ", err) 402 } 403 fh.Close() 404 } 405 406 // #194 407 func TestUnionFileReaddirEmpty(t *testing.T) { 408 osFs := NewOsFs() 409 410 base := NewMemMapFs() 411 overlay := NewMemMapFs() 412 ufs := &CopyOnWriteFs{base: base, layer: overlay} 413 mem := NewMemMapFs() 414 415 // The OS file will return io.EOF on end of directory. 416 for _, fs := range []Fs{osFs, ufs, mem} { 417 baseDir, err := TempDir(fs, "", "empty-dir") 418 if err != nil { 419 t.Fatal(err) 420 } 421 422 f, err := fs.Open(baseDir) 423 if err != nil { 424 t.Fatal(err) 425 } 426 427 names, err := f.Readdirnames(1) 428 if err != io.EOF { 429 t.Fatal(err) 430 } 431 432 if len(names) != 0 { 433 t.Fatal("should be empty") 434 } 435 436 f.Close() 437 438 fs.RemoveAll(baseDir) 439 } 440 } 441 442 // #197 443 func TestUnionFileReaddirDuplicateEmpty(t *testing.T) { 444 base := NewMemMapFs() 445 dir, err := TempDir(base, "", "empty-dir") 446 if err != nil { 447 t.Fatal(err) 448 } 449 450 // Overlay shares same empty directory as base 451 overlay := NewMemMapFs() 452 err = overlay.Mkdir(dir, 0700) 453 if err != nil { 454 t.Fatal(err) 455 } 456 457 ufs := &CopyOnWriteFs{base: base, layer: overlay} 458 459 f, err := ufs.Open(dir) 460 if err != nil { 461 t.Fatal(err) 462 } 463 defer f.Close() 464 465 names, err := f.Readdirnames(0) 466 467 if err == io.EOF { 468 t.Errorf("unexpected io.EOF error") 469 } 470 471 if len(names) != 0 { 472 t.Fatal("should be empty") 473 } 474 } 475 476 func TestUnionFileReaddirAskForTooMany(t *testing.T) { 477 base := &MemMapFs{} 478 overlay := &MemMapFs{} 479 480 const testFiles = 5 481 for i := 0; i < testFiles; i++ { 482 WriteFile(base, fmt.Sprintf("file%d.txt", i), []byte("afero"), 0777) 483 } 484 485 ufs := &CopyOnWriteFs{base: base, layer: overlay} 486 487 f, err := ufs.Open("") 488 if err != nil { 489 t.Fatal(err) 490 } 491 492 defer f.Close() 493 494 // Read part of all files 495 wantNames := 3 496 names, err := f.Readdirnames(wantNames) 497 if err != nil { 498 t.Fatal(err) 499 } 500 if len(names) != wantNames { 501 t.Fatalf("got %d names %v, want %d", len(names), names, wantNames) 502 } 503 504 // Try to read more files than remaining 505 wantNames = testFiles - len(names) 506 names, err = f.Readdirnames(wantNames + 1) 507 if err != nil { 508 t.Fatal(err) 509 } 510 if len(names) != wantNames { 511 t.Fatalf("got %d names %v, want %d", len(names), names, wantNames) 512 } 513 514 // End of directory 515 _, err = f.Readdirnames(3) 516 if err != io.EOF { 517 t.Fatal(err) 518 } 519 }