github.com/27149chen/afero@v1.6.2/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  	uid := 1000
    42  	gid := 1000
    43  
    44  	// relevant functions:
    45  	// func (m *MemMapFs) Chmod(name string, mode os.FileMode) error
    46  	// func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error
    47  	// func (m *MemMapFs) Create(name string) (File, error)
    48  	// func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error
    49  	// func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error
    50  	// func (m *MemMapFs) Open(name string) (File, error)
    51  	// func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error)
    52  	// func (m *MemMapFs) Remove(name string) error
    53  	// func (m *MemMapFs) Rename(oldname, newname string) error
    54  	// func (m *MemMapFs) Stat(name string) (os.FileInfo, error)
    55  
    56  	err := fs.Chmod(path, perm)
    57  	checkPathError(t, err, "Chmod")
    58  
    59  	err = fs.Chown(path, uid, gid)
    60  	checkPathError(t, err, "Chown")
    61  
    62  	err = fs.Chtimes(path, time.Now(), time.Now())
    63  	checkPathError(t, err, "Chtimes")
    64  
    65  	// fs.Create doesn't return an error
    66  
    67  	err = fs.Mkdir(path2, perm)
    68  	if err != nil {
    69  		t.Error(err)
    70  	}
    71  	err = fs.Mkdir(path2, perm)
    72  	checkPathError(t, err, "Mkdir")
    73  
    74  	err = fs.MkdirAll(path2, perm)
    75  	if err != nil {
    76  		t.Error("MkdirAll:", err)
    77  	}
    78  
    79  	_, err = fs.Open(path)
    80  	checkPathError(t, err, "Open")
    81  
    82  	_, err = fs.OpenFile(path, os.O_RDWR, perm)
    83  	checkPathError(t, err, "OpenFile")
    84  
    85  	err = fs.Remove(path)
    86  	checkPathError(t, err, "Remove")
    87  
    88  	err = fs.RemoveAll(path)
    89  	if err != nil {
    90  		t.Error("RemoveAll:", err)
    91  	}
    92  
    93  	err = fs.Rename(path, path2)
    94  	checkPathError(t, err, "Rename")
    95  
    96  	_, err = fs.Stat(path)
    97  	checkPathError(t, err, "Stat")
    98  }
    99  
   100  func checkPathError(t *testing.T, err error, op string) {
   101  	pathErr, ok := err.(*os.PathError)
   102  	if !ok {
   103  		t.Error(op+":", err, "is not a os.PathError")
   104  		return
   105  	}
   106  	_, ok = pathErr.Err.(*os.PathError)
   107  	if ok {
   108  		t.Error(op+":", err, "contains another os.PathError")
   109  	}
   110  }
   111  
   112  func TestMemFsRename(t *testing.T) {
   113  	memFs := &MemMapFs{}
   114  
   115  	const (
   116  		oldPath        = "/old"
   117  		newPath        = "/new"
   118  		fileName       = "afero.txt"
   119  		subDirName     = "subdir"
   120  		subDirFileName = "subafero.txt"
   121  	)
   122  	err := memFs.Mkdir(oldPath, 0700)
   123  	if err != nil {
   124  		t.Fatal(err)
   125  	}
   126  	oldFilePath := filepath.Join(oldPath, fileName)
   127  	_, err = memFs.Create(oldFilePath)
   128  	if err != nil {
   129  		t.Fatal(err)
   130  	}
   131  	oldSubDirPath := filepath.Join(oldPath, subDirName)
   132  	err = memFs.Mkdir(oldSubDirPath, 0700)
   133  	if err != nil {
   134  		t.Fatal(err)
   135  	}
   136  	oldSubDirFilePath := filepath.Join(oldPath, subDirName, subDirFileName)
   137  	_, err = memFs.Create(oldSubDirFilePath)
   138  	if err != nil {
   139  		t.Fatal(err)
   140  	}
   141  
   142  	err = memFs.Rename(oldPath, newPath)
   143  	if err != nil {
   144  		t.Fatal(err)
   145  	}
   146  	fmt.Println("MemFs contents:")
   147  	memFs.List()
   148  	fmt.Println()
   149  
   150  	newFilePath := filepath.Join(newPath, fileName)
   151  	newSubDirFilePath := filepath.Join(newPath, subDirName, subDirFileName)
   152  	_, err = memFs.Stat(newFilePath)
   153  	if err != nil {
   154  		t.Errorf("File should exist in new directory %q but received error: %s", newFilePath, err)
   155  	}
   156  	_, err = memFs.Stat(newSubDirFilePath)
   157  	if err != nil {
   158  		t.Errorf("File should exist in new sub directory %q but received error: %s", newSubDirFilePath, err)
   159  	}
   160  
   161  	_, err = memFs.Stat(oldFilePath)
   162  	if err == nil {
   163  		t.Errorf("File should not exist in old directory %q", oldFilePath)
   164  	}
   165  	_, err = memFs.Stat(oldSubDirFilePath)
   166  	if err == nil {
   167  		t.Errorf("File should not exist in old sub directory %q", oldSubDirFilePath)
   168  	}
   169  }
   170  
   171  // Ensure os.O_EXCL is correctly handled.
   172  func TestOpenFileExcl(t *testing.T) {
   173  	const fileName = "/myFileTest"
   174  	const fileMode = os.FileMode(0765)
   175  
   176  	fs := NewMemMapFs()
   177  
   178  	// First creation should succeed.
   179  	f, err := fs.OpenFile(fileName, os.O_CREATE|os.O_EXCL, fileMode)
   180  	if err != nil {
   181  		t.Errorf("OpenFile Create Excl failed: %s", err)
   182  		return
   183  	}
   184  	f.Close()
   185  
   186  	// Second creation should fail.
   187  	_, err = fs.OpenFile(fileName, os.O_CREATE|os.O_EXCL, fileMode)
   188  	if err == nil {
   189  		t.Errorf("OpenFile Create Excl should have failed, but it didn't")
   190  	}
   191  	checkPathError(t, err, "Open")
   192  }
   193  
   194  // Ensure Permissions are set on OpenFile/Mkdir/MkdirAll
   195  func TestPermSet(t *testing.T) {
   196  	const fileName = "/myFileTest"
   197  	const dirPath = "/myDirTest"
   198  	const dirPathAll = "/my/path/to/dir"
   199  
   200  	const fileMode = os.FileMode(0765)
   201  	// directories will also have the directory bit set
   202  	const dirMode = fileMode | os.ModeDir
   203  
   204  	fs := NewMemMapFs()
   205  
   206  	// Test Openfile
   207  	f, err := fs.OpenFile(fileName, os.O_CREATE, fileMode)
   208  	if err != nil {
   209  		t.Errorf("OpenFile Create failed: %s", err)
   210  		return
   211  	}
   212  	f.Close()
   213  
   214  	s, err := fs.Stat(fileName)
   215  	if err != nil {
   216  		t.Errorf("Stat failed: %s", err)
   217  		return
   218  	}
   219  	if s.Mode().String() != fileMode.String() {
   220  		t.Errorf("Permissions Incorrect: %s != %s", s.Mode().String(), fileMode.String())
   221  		return
   222  	}
   223  
   224  	// Test Mkdir
   225  	err = fs.Mkdir(dirPath, dirMode)
   226  	if err != nil {
   227  		t.Errorf("MkDir Create failed: %s", err)
   228  		return
   229  	}
   230  	s, err = fs.Stat(dirPath)
   231  	if err != nil {
   232  		t.Errorf("Stat failed: %s", err)
   233  		return
   234  	}
   235  	// sets File
   236  	if s.Mode().String() != dirMode.String() {
   237  		t.Errorf("Permissions Incorrect: %s != %s", s.Mode().String(), dirMode.String())
   238  		return
   239  	}
   240  
   241  	// Test MkdirAll
   242  	err = fs.MkdirAll(dirPathAll, dirMode)
   243  	if err != nil {
   244  		t.Errorf("MkDir Create failed: %s", err)
   245  		return
   246  	}
   247  	s, err = fs.Stat(dirPathAll)
   248  	if err != nil {
   249  		t.Errorf("Stat failed: %s", err)
   250  		return
   251  	}
   252  	if s.Mode().String() != dirMode.String() {
   253  		t.Errorf("Permissions Incorrect: %s != %s", s.Mode().String(), dirMode.String())
   254  		return
   255  	}
   256  }
   257  
   258  // Fails if multiple file objects use the same file.at counter in MemMapFs
   259  func TestMultipleOpenFiles(t *testing.T) {
   260  	defer removeAllTestFiles(t)
   261  	const fileName = "afero-demo2.txt"
   262  
   263  	var data = make([][]byte, len(Fss))
   264  
   265  	for i, fs := range Fss {
   266  		dir := testDir(fs)
   267  		path := filepath.Join(dir, fileName)
   268  		fh1, err := fs.Create(path)
   269  		if err != nil {
   270  			t.Error("fs.Create failed: " + err.Error())
   271  		}
   272  		_, err = fh1.Write([]byte("test"))
   273  		if err != nil {
   274  			t.Error("fh.Write failed: " + err.Error())
   275  		}
   276  		_, err = fh1.Seek(0, os.SEEK_SET)
   277  		if err != nil {
   278  			t.Error(err)
   279  		}
   280  
   281  		fh2, err := fs.OpenFile(path, os.O_RDWR, 0777)
   282  		if err != nil {
   283  			t.Error("fs.OpenFile failed: " + err.Error())
   284  		}
   285  		_, err = fh2.Seek(0, os.SEEK_END)
   286  		if err != nil {
   287  			t.Error(err)
   288  		}
   289  		_, err = fh2.Write([]byte("data"))
   290  		if err != nil {
   291  			t.Error(err)
   292  		}
   293  		err = fh2.Close()
   294  		if err != nil {
   295  			t.Error(err)
   296  		}
   297  
   298  		_, err = fh1.Write([]byte("data"))
   299  		if err != nil {
   300  			t.Error(err)
   301  		}
   302  		err = fh1.Close()
   303  		if err != nil {
   304  			t.Error(err)
   305  		}
   306  		// the file now should contain "datadata"
   307  		data[i], err = ReadFile(fs, path)
   308  		if err != nil {
   309  			t.Error(err)
   310  		}
   311  	}
   312  
   313  	for i, fs := range Fss {
   314  		if i == 0 {
   315  			continue
   316  		}
   317  		if string(data[0]) != string(data[i]) {
   318  			t.Errorf("%s and %s don't behave the same\n"+
   319  				"%s: \"%s\"\n%s: \"%s\"\n",
   320  				Fss[0].Name(), fs.Name(), Fss[0].Name(), data[0], fs.Name(), data[i])
   321  		}
   322  	}
   323  }
   324  
   325  // Test if file.Write() fails when opened as read only
   326  func TestReadOnly(t *testing.T) {
   327  	defer removeAllTestFiles(t)
   328  	const fileName = "afero-demo.txt"
   329  
   330  	for _, fs := range Fss {
   331  		dir := testDir(fs)
   332  		path := filepath.Join(dir, fileName)
   333  
   334  		f, err := fs.Create(path)
   335  		if err != nil {
   336  			t.Error(fs.Name()+":", "fs.Create failed: "+err.Error())
   337  		}
   338  		_, err = f.Write([]byte("test"))
   339  		if err != nil {
   340  			t.Error(fs.Name()+":", "Write failed: "+err.Error())
   341  		}
   342  		f.Close()
   343  
   344  		f, err = fs.Open(path)
   345  		if err != nil {
   346  			t.Error("fs.Open failed: " + err.Error())
   347  		}
   348  		_, err = f.Write([]byte("data"))
   349  		if err == nil {
   350  			t.Error(fs.Name()+":", "No write error")
   351  		}
   352  		f.Close()
   353  
   354  		f, err = fs.OpenFile(path, os.O_RDONLY, 0644)
   355  		if err != nil {
   356  			t.Error("fs.Open failed: " + err.Error())
   357  		}
   358  		_, err = f.Write([]byte("data"))
   359  		if err == nil {
   360  			t.Error(fs.Name()+":", "No write error")
   361  		}
   362  		f.Close()
   363  	}
   364  }
   365  
   366  func TestWriteCloseTime(t *testing.T) {
   367  	defer removeAllTestFiles(t)
   368  	const fileName = "afero-demo.txt"
   369  
   370  	for _, fs := range Fss {
   371  		dir := testDir(fs)
   372  		path := filepath.Join(dir, fileName)
   373  
   374  		f, err := fs.Create(path)
   375  		if err != nil {
   376  			t.Error(fs.Name()+":", "fs.Create failed: "+err.Error())
   377  		}
   378  		f.Close()
   379  
   380  		f, err = fs.Create(path)
   381  		if err != nil {
   382  			t.Error(fs.Name()+":", "fs.Create failed: "+err.Error())
   383  		}
   384  		fi, err := f.Stat()
   385  		if err != nil {
   386  			t.Error(fs.Name()+":", "Stat failed: "+err.Error())
   387  		}
   388  		timeBefore := fi.ModTime()
   389  
   390  		// sorry for the delay, but we have to make sure time advances,
   391  		// also on non Un*x systems...
   392  		switch runtime.GOOS {
   393  		case "windows":
   394  			time.Sleep(2 * time.Second)
   395  		case "darwin":
   396  			time.Sleep(1 * time.Second)
   397  		default: // depending on the FS, this may work with < 1 second, on my old ext3 it does not
   398  			time.Sleep(1 * time.Second)
   399  		}
   400  
   401  		_, err = f.Write([]byte("test"))
   402  		if err != nil {
   403  			t.Error(fs.Name()+":", "Write failed: "+err.Error())
   404  		}
   405  		f.Close()
   406  		fi, err = fs.Stat(path)
   407  		if err != nil {
   408  			t.Error(fs.Name()+":", "fs.Stat failed: "+err.Error())
   409  		}
   410  		if fi.ModTime().Equal(timeBefore) {
   411  			t.Error(fs.Name()+":", "ModTime was not set on Close()")
   412  		}
   413  	}
   414  }
   415  
   416  // This test should be run with the race detector on:
   417  // go test -race -v -timeout 10s -run TestRacingDeleteAndClose
   418  func TestRacingDeleteAndClose(t *testing.T) {
   419  	fs := NewMemMapFs()
   420  	pathname := "testfile"
   421  	f, err := fs.Create(pathname)
   422  	if err != nil {
   423  		t.Fatal(err)
   424  	}
   425  
   426  	in := make(chan bool)
   427  
   428  	go func() {
   429  		<-in
   430  		f.Close()
   431  	}()
   432  	go func() {
   433  		<-in
   434  		fs.Remove(pathname)
   435  	}()
   436  	close(in)
   437  }
   438  
   439  // This test should be run with the race detector on:
   440  // go test -run TestMemFsDataRace -race
   441  func TestMemFsDataRace(t *testing.T) {
   442  	const dir = "test_dir"
   443  	fs := NewMemMapFs()
   444  
   445  	if err := fs.MkdirAll(dir, 0777); err != nil {
   446  		t.Fatal(err)
   447  	}
   448  
   449  	const n = 1000
   450  	done := make(chan struct{})
   451  
   452  	go func() {
   453  		defer close(done)
   454  		for i := 0; i < n; i++ {
   455  			fname := filepath.Join(dir, fmt.Sprintf("%d.txt", i))
   456  			if err := WriteFile(fs, fname, []byte(""), 0777); err != nil {
   457  				panic(err)
   458  			}
   459  			if err := fs.Remove(fname); err != nil {
   460  				panic(err)
   461  			}
   462  		}
   463  	}()
   464  
   465  loop:
   466  	for {
   467  		select {
   468  		case <-done:
   469  			break loop
   470  		default:
   471  			_, err := ReadDir(fs, dir)
   472  			if err != nil {
   473  				t.Fatal(err)
   474  			}
   475  		}
   476  	}
   477  }
   478  
   479  // root is a directory
   480  func TestMemFsRootDirMode(t *testing.T) {
   481  	t.Parallel()
   482  
   483  	fs := NewMemMapFs()
   484  	info, err := fs.Stat("/")
   485  	if err != nil {
   486  		t.Fatal(err)
   487  	}
   488  	if !info.IsDir() {
   489  		t.Error("should be a directory")
   490  	}
   491  	if !info.Mode().IsDir() {
   492  		t.Errorf("FileMode is not directory, is %s", info.Mode().String())
   493  	}
   494  }
   495  
   496  // MkdirAll creates intermediate directories with correct mode
   497  func TestMemFsMkdirAllMode(t *testing.T) {
   498  	t.Parallel()
   499  
   500  	fs := NewMemMapFs()
   501  	err := fs.MkdirAll("/a/b/c", 0755)
   502  	if err != nil {
   503  		t.Fatal(err)
   504  	}
   505  	info, err := fs.Stat("/a")
   506  	if err != nil {
   507  		t.Fatal(err)
   508  	}
   509  	if !info.Mode().IsDir() {
   510  		t.Error("/a: mode is not directory")
   511  	}
   512  	if info.Mode() != os.FileMode(os.ModeDir|0755) {
   513  		t.Errorf("/a: wrong permissions, expected drwxr-xr-x, got %s", info.Mode())
   514  	}
   515  	info, err = fs.Stat("/a/b")
   516  	if err != nil {
   517  		t.Fatal(err)
   518  	}
   519  	if !info.Mode().IsDir() {
   520  		t.Error("/a/b: mode is not directory")
   521  	}
   522  	if info.Mode() != os.FileMode(os.ModeDir|0755) {
   523  		t.Errorf("/a/b: wrong permissions, expected drwxr-xr-x, got %s", info.Mode())
   524  	}
   525  	info, err = fs.Stat("/a/b/c")
   526  	if err != nil {
   527  		t.Fatal(err)
   528  	}
   529  	if !info.Mode().IsDir() {
   530  		t.Error("/a/b/c: mode is not directory")
   531  	}
   532  	if info.Mode() != os.FileMode(os.ModeDir|0755) {
   533  		t.Errorf("/a/b/c: wrong permissions, expected drwxr-xr-x, got %s", info.Mode())
   534  	}
   535  }
   536  
   537  // MkdirAll does not change permissions of already-existing directories
   538  func TestMemFsMkdirAllNoClobber(t *testing.T) {
   539  	t.Parallel()
   540  
   541  	fs := NewMemMapFs()
   542  	err := fs.MkdirAll("/a/b/c", 0755)
   543  	if err != nil {
   544  		t.Fatal(err)
   545  	}
   546  	info, err := fs.Stat("/a/b")
   547  	if err != nil {
   548  		t.Fatal(err)
   549  	}
   550  	if info.Mode() != os.FileMode(os.ModeDir|0755) {
   551  		t.Errorf("/a/b: wrong permissions, expected drwxr-xr-x, got %s", info.Mode())
   552  	}
   553  	err = fs.MkdirAll("/a/b/c/d/e/f", 0710)
   554  	// '/a/b' is unchanged
   555  	if err != nil {
   556  		t.Fatal(err)
   557  	}
   558  	info, err = fs.Stat("/a/b")
   559  	if err != nil {
   560  		t.Fatal(err)
   561  	}
   562  	if info.Mode() != os.FileMode(os.ModeDir|0755) {
   563  		t.Errorf("/a/b: wrong permissions, expected drwxr-xr-x, got %s", info.Mode())
   564  	}
   565  	// new directories created with proper permissions
   566  	info, err = fs.Stat("/a/b/c/d")
   567  	if err != nil {
   568  		t.Fatal(err)
   569  	}
   570  	if info.Mode() != os.FileMode(os.ModeDir|0710) {
   571  		t.Errorf("/a/b/c/d: wrong permissions, expected drwx--x---, got %s", info.Mode())
   572  	}
   573  	info, err = fs.Stat("/a/b/c/d/e")
   574  	if err != nil {
   575  		t.Fatal(err)
   576  	}
   577  	if info.Mode() != os.FileMode(os.ModeDir|0710) {
   578  		t.Errorf("/a/b/c/d/e: wrong permissions, expected drwx--x---, got %s", info.Mode())
   579  	}
   580  	info, err = fs.Stat("/a/b/c/d/e/f")
   581  	if err != nil {
   582  		t.Fatal(err)
   583  	}
   584  	if info.Mode() != os.FileMode(os.ModeDir|0710) {
   585  		t.Errorf("/a/b/c/d/e/f: wrong permissions, expected drwx--x---, got %s", info.Mode())
   586  	}
   587  }
   588  
   589  func TestMemFsDirMode(t *testing.T) {
   590  	fs := NewMemMapFs()
   591  	err := fs.Mkdir("/testDir1", 0644)
   592  	if err != nil {
   593  		t.Error(err)
   594  	}
   595  	err = fs.MkdirAll("/sub/testDir2", 0644)
   596  	if err != nil {
   597  		t.Error(err)
   598  	}
   599  	info, err := fs.Stat("/testDir1")
   600  	if err != nil {
   601  		t.Error(err)
   602  	}
   603  	if !info.IsDir() {
   604  		t.Error("should be a directory")
   605  	}
   606  	if !info.Mode().IsDir() {
   607  		t.Error("FileMode is not directory")
   608  	}
   609  	info, err = fs.Stat("/sub/testDir2")
   610  	if err != nil {
   611  		t.Error(err)
   612  	}
   613  	if !info.IsDir() {
   614  		t.Error("should be a directory")
   615  	}
   616  	if !info.Mode().IsDir() {
   617  		t.Error("FileMode is not directory")
   618  	}
   619  }
   620  
   621  func TestMemFsUnexpectedEOF(t *testing.T) {
   622  	t.Parallel()
   623  
   624  	fs := NewMemMapFs()
   625  
   626  	if err := WriteFile(fs, "file.txt", []byte("abc"), 0777); err != nil {
   627  		t.Fatal(err)
   628  	}
   629  
   630  	f, err := fs.Open("file.txt")
   631  	if err != nil {
   632  		t.Fatal(err)
   633  	}
   634  	defer f.Close()
   635  
   636  	// Seek beyond the end.
   637  	_, err = f.Seek(512, 0)
   638  	if err != nil {
   639  		t.Fatal(err)
   640  	}
   641  
   642  	buff := make([]byte, 256)
   643  	_, err = io.ReadAtLeast(f, buff, 256)
   644  
   645  	if err != io.ErrUnexpectedEOF {
   646  		t.Fatal("Expected ErrUnexpectedEOF")
   647  	}
   648  }
   649  
   650  func TestMemFsChmod(t *testing.T) {
   651  	t.Parallel()
   652  
   653  	fs := NewMemMapFs()
   654  	const file = "hello"
   655  	if err := fs.Mkdir(file, 0700); err != nil {
   656  		t.Fatal(err)
   657  	}
   658  
   659  	info, err := fs.Stat(file)
   660  	if err != nil {
   661  		t.Fatal(err)
   662  	}
   663  	if info.Mode().String() != "drwx------" {
   664  		t.Fatal("mkdir failed to create a directory: mode =", info.Mode())
   665  	}
   666  
   667  	err = fs.Chmod(file, 0)
   668  	if err != nil {
   669  		t.Error("Failed to run chmod:", err)
   670  	}
   671  
   672  	info, err = fs.Stat(file)
   673  	if err != nil {
   674  		t.Fatal(err)
   675  	}
   676  	if info.Mode().String() != "d---------" {
   677  		t.Error("chmod should not change file type. New mode =", info.Mode())
   678  	}
   679  }
   680  
   681  // can't use Mkdir to get around which permissions we're allowed to set
   682  func TestMemFsMkdirModeIllegal(t *testing.T) {
   683  	t.Parallel()
   684  
   685  	fs := NewMemMapFs()
   686  	err := fs.Mkdir("/a", os.ModeSocket|0755)
   687  	if err != nil {
   688  		t.Fatal(err)
   689  	}
   690  	info, err := fs.Stat("/a")
   691  	if err != nil {
   692  		t.Fatal(err)
   693  	}
   694  	if info.Mode() != os.FileMode(os.ModeDir|0755) {
   695  		t.Fatalf("should not be able to use Mkdir to set illegal mode: %s", info.Mode().String())
   696  	}
   697  }
   698  
   699  // can't use OpenFile to get around which permissions we're allowed to set
   700  func TestMemFsOpenFileModeIllegal(t *testing.T) {
   701  	t.Parallel()
   702  
   703  	fs := NewMemMapFs()
   704  	file, err := fs.OpenFile("/a", os.O_CREATE, os.ModeSymlink|0644)
   705  	if err != nil {
   706  		t.Fatal(err)
   707  	}
   708  	defer file.Close()
   709  	info, err := fs.Stat("/a")
   710  	if err != nil {
   711  		t.Fatal(err)
   712  	}
   713  	if info.Mode() != os.FileMode(0644) {
   714  		t.Fatalf("should not be able to use OpenFile to set illegal mode: %s", info.Mode().String())
   715  	}
   716  }
   717  
   718  // LstatIfPossible should always return false, since MemMapFs does not
   719  // support symlinks.
   720  func TestMemFsLstatIfPossible(t *testing.T) {
   721  	t.Parallel()
   722  
   723  	fs := NewMemMapFs()
   724  
   725  	// We assert that fs implements Lstater
   726  	fsAsserted, ok := fs.(Lstater)
   727  	if !ok {
   728  		t.Fatalf("The filesytem does not implement Lstater")
   729  	}
   730  
   731  	file, err := fs.OpenFile("/a.txt", os.O_CREATE, 0o644)
   732  	if err != nil {
   733  		t.Fatalf("Error when opening file: %v", err)
   734  	}
   735  	defer file.Close()
   736  
   737  	_, lstatCalled, err := fsAsserted.LstatIfPossible("/a.txt")
   738  	if err != nil {
   739  		t.Fatalf("Function returned err: %v", err)
   740  	}
   741  	if lstatCalled {
   742  		t.Fatalf("Function indicated lstat was called. This should never be true.")
   743  	}
   744  }