...

Source file src/github.com/spf13/afero/composite_test.go

Documentation: github.com/spf13/afero

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

View as plain text