github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/sysfs/open_file_test.go (about)

     1  package sysfs
     2  
     3  import (
     4  	"os"
     5  	path "path/filepath"
     6  	"runtime"
     7  	"testing"
     8  
     9  	"github.com/bananabytelabs/wazero/experimental/sys"
    10  	"github.com/bananabytelabs/wazero/internal/testing/require"
    11  )
    12  
    13  func TestOpenFile(t *testing.T) {
    14  	tmpDir := t.TempDir()
    15  
    16  	t.Run("directory with a trailing slash", func(t *testing.T) {
    17  		path := path.Join(tmpDir, "dir", "nested")
    18  		err := os.MkdirAll(path, 0o700)
    19  		require.NoError(t, err)
    20  
    21  		f, errno := OpenFile(path+"/", sys.O_RDONLY, 0)
    22  		require.EqualErrno(t, 0, errno)
    23  		require.NoError(t, f.Close())
    24  	})
    25  
    26  	// from os.TestDirFSPathsValid
    27  	if runtime.GOOS != "windows" {
    28  		t.Run("strange name", func(t *testing.T) {
    29  			f, errno := OpenFile(path.Join(tmpDir, `e:xperi\ment.txt`), sys.O_WRONLY|sys.O_CREAT|sys.O_TRUNC, 0o600)
    30  			require.EqualErrno(t, 0, errno)
    31  			require.NoError(t, f.Close())
    32  		})
    33  	}
    34  }
    35  
    36  func TestOpenFile_Errors(t *testing.T) {
    37  	tmpDir := t.TempDir()
    38  
    39  	t.Run("file with a trailing slash is ENOTDIR", func(t *testing.T) {
    40  		nested := path.Join(tmpDir, "dir", "nested")
    41  		err := os.MkdirAll(nested, 0o700)
    42  		require.NoError(t, err)
    43  
    44  		nestedFile := path.Join(nested, "file")
    45  		err = os.WriteFile(nestedFile, nil, 0o700)
    46  		require.NoError(t, err)
    47  
    48  		_, errno := OpenFile(nestedFile+"/", sys.O_RDONLY, 0)
    49  		require.EqualErrno(t, sys.ENOTDIR, errno)
    50  	})
    51  
    52  	t.Run("not found must be ENOENT", func(t *testing.T) {
    53  		_, errno := OpenFile(path.Join(tmpDir, "not-really-exist.txt"), sys.O_RDONLY, 0o600)
    54  		require.EqualErrno(t, sys.ENOENT, errno)
    55  	})
    56  
    57  	// This is the same as https://github.com/ziglang/zig/blob/d24ebf1d12cf66665b52136a2807f97ff021d78d/lib/std/os/test.zig#L105-L112
    58  	t.Run("try creating on existing file must be EEXIST", func(t *testing.T) {
    59  		filepath := path.Join(tmpDir, "file.txt")
    60  		f, errno := OpenFile(filepath, sys.O_RDWR|sys.O_CREAT|sys.O_EXCL, 0o666)
    61  		require.EqualErrno(t, 0, errno)
    62  		defer f.Close()
    63  
    64  		_, err := OpenFile(filepath, sys.O_RDWR|sys.O_CREAT|sys.O_EXCL, 0o666)
    65  		require.EqualErrno(t, sys.EEXIST, err)
    66  	})
    67  
    68  	t.Run("writing to a read-only file is EBADF", func(t *testing.T) {
    69  		path := path.Join(tmpDir, "file")
    70  		require.NoError(t, os.WriteFile(path, nil, 0o600))
    71  
    72  		f := requireOpenFile(t, path, sys.O_RDONLY, 0)
    73  		defer f.Close()
    74  
    75  		_, errno := f.Write([]byte{1, 2, 3, 4})
    76  		require.EqualErrno(t, sys.EBADF, errno)
    77  	})
    78  
    79  	t.Run("writing to a directory is EISDIR", func(t *testing.T) {
    80  		path := path.Join(tmpDir, "diragain")
    81  		require.NoError(t, os.Mkdir(path, 0o755))
    82  
    83  		f := requireOpenFile(t, path, sys.O_RDONLY, 0)
    84  		defer f.Close()
    85  
    86  		_, errno := f.Write([]byte{1, 2, 3, 4})
    87  		require.EqualErrno(t, sys.EISDIR, errno)
    88  	})
    89  
    90  	// This is similar to https://github.com/WebAssembly/wasi-testsuite/blob/dc7f8d27be1030cd4788ebdf07d9b57e5d23441e/tests/rust/src/bin/dangling_symlink.rs
    91  	t.Run("dangling symlinks", func(t *testing.T) {
    92  		target := path.Join(tmpDir, "target")
    93  		symlink := path.Join(tmpDir, "dangling_symlink_symlink.cleanup")
    94  
    95  		err := os.Symlink(target, symlink)
    96  		require.NoError(t, err)
    97  
    98  		_, errno := OpenFile(symlink, sys.O_DIRECTORY|sys.O_NOFOLLOW, 0o0666)
    99  		require.EqualErrno(t, sys.ENOTDIR, errno)
   100  
   101  		_, errno = OpenFile(symlink, sys.O_NOFOLLOW, 0o0666)
   102  		require.EqualErrno(t, sys.ELOOP, errno)
   103  	})
   104  
   105  	t.Run("opening a directory writeable is EISDIR", func(t *testing.T) {
   106  		_, errno := OpenFile(tmpDir, sys.O_DIRECTORY|sys.O_WRONLY, 0o0666)
   107  		require.EqualErrno(t, sys.EISDIR, errno)
   108  
   109  		_, errno = OpenFile(tmpDir, sys.O_DIRECTORY|sys.O_WRONLY, 0o0666)
   110  		require.EqualErrno(t, sys.EISDIR, errno)
   111  	})
   112  }