Files
wazero/internal/sysfs/readfs_test.go
Crypt Keeper e77f24fe31 sysfs: drops os.File special casing for fs.FS to pass wasi-testsuite (#1174)
This adds a wazero adapter which passes wasi-testsuite 100pct on darwin,
linux and windows. While the main change was adding inodes to the wasi
`fd_readdir` dirents, there was a lot of incidental work needed.

Most of the work was troubleshooting in nature, around windows
specifically, but also wrapping of files. This backfills a lot of tests
and reworked how wrapping works, particularly around windows.

To accommodate this, we drop `os.File` special casing except for
`sysfs.DirFS`

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-03-01 13:28:57 +08:00

195 lines
4.5 KiB
Go

package sysfs
import (
"io/fs"
"os"
pathutil "path"
"runtime"
"syscall"
"testing"
"github.com/tetratelabs/wazero/internal/fstest"
"github.com/tetratelabs/wazero/internal/testing/require"
)
func TestNewReadFS(t *testing.T) {
tmpDir := t.TempDir()
// Doesn't double-wrap file systems that are already read-only
require.Equal(t, UnimplementedFS{}, NewReadFS(UnimplementedFS{}))
// Wraps a fs.FS because it allows access to Write
adapted := Adapt(os.DirFS(tmpDir))
require.NotEqual(t, adapted, NewReadFS(adapted))
// Wraps a writeable file system
writeable := NewDirFS(tmpDir)
readFS := NewReadFS(writeable)
require.NotEqual(t, writeable, readFS)
}
func TestReadFS_String(t *testing.T) {
writeable := NewDirFS("/tmp")
readFS := NewReadFS(writeable)
require.NotEqual(t, writeable, readFS)
require.Equal(t, "/tmp", readFS.String())
}
func TestReadFS_Lstat(t *testing.T) {
tmpDir := t.TempDir()
require.NoError(t, fstest.WriteTestFiles(tmpDir))
writeable := NewDirFS(tmpDir)
for _, path := range []string{"animals.txt", "sub", "sub-link"} {
require.NoError(t, writeable.Symlink(path, path+"-link"))
}
testFS := NewReadFS(writeable)
testLstat(t, testFS)
}
func TestReadFS_MkDir(t *testing.T) {
writeable := NewDirFS(t.TempDir())
testFS := NewReadFS(writeable)
err := testFS.Mkdir("mkdir", fs.ModeDir)
require.EqualErrno(t, syscall.ENOSYS, err)
}
func TestReadFS_Chmod(t *testing.T) {
writeable := NewDirFS(t.TempDir())
testFS := NewReadFS(writeable)
err := testFS.Chmod("chmod", fs.ModeDir)
require.EqualErrno(t, syscall.ENOSYS, err)
}
func TestReadFS_Rename(t *testing.T) {
tmpDir := t.TempDir()
writeable := NewDirFS(tmpDir)
testFS := NewReadFS(writeable)
file1 := "file1"
file1Path := pathutil.Join(tmpDir, file1)
file1Contents := []byte{1}
err := os.WriteFile(file1Path, file1Contents, 0o600)
require.NoError(t, err)
file2 := "file2"
file2Path := pathutil.Join(tmpDir, file2)
file2Contents := []byte{2}
err = os.WriteFile(file2Path, file2Contents, 0o600)
require.NoError(t, err)
err = testFS.Rename(file1, file2)
require.EqualErrno(t, syscall.ENOSYS, err)
}
func TestReadFS_Rmdir(t *testing.T) {
tmpDir := t.TempDir()
writeable := NewDirFS(tmpDir)
testFS := NewReadFS(writeable)
path := "rmdir"
realPath := pathutil.Join(tmpDir, path)
require.NoError(t, os.Mkdir(realPath, 0o700))
err := testFS.Rmdir(path)
require.EqualErrno(t, syscall.ENOSYS, err)
}
func TestReadFS_Unlink(t *testing.T) {
tmpDir := t.TempDir()
writeable := NewDirFS(tmpDir)
testFS := NewReadFS(writeable)
path := "unlink"
realPath := pathutil.Join(tmpDir, path)
require.NoError(t, os.WriteFile(realPath, []byte{}, 0o600))
err := testFS.Unlink(path)
require.EqualErrno(t, syscall.ENOSYS, err)
}
func TestReadFS_Utimes(t *testing.T) {
tmpDir := t.TempDir()
writeable := NewDirFS(tmpDir)
testFS := NewReadFS(writeable)
path := "utimes"
realPath := pathutil.Join(tmpDir, path)
require.NoError(t, os.WriteFile(realPath, []byte{}, 0o600))
err := testFS.Utimes(path, 1, 1)
require.EqualErrno(t, syscall.ENOSYS, err)
}
func TestReadFS_Open_Read(t *testing.T) {
t.Parallel()
tmpDir := t.TempDir()
require.NoError(t, fstest.WriteTestFiles(tmpDir))
type test struct {
name string
fs FS
expectIno bool
}
tests := []test{
{name: "DirFS", fs: NewReadFS(NewDirFS(tmpDir)), expectIno: true},
{name: "fstest.MapFS", fs: NewReadFS(Adapt(fstest.FS)), expectIno: false},
}
// We can't correct operating system portability issues with os.DirFS on
// windows. Use syscall.DirFS instead!
if runtime.GOOS != "windows" {
tests = append(tests, test{name: "os.DirFS", fs: NewReadFS(Adapt(os.DirFS(tmpDir))), expectIno: true})
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
testOpen_Read(t, tc.fs, tc.expectIno)
})
}
}
func TestReadFS_Stat(t *testing.T) {
tmpDir := t.TempDir()
require.NoError(t, fstest.WriteTestFiles(tmpDir))
writeable := NewDirFS(tmpDir)
testFS := NewReadFS(writeable)
testStat(t, testFS)
}
func TestReadFS_Readlink(t *testing.T) {
tmpDir := t.TempDir()
require.NoError(t, fstest.WriteTestFiles(tmpDir))
writeable := NewDirFS(tmpDir)
testFS := NewReadFS(writeable)
testReadlink(t, testFS, writeable)
}
func TestReadFS_TestFS(t *testing.T) {
t.Parallel()
// Set up the test files
tmpDir := t.TempDir()
require.NoError(t, fstest.WriteTestFiles(tmpDir))
// Create a writeable filesystem
testFS := NewDirFS(tmpDir)
// Wrap it as read-only
testFS = NewReadFS(testFS)
// Run TestFS via the adapter
require.NoError(t, fstest.TestFS(testFS.(fs.FS)))
}