github.com/gojuno/afero@v1.1.1/memmap_test.go (about)

     1  package afero
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"path/filepath"
     8  	"runtime"
     9  	"testing"
    10  	"time"
    11  )
    12  
    13  func TestNormalizePath(t *testing.T) {
    14  	type test struct {
    15  		input    string
    16  		expected string
    17  	}
    18  
    19  	data := []test{
    20  		{".", FilePathSeparator},
    21  		{"./", FilePathSeparator},
    22  		{"..", FilePathSeparator},
    23  		{"../", FilePathSeparator},
    24  		{"./..", FilePathSeparator},
    25  		{"./../", FilePathSeparator},
    26  	}
    27  
    28  	for i, d := range data {
    29  		cpath := normalizePath(d.input)
    30  		if d.expected != cpath {
    31  			t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, cpath)
    32  		}
    33  	}
    34  }
    35  
    36  func TestPathErrors(t *testing.T) {
    37  	path := filepath.Join(".", "some", "path")
    38  	path2 := filepath.Join(".", "different", "path")
    39  	fs := NewMemMapFs()
    40  	perm := os.FileMode(0755)
    41  
    42  	// relevant functions:
    43  	// func (m *MemMapFs) Chmod(name string, mode os.FileMode) error
    44  	// func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error
    45  	// func (m *MemMapFs) Create(name string) (File, error)
    46  	// func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error
    47  	// func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error
    48  	// func (m *MemMapFs) Open(name string) (File, error)
    49  	// func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error)
    50  	// func (m *MemMapFs) Remove(name string) error
    51  	// func (m *MemMapFs) Rename(oldname, newname string) error
    52  	// func (m *MemMapFs) Stat(name string) (os.FileInfo, error)
    53  
    54  	err := fs.Chmod(path, perm)
    55  	checkPathError(t, err, "Chmod")
    56  
    57  	err = fs.Chtimes(path, time.Now(), time.Now())
    58  	checkPathError(t, err, "Chtimes")
    59  
    60  	// fs.Create doesn't return an error
    61  
    62  	err = fs.Mkdir(path2, perm)
    63  	if err != nil {
    64  		t.Error(err)
    65  	}
    66  	err = fs.Mkdir(path2, perm)
    67  	checkPathError(t, err, "Mkdir")
    68  
    69  	err = fs.MkdirAll(path2, perm)
    70  	if err != nil {
    71  		t.Error("MkdirAll:", err)
    72  	}
    73  
    74  	_, err = fs.Open(path)
    75  	checkPathError(t, err, "Open")
    76  
    77  	_, err = fs.OpenFile(path, os.O_RDWR, perm)
    78  	checkPathError(t, err, "OpenFile")
    79  
    80  	err = fs.Remove(path)
    81  	checkPathError(t, err, "Remove")
    82  
    83  	err = fs.RemoveAll(path)
    84  	if err != nil {
    85  		t.Error("RemoveAll:", err)
    86  	}
    87  
    88  	err = fs.Rename(path, path2)
    89  	checkPathError(t, err, "Rename")
    90  
    91  	_, err = fs.Stat(path)
    92  	checkPathError(t, err, "Stat")
    93  }
    94  
    95  func checkPathError(t *testing.T, err error, op string) {
    96  	pathErr, ok := err.(*os.PathError)
    97  	if !ok {
    98  		t.Error(op+":", err, "is not a os.PathError")
    99  		return
   100  	}
   101  	_, ok = pathErr.Err.(*os.PathError)
   102  	if ok {
   103  		t.Error(op+":", err, "contains another os.PathError")
   104  	}
   105  }
   106  
   107  // Ensure Permissions are set on OpenFile/Mkdir/MkdirAll
   108  func TestPermSet(t *testing.T) {
   109  	const fileName = "/myFileTest"
   110  	const dirPath = "/myDirTest"
   111  	const dirPathAll = "/my/path/to/dir"
   112  
   113  	const fileMode = os.FileMode(0765)
   114  	// directories will also have the directory bit set
   115  	const dirMode = fileMode | os.ModeDir
   116  
   117  	fs := NewMemMapFs()
   118  
   119  	// Test Openfile
   120  	f, err := fs.OpenFile(fileName, os.O_CREATE, fileMode)
   121  	if err != nil {
   122  		t.Errorf("OpenFile Create failed: %s", err)
   123  		return
   124  	}
   125  	f.Close()
   126  
   127  	s, err := fs.Stat(fileName)
   128  	if err != nil {
   129  		t.Errorf("Stat failed: %s", err)
   130  		return
   131  	}
   132  	if s.Mode().String() != fileMode.String() {
   133  		t.Errorf("Permissions Incorrect: %s != %s", s.Mode().String(), fileMode.String())
   134  		return
   135  	}
   136  
   137  	// Test Mkdir
   138  	err = fs.Mkdir(dirPath, dirMode)
   139  	if err != nil {
   140  		t.Errorf("MkDir Create failed: %s", err)
   141  		return
   142  	}
   143  	s, err = fs.Stat(dirPath)
   144  	if err != nil {
   145  		t.Errorf("Stat failed: %s", err)
   146  		return
   147  	}
   148  	// sets File
   149  	if s.Mode().String() != dirMode.String() {
   150  		t.Errorf("Permissions Incorrect: %s != %s", s.Mode().String(), dirMode.String())
   151  		return
   152  	}
   153  
   154  	// Test MkdirAll
   155  	err = fs.MkdirAll(dirPathAll, dirMode)
   156  	if err != nil {
   157  		t.Errorf("MkDir Create failed: %s", err)
   158  		return
   159  	}
   160  	s, err = fs.Stat(dirPathAll)
   161  	if err != nil {
   162  		t.Errorf("Stat failed: %s", err)
   163  		return
   164  	}
   165  	if s.Mode().String() != dirMode.String() {
   166  		t.Errorf("Permissions Incorrect: %s != %s", s.Mode().String(), dirMode.String())
   167  		return
   168  	}
   169  }
   170  
   171  // Fails if multiple file objects use the same file.at counter in MemMapFs
   172  func TestMultipleOpenFiles(t *testing.T) {
   173  	defer removeAllTestFiles(t)
   174  	const fileName = "afero-demo2.txt"
   175  
   176  	var data = make([][]byte, len(Fss))
   177  
   178  	for i, fs := range Fss {
   179  		dir := testDir(fs)
   180  		path := filepath.Join(dir, fileName)
   181  		fh1, err := fs.Create(path)
   182  		if err != nil {
   183  			t.Error("fs.Create failed: " + err.Error())
   184  		}
   185  		_, err = fh1.Write([]byte("test"))
   186  		if err != nil {
   187  			t.Error("fh.Write failed: " + err.Error())
   188  		}
   189  		_, err = fh1.Seek(0, os.SEEK_SET)
   190  		if err != nil {
   191  			t.Error(err)
   192  		}
   193  
   194  		fh2, err := fs.OpenFile(path, os.O_RDWR, 0777)
   195  		if err != nil {
   196  			t.Error("fs.OpenFile failed: " + err.Error())
   197  		}
   198  		_, err = fh2.Seek(0, os.SEEK_END)
   199  		if err != nil {
   200  			t.Error(err)
   201  		}
   202  		_, err = fh2.Write([]byte("data"))
   203  		if err != nil {
   204  			t.Error(err)
   205  		}
   206  		err = fh2.Close()
   207  		if err != nil {
   208  			t.Error(err)
   209  		}
   210  
   211  		_, err = fh1.Write([]byte("data"))
   212  		if err != nil {
   213  			t.Error(err)
   214  		}
   215  		err = fh1.Close()
   216  		if err != nil {
   217  			t.Error(err)
   218  		}
   219  		// the file now should contain "datadata"
   220  		data[i], err = ReadFile(fs, path)
   221  		if err != nil {
   222  			t.Error(err)
   223  		}
   224  	}
   225  
   226  	for i, fs := range Fss {
   227  		if i == 0 {
   228  			continue
   229  		}
   230  		if string(data[0]) != string(data[i]) {
   231  			t.Errorf("%s and %s don't behave the same\n"+
   232  				"%s: \"%s\"\n%s: \"%s\"\n",
   233  				Fss[0].Name(), fs.Name(), Fss[0].Name(), data[0], fs.Name(), data[i])
   234  		}
   235  	}
   236  }
   237  
   238  // Test if file.Write() fails when opened as read only
   239  func TestReadOnly(t *testing.T) {
   240  	defer removeAllTestFiles(t)
   241  	const fileName = "afero-demo.txt"
   242  
   243  	for _, fs := range Fss {
   244  		dir := testDir(fs)
   245  		path := filepath.Join(dir, fileName)
   246  
   247  		f, err := fs.Create(path)
   248  		if err != nil {
   249  			t.Error(fs.Name()+":", "fs.Create failed: "+err.Error())
   250  		}
   251  		_, err = f.Write([]byte("test"))
   252  		if err != nil {
   253  			t.Error(fs.Name()+":", "Write failed: "+err.Error())
   254  		}
   255  		f.Close()
   256  
   257  		f, err = fs.Open(path)
   258  		if err != nil {
   259  			t.Error("fs.Open failed: " + err.Error())
   260  		}
   261  		_, err = f.Write([]byte("data"))
   262  		if err == nil {
   263  			t.Error(fs.Name()+":", "No write error")
   264  		}
   265  		f.Close()
   266  
   267  		f, err = fs.OpenFile(path, os.O_RDONLY, 0644)
   268  		if err != nil {
   269  			t.Error("fs.Open failed: " + err.Error())
   270  		}
   271  		_, err = f.Write([]byte("data"))
   272  		if err == nil {
   273  			t.Error(fs.Name()+":", "No write error")
   274  		}
   275  		f.Close()
   276  	}
   277  }
   278  
   279  func TestWriteCloseTime(t *testing.T) {
   280  	defer removeAllTestFiles(t)
   281  	const fileName = "afero-demo.txt"
   282  
   283  	for _, fs := range Fss {
   284  		dir := testDir(fs)
   285  		path := filepath.Join(dir, fileName)
   286  
   287  		f, err := fs.Create(path)
   288  		if err != nil {
   289  			t.Error(fs.Name()+":", "fs.Create failed: "+err.Error())
   290  		}
   291  		f.Close()
   292  
   293  		f, err = fs.Create(path)
   294  		if err != nil {
   295  			t.Error(fs.Name()+":", "fs.Create failed: "+err.Error())
   296  		}
   297  		fi, err := f.Stat()
   298  		if err != nil {
   299  			t.Error(fs.Name()+":", "Stat failed: "+err.Error())
   300  		}
   301  		timeBefore := fi.ModTime()
   302  
   303  		// sorry for the delay, but we have to make sure time advances,
   304  		// also on non Un*x systems...
   305  		switch runtime.GOOS {
   306  		case "windows":
   307  			time.Sleep(2 * time.Second)
   308  		case "darwin":
   309  			time.Sleep(1 * time.Second)
   310  		default: // depending on the FS, this may work with < 1 second, on my old ext3 it does not
   311  			time.Sleep(1 * time.Second)
   312  		}
   313  
   314  		_, err = f.Write([]byte("test"))
   315  		if err != nil {
   316  			t.Error(fs.Name()+":", "Write failed: "+err.Error())
   317  		}
   318  		f.Close()
   319  		fi, err = fs.Stat(path)
   320  		if err != nil {
   321  			t.Error(fs.Name()+":", "fs.Stat failed: "+err.Error())
   322  		}
   323  		if fi.ModTime().Equal(timeBefore) {
   324  			t.Error(fs.Name()+":", "ModTime was not set on Close()")
   325  		}
   326  	}
   327  }
   328  
   329  // This test should be run with the race detector on:
   330  // go test -race -v -timeout 10s -run TestRacingDeleteAndClose
   331  func TestRacingDeleteAndClose(t *testing.T) {
   332  	fs := NewMemMapFs()
   333  	pathname := "testfile"
   334  	f, err := fs.Create(pathname)
   335  	if err != nil {
   336  		t.Fatal(err)
   337  	}
   338  
   339  	in := make(chan bool)
   340  
   341  	go func() {
   342  		<-in
   343  		f.Close()
   344  	}()
   345  	go func() {
   346  		<-in
   347  		fs.Remove(pathname)
   348  	}()
   349  	close(in)
   350  }
   351  
   352  // This test should be run with the race detector on:
   353  // go test -run TestMemFsDataRace -race
   354  func TestMemFsDataRace(t *testing.T) {
   355  	const dir = "test_dir"
   356  	fs := NewMemMapFs()
   357  
   358  	if err := fs.MkdirAll(dir, 0777); err != nil {
   359  		t.Fatal(err)
   360  	}
   361  
   362  	const n = 1000
   363  	done := make(chan struct{})
   364  
   365  	go func() {
   366  		defer close(done)
   367  		for i := 0; i < n; i++ {
   368  			fname := filepath.Join(dir, fmt.Sprintf("%d.txt", i))
   369  			if err := WriteFile(fs, fname, []byte(""), 0777); err != nil {
   370  				panic(err)
   371  			}
   372  			if err := fs.Remove(fname); err != nil {
   373  				panic(err)
   374  			}
   375  		}
   376  	}()
   377  
   378  loop:
   379  	for {
   380  		select {
   381  		case <-done:
   382  			break loop
   383  		default:
   384  			_, err := ReadDir(fs, dir)
   385  			if err != nil {
   386  				t.Fatal(err)
   387  			}
   388  		}
   389  	}
   390  }
   391  
   392  func TestMemFsDirMode(t *testing.T) {
   393  	fs := NewMemMapFs()
   394  	err := fs.Mkdir("/testDir1", 0644)
   395  	if err != nil {
   396  		t.Error(err)
   397  	}
   398  	err = fs.MkdirAll("/sub/testDir2", 0644)
   399  	if err != nil {
   400  		t.Error(err)
   401  	}
   402  	info, err := fs.Stat("/testDir1")
   403  	if err != nil {
   404  		t.Error(err)
   405  	}
   406  	if !info.IsDir() {
   407  		t.Error("should be a directory")
   408  	}
   409  	if !info.Mode().IsDir() {
   410  		t.Error("FileMode is not directory")
   411  	}
   412  	info, err = fs.Stat("/sub/testDir2")
   413  	if err != nil {
   414  		t.Error(err)
   415  	}
   416  	if !info.IsDir() {
   417  		t.Error("should be a directory")
   418  	}
   419  	if !info.Mode().IsDir() {
   420  		t.Error("FileMode is not directory")
   421  	}
   422  }
   423  
   424  func TestMemFsUnexpectedEOF(t *testing.T) {
   425  	t.Parallel()
   426  
   427  	fs := NewMemMapFs()
   428  
   429  	if err := WriteFile(fs, "file.txt", []byte("abc"), 0777); err != nil {
   430  		t.Fatal(err)
   431  	}
   432  
   433  	f, err := fs.Open("file.txt")
   434  	if err != nil {
   435  		t.Fatal(err)
   436  	}
   437  	defer f.Close()
   438  
   439  	// Seek beyond the end.
   440  	_, err = f.Seek(512, 0)
   441  	if err != nil {
   442  		t.Fatal(err)
   443  	}
   444  
   445  	buff := make([]byte, 256)
   446  	_, err = io.ReadAtLeast(f, buff, 256)
   447  
   448  	if err != io.ErrUnexpectedEOF {
   449  		t.Fatal("Expected ErrUnexpectedEOF")
   450  	}
   451  }