tinygo/src/os/os_anyos_test.go
2022-08-07 10:32:23 +02:00

333 строки
8 КиБ
Go

//go:build windows || darwin || (linux && !baremetal)
// +build windows darwin linux,!baremetal
package os_test
import (
"io/fs"
"os"
. "os"
"path/filepath"
"runtime"
"strconv"
"strings"
"testing"
"testing/fstest"
"time"
)
var dot = []string{
"dir.go",
"env.go",
"errors.go",
"file.go",
"os_test.go",
"types.go",
"stat_darwin.go",
"stat_linux.go",
}
func randomName() string {
// fastrand() does not seem available here, so fake it
ns := time.Now().Nanosecond()
pid := Getpid()
return strconv.FormatUint(uint64(ns^pid), 10)
}
func TestMkdir(t *testing.T) {
dir := TempDir() + "/TestMkdir" + randomName()
Remove(dir)
err := Mkdir(dir, 0755)
defer Remove(dir)
if err != nil {
t.Errorf("Mkdir(%s, 0755) returned %v", dir, err)
}
// tests the "directory" branch of Remove
err = Remove(dir)
if err != nil {
t.Errorf("Remove(%s) returned %v", dir, err)
}
}
func TestStatBadDir(t *testing.T) {
if runtime.GOOS == "windows" {
t.Log("TODO: TestStatBadDir: IsNotExist fails on Windows, skipping")
return
}
dir := TempDir()
badDir := filepath.Join(dir, "not-exist/really-not-exist")
_, err := Stat(badDir)
if pe, ok := err.(*fs.PathError); !ok || !IsNotExist(err) || pe.Path != badDir {
t.Errorf("Mkdir error = %#v; want PathError for path %q satisifying IsNotExist", err, badDir)
}
}
func equal(name1, name2 string) (r bool) {
switch runtime.GOOS {
case "windows":
r = strings.ToLower(name1) == strings.ToLower(name2)
default:
r = name1 == name2
}
return
}
func TestFstat(t *testing.T) {
if runtime.GOARCH == "386" || runtime.GOARCH == "arm" {
t.Log("TODO: implement fstat for 386 and arm")
return
}
sfname := "TestFstat"
path := TempDir() + "/" + sfname
payload := writeFile(t, path, O_CREATE|O_TRUNC|O_RDWR, "Hello")
defer Remove(path)
file, err1 := Open(path)
if err1 != nil {
t.Fatal("open failed:", err1)
}
defer file.Close()
dir, err2 := file.Stat()
if err2 != nil {
t.Fatal("fstat failed:", err2)
}
if !equal(sfname, dir.Name()) {
t.Error("name should be ", sfname, "; is", dir.Name())
}
filesize := len(payload)
if dir.Size() != int64(filesize) {
t.Error("size should be", filesize, "; is", dir.Size())
}
}
func writeFile(t *testing.T, fname string, flag int, text string) string {
f, err := OpenFile(fname, flag, 0666)
if err != nil {
t.Fatalf("Open: %v", err)
}
n, err := f.WriteString(text)
if err != nil {
t.Fatalf("WriteString: %d, %v", n, err)
}
f.Close()
data, err := ReadFile(f.Name())
if err != nil {
t.Fatalf("ReadFile: %v", err)
}
return string(data)
}
func TestRemove(t *testing.T) {
f := TempDir() + "/TestRemove" + randomName()
err := Remove(f)
if err == nil {
t.Errorf("TestRemove: remove of nonexistent file did not fail")
} else {
if pe, ok := err.(*fs.PathError); !ok {
t.Errorf("TestRemove: expected PathError, got err %q", err.Error())
} else {
if pe.Path != f {
t.Errorf("TestRemove: PathError returned path %q, expected %q", pe.Path, f)
}
}
if !IsNotExist(err) {
t.Errorf("TestRemove: expected IsNotExist(err) true, got false; err %q", err.Error())
}
}
s := writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
if s != "new" {
t.Fatalf("writeFile: have %q want %q", s, "new")
}
// tests the "file" branch of Remove
err = Remove(f)
if err != nil {
t.Fatalf("Remove: %v", err)
}
}
// chtmpdir changes the working directory to a new temporary directory and
// provides a cleanup function.
func chtmpdir(t *testing.T) func() {
oldwd, err := Getwd()
if err != nil {
t.Fatalf("chtmpdir: %v", err)
}
d, err := MkdirTemp("", "test")
if err != nil {
t.Fatalf("chtmpdir: %v", err)
}
if err := Chdir(d); err != nil {
t.Fatalf("chtmpdir: %v", err)
}
return func() {
if err := Chdir(oldwd); err != nil {
t.Fatalf("chtmpdir: %v", err)
}
RemoveAll(d)
}
}
func TestRename(t *testing.T) {
// TODO: use t.TempDir()
from, to := TempDir()+"/"+"TestRename-from", TempDir()+"/"+"TestRename-to"
file, err := Create(from)
defer Remove(from) // TODO: switch to t.Tempdir, remove this line
if err != nil {
t.Fatalf("open %q failed: %v", from, err)
}
defer Remove(to) // TODO: switch to t.Tempdir, remove this line
if err = file.Close(); err != nil {
t.Errorf("close %q failed: %v", from, err)
}
err = Rename(from, to)
if err != nil {
t.Fatalf("rename %q, %q failed: %v", to, from, err)
}
_, err = Stat(to)
if err != nil {
t.Errorf("stat %q failed: %v", to, err)
}
}
func TestRenameOverwriteDest(t *testing.T) {
from, to := TempDir()+"/"+"TestRenameOverwrite-from", TempDir()+"/"+"TestRenameOverwrite-to"
toData := []byte("to")
fromData := []byte("from")
err := os.WriteFile(to, toData, 0777)
defer Remove(to) // TODO: switch to t.Tempdir, remove this line
if err != nil {
t.Fatalf("write file %q failed: %v", to, err)
}
err = os.WriteFile(from, fromData, 0777)
defer Remove(from) // TODO: switch to t.Tempdir, remove this line
if err != nil {
t.Fatalf("write file %q failed: %v", from, err)
}
err = Rename(from, to)
if err != nil {
t.Fatalf("rename %q, %q failed: %v", to, from, err)
}
_, err = Stat(from)
if err == nil {
t.Errorf("from file %q still exists", from)
}
if runtime.GOOS == "windows" {
t.Log("TODO: TestRenameOverwriteDest: IsNotExist fails on Windows, skipping")
} else if err != nil && !IsNotExist(err) {
t.Fatalf("stat from: %v", err)
}
toFi, err := Stat(to)
if err != nil {
t.Fatalf("stat %q failed: %v", to, err)
}
if toFi.Size() != int64(len(fromData)) {
t.Errorf(`"to" size = %d; want %d (old "from" size)`, toFi.Size(), len(fromData))
}
}
func TestRenameFailed(t *testing.T) {
from, to := TempDir()+"/"+"RenameFailed-from", TempDir()+"/"+"RenameFailed-to"
err := Rename(from, to)
switch err := err.(type) {
case *LinkError:
if err.Op != "rename" {
t.Errorf("rename %q, %q: err.Op: want %q, got %q", from, to, "rename", err.Op)
}
if err.Old != from {
t.Errorf("rename %q, %q: err.Old: want %q, got %q", from, to, from, err.Old)
}
if err.New != to {
t.Errorf("rename %q, %q: err.New: want %q, got %q", from, to, to, err.New)
}
case nil:
t.Errorf("rename %q, %q: expected error, got nil", from, to)
default:
t.Errorf("rename %q, %q: expected %T, got %T %v", from, to, new(LinkError), err, err)
}
}
func TestUserHomeDir(t *testing.T) {
dir, err := UserHomeDir()
if dir == "" && err == nil {
t.Fatal("UserHomeDir returned an empty string but no error")
}
if err != nil {
t.Logf("UserHomeDir failed: %v", err)
return
}
fi, err := Stat(dir)
if err != nil {
t.Fatal(err)
}
if !fi.IsDir() {
t.Fatalf("dir %s is not directory; type = %v", dir, fi.Mode())
}
}
func TestDirFS(t *testing.T) {
if runtime.GOOS == "windows" {
t.Log("TODO: implement Readdir for Windows")
return
}
if isWASI {
t.Log("TODO: allow foo/bar/. as synonym for path foo/bar on wasi?")
return
}
if err := fstest.TestFS(DirFS("./testdata/dirfs"), "a", "b", "dir/x"); err != nil {
t.Fatal(err)
}
// Test that Open does not accept backslash as separator.
d := DirFS(".")
_, err := d.Open(`testdata\dirfs`)
if err == nil {
t.Fatalf(`Open testdata\dirfs succeeded`)
}
}
func TestDirFSPathsValid(t *testing.T) {
if runtime.GOOS == "windows" {
t.Log("skipping on Windows")
return
}
if isWASI {
t.Log("skipping on wasi because it fails on wasi on windows")
return
}
// TODO: switch back to t.TempDir once it's implemented
d, err := MkdirTemp("", "TestDirFSPathsValid")
if err != nil {
t.Fatal(err)
}
defer Remove(d)
if err := WriteFile(filepath.Join(d, "control.txt"), []byte(string("Hello, world!")), 0644); err != nil {
t.Fatal(err)
}
defer Remove(filepath.Join(d, "control.txt"))
if err := WriteFile(filepath.Join(d, `e:xperi\ment.txt`), []byte(string("Hello, colon and backslash!")), 0644); err != nil {
t.Fatal(err)
}
defer Remove(filepath.Join(d, `e:xperi\ment.txt`))
fsys := DirFS(d)
err = fs.WalkDir(fsys, ".", func(path string, e fs.DirEntry, err error) error {
if fs.ValidPath(e.Name()) {
t.Logf("%q ok", e.Name())
} else {
t.Errorf("%q INVALID", e.Name())
}
return nil
})
if err != nil {
t.Fatal(err)
}
}