333 строки
8 КиБ
Go
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)
|
|
}
|
|
}
|