summaryrefslogtreecommitdiffstats
path: root/llgo/third_party/gofrontend/libgo/go/os/os_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'llgo/third_party/gofrontend/libgo/go/os/os_test.go')
-rw-r--r--llgo/third_party/gofrontend/libgo/go/os/os_test.go400
1 files changed, 313 insertions, 87 deletions
diff --git a/llgo/third_party/gofrontend/libgo/go/os/os_test.go b/llgo/third_party/gofrontend/libgo/go/os/os_test.go
index 7a86efac218..78201f2c27e 100644
--- a/llgo/third_party/gofrontend/libgo/go/os/os_test.go
+++ b/llgo/third_party/gofrontend/libgo/go/os/os_test.go
@@ -9,6 +9,7 @@ import (
"errors"
"flag"
"fmt"
+ "internal/testenv"
"io"
"io/ioutil"
. "os"
@@ -21,7 +22,6 @@ import (
"sync"
"syscall"
"testing"
- "text/template"
"time"
)
@@ -41,18 +41,33 @@ type sysDir struct {
files []string
}
-var sysdir = func() (sd *sysDir) {
+var sysdir = func() *sysDir {
switch runtime.GOOS {
case "android":
- sd = &sysDir{
+ return &sysDir{
"/system/etc",
[]string{
"audio_policy.conf",
"system_fonts.xml",
},
}
+ case "darwin":
+ switch runtime.GOARCH {
+ case "arm", "arm64":
+ wd, err := syscall.Getwd()
+ if err != nil {
+ wd = err.Error()
+ }
+ return &sysDir{
+ filepath.Join(wd, "..", ".."),
+ []string{
+ "ResourceRules.plist",
+ "Info.plist",
+ },
+ }
+ }
case "windows":
- sd = &sysDir{
+ return &sysDir{
Getenv("SystemRoot") + "\\system32\\drivers\\etc",
[]string{
"networks",
@@ -61,24 +76,22 @@ var sysdir = func() (sd *sysDir) {
},
}
case "plan9":
- sd = &sysDir{
+ return &sysDir{
"/lib/ndb",
[]string{
"common",
"local",
},
}
- default:
- sd = &sysDir{
- "/etc",
- []string{
- "group",
- "hosts",
- "passwd",
- },
- }
}
- return
+ return &sysDir{
+ "/etc",
+ []string{
+ "group",
+ "hosts",
+ "passwd",
+ },
+ }
}()
func size(name string, t *testing.T) int64 {
@@ -112,15 +125,22 @@ func equal(name1, name2 string) (r bool) {
return
}
-func newFile(testName string, t *testing.T) (f *File) {
- // Use a local file system, not NFS.
- // On Unix, override $TMPDIR in case the user
- // has it set to an NFS-mounted directory.
- dir := ""
- if runtime.GOOS != "android" && runtime.GOOS != "windows" {
- dir = "/tmp"
+// localTmp returns a local temporary directory not on NFS.
+func localTmp() string {
+ switch runtime.GOOS {
+ case "android", "windows":
+ return TempDir()
+ case "darwin":
+ switch runtime.GOARCH {
+ case "arm", "arm64":
+ return TempDir()
+ }
}
- f, err := ioutil.TempFile(dir, "_Go_"+testName)
+ return "/tmp"
+}
+
+func newFile(testName string, t *testing.T) (f *File) {
+ f, err := ioutil.TempFile(localTmp(), "_Go_"+testName)
if err != nil {
t.Fatalf("TempFile %s: %s", testName, err)
}
@@ -128,14 +148,7 @@ func newFile(testName string, t *testing.T) (f *File) {
}
func newDir(testName string, t *testing.T) (name string) {
- // Use a local file system, not NFS.
- // On Unix, override $TMPDIR in case the user
- // has it set to an NFS-mounted directory.
- dir := ""
- if runtime.GOOS != "android" && runtime.GOOS != "windows" {
- dir = "/tmp"
- }
- name, err := ioutil.TempDir(dir, "_Go_"+testName)
+ name, err := ioutil.TempDir(localTmp(), "_Go_"+testName)
if err != nil {
t.Fatalf("TempDir %s: %s", testName, err)
}
@@ -310,6 +323,15 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
switch runtime.GOOS {
case "android":
dir = "/system/bin"
+ case "darwin":
+ switch runtime.GOARCH {
+ case "arm", "arm64":
+ wd, err := Getwd()
+ if err != nil {
+ t.Fatal(err)
+ }
+ dir = wd
+ }
case "plan9":
dir = "/bin"
case "windows":
@@ -489,11 +511,35 @@ func TestReaddirStatFailures(t *testing.T) {
}
}
+// Readdir on a regular file should fail.
+func TestReaddirOfFile(t *testing.T) {
+ f, err := ioutil.TempFile("", "_Go_ReaddirOfFile")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer Remove(f.Name())
+ f.Write([]byte("foo"))
+ f.Close()
+ reg, err := Open(f.Name())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer reg.Close()
+
+ names, err := reg.Readdirnames(-1)
+ if err == nil {
+ t.Error("Readdirnames succeeded; want non-nil error")
+ }
+ if len(names) > 0 {
+ t.Errorf("unexpected dir names in regular file: %q", names)
+ }
+}
+
func TestHardLink(t *testing.T) {
- // Hardlinks are not supported under windows or Plan 9.
if runtime.GOOS == "plan9" {
- return
+ t.Skip("skipping on plan9, hardlinks not supported")
}
+ defer chtmpdir(t)()
from, to := "hardlinktestfrom", "hardlinktestto"
Remove(from) // Just in case.
file, err := Create(to)
@@ -508,6 +554,14 @@ func TestHardLink(t *testing.T) {
if err != nil {
t.Fatalf("link %q, %q failed: %v", to, from, err)
}
+
+ none := "hardlinktestnone"
+ err = Link(none, none)
+ // Check the returned error is well-formed.
+ if lerr, ok := err.(*LinkError); !ok || lerr.Error() == "" {
+ t.Errorf("link %q, %q failed to return a valid error", none, none)
+ }
+
defer Remove(from)
tostat, err := Stat(to)
if err != nil {
@@ -522,6 +576,31 @@ func TestHardLink(t *testing.T) {
}
}
+// chtmpdir changes the working directory to a new temporary directory and
+// provides a cleanup function. Used when PWD is read-only.
+func chtmpdir(t *testing.T) func() {
+ if runtime.GOOS != "darwin" || (runtime.GOARCH != "arm" && runtime.GOARCH != "arm64") {
+ return func() {} // only needed on darwin/arm{,64}
+ }
+ oldwd, err := Getwd()
+ if err != nil {
+ t.Fatalf("chtmpdir: %v", err)
+ }
+ d, err := ioutil.TempDir("", "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 TestSymlink(t *testing.T) {
switch runtime.GOOS {
case "android", "nacl", "plan9":
@@ -531,6 +610,7 @@ func TestSymlink(t *testing.T) {
t.Skipf("skipping on %s", runtime.GOOS)
}
}
+ defer chtmpdir(t)()
from, to := "symlinktestfrom", "symlinktestto"
Remove(from) // Just in case.
file, err := Create(to)
@@ -597,6 +677,7 @@ func TestLongSymlink(t *testing.T) {
t.Skipf("skipping on %s", runtime.GOOS)
}
}
+ defer chtmpdir(t)()
s := "0123456789abcdef"
// Long, but not too long: a common limit is 255.
s = s + s + s + s + s + s + s + s + s + s + s + s + s + s + s
@@ -617,14 +698,18 @@ func TestLongSymlink(t *testing.T) {
}
func TestRename(t *testing.T) {
+ defer chtmpdir(t)()
from, to := "renamefrom", "renameto"
- Remove(to) // Just in case.
+ // Ensure we are not testing the overwrite case here.
+ Remove(from)
+ Remove(to)
+
file, err := Create(from)
if err != nil {
- t.Fatalf("open %q failed: %v", to, err)
+ t.Fatalf("open %q failed: %v", from, err)
}
if err = file.Close(); err != nil {
- t.Errorf("close %q failed: %v", to, err)
+ t.Errorf("close %q failed: %v", from, err)
}
err = Rename(from, to)
if err != nil {
@@ -637,6 +722,79 @@ func TestRename(t *testing.T) {
}
}
+func TestRenameOverwriteDest(t *testing.T) {
+ if runtime.GOOS == "plan9" {
+ t.Skip("skipping on plan9")
+ }
+ defer chtmpdir(t)()
+ from, to := "renamefrom", "renameto"
+ // Just in case.
+ Remove(from)
+ Remove(to)
+
+ toData := []byte("to")
+ fromData := []byte("from")
+
+ err := ioutil.WriteFile(to, toData, 0777)
+ if err != nil {
+ t.Fatalf("write file %q failed: %v", to, err)
+ }
+
+ err = ioutil.WriteFile(from, fromData, 0777)
+ 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)
+ }
+ defer Remove(to)
+
+ _, err = Stat(from)
+ if err == nil {
+ t.Errorf("from file %q still exists", from)
+ }
+ 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) {
+ defer chtmpdir(t)()
+ from, to := "renamefrom", "renameto"
+ // Ensure we are not testing the overwrite case here.
+ Remove(from)
+ Remove(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)
+
+ // cleanup whatever was placed in "renameto"
+ Remove(to)
+ default:
+ t.Errorf("rename %q, %q: expected %T, got %T %v", from, to, new(LinkError), err, err)
+ }
+}
+
func exec(t *testing.T, dir, cmd string, args []string, expect string) {
r, w, err := Pipe()
if err != nil {
@@ -664,18 +822,18 @@ func exec(t *testing.T, dir, cmd string, args []string, expect string) {
}
func TestStartProcess(t *testing.T) {
- switch runtime.GOOS {
- case "android", "nacl":
- t.Skipf("skipping on %s", runtime.GOOS)
- }
+ testenv.MustHaveExec(t)
var dir, cmd string
var args []string
- if runtime.GOOS == "windows" {
+ switch runtime.GOOS {
+ case "android":
+ t.Skip("android doesn't have /bin/pwd")
+ case "windows":
cmd = Getenv("COMSPEC")
dir = Getenv("SystemRoot")
args = []string{"/c", "cd"}
- } else {
+ default:
cmd = "/bin/pwd"
dir = "/"
args = []string{}
@@ -847,6 +1005,19 @@ func TestChdirAndGetwd(t *testing.T) {
dirs = []string{"/", "/system/bin"}
case "plan9":
dirs = []string{"/", "/usr"}
+ case "darwin":
+ switch runtime.GOARCH {
+ case "arm", "arm64":
+ d1, err := ioutil.TempDir("", "d1")
+ if err != nil {
+ t.Fatalf("TempDir: %v", err)
+ }
+ d2, err := ioutil.TempDir("", "d2")
+ if err != nil {
+ t.Fatalf("TempDir: %v", err)
+ }
+ dirs = []string{d1, d2}
+ }
}
oldwd := Getenv("PWD")
for mode := 0; mode < 2; mode++ {
@@ -892,6 +1063,64 @@ func TestChdirAndGetwd(t *testing.T) {
fd.Close()
}
+// Test that Chdir+Getwd is program-wide.
+func TestProgWideChdir(t *testing.T) {
+ const N = 10
+ c := make(chan bool)
+ cpwd := make(chan string)
+ for i := 0; i < N; i++ {
+ go func(i int) {
+ // Lock half the goroutines in their own operating system
+ // thread to exercise more scheduler possibilities.
+ if i%2 == 1 {
+ // On Plan 9, after calling LockOSThread, the goroutines
+ // run on different processes which don't share the working
+ // directory. This used to be an issue because Go expects
+ // the working directory to be program-wide.
+ // See issue 9428.
+ runtime.LockOSThread()
+ }
+ <-c
+ pwd, err := Getwd()
+ if err != nil {
+ t.Errorf("Getwd on goroutine %d: %v", i, err)
+ return
+ }
+ cpwd <- pwd
+ }(i)
+ }
+ oldwd, err := Getwd()
+ if err != nil {
+ t.Fatalf("Getwd: %v", err)
+ }
+ d, err := ioutil.TempDir("", "test")
+ if err != nil {
+ t.Fatalf("TempDir: %v", err)
+ }
+ defer func() {
+ if err := Chdir(oldwd); err != nil {
+ t.Fatalf("Chdir: %v", err)
+ }
+ RemoveAll(d)
+ }()
+ if err := Chdir(d); err != nil {
+ t.Fatalf("Chdir: %v", err)
+ }
+ // OS X sets TMPDIR to a symbolic link.
+ // So we resolve our working directory again before the test.
+ d, err = Getwd()
+ if err != nil {
+ t.Fatalf("Getwd: %v", err)
+ }
+ close(c)
+ for i := 0; i < N; i++ {
+ pwd := <-cpwd
+ if pwd != d {
+ t.Errorf("Getwd returned %q; want %q", pwd, d)
+ }
+ }
+}
+
func TestSeek(t *testing.T) {
f := newFile("TestSeek", t)
defer Remove(f.Name())
@@ -920,7 +1149,7 @@ func TestSeek(t *testing.T) {
if off != tt.out || err != nil {
if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 {
// Reiserfs rejects the big seeks.
- // http://code.google.com/p/go/issues/detail?id=91
+ // https://golang.org/issue/91
break
}
t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
@@ -1033,14 +1262,35 @@ func run(t *testing.T, cmd []string) string {
return output
}
+func testWindowsHostname(t *testing.T) {
+ hostname, err := Hostname()
+ if err != nil {
+ t.Fatal(err)
+ }
+ cmd := osexec.Command("hostname")
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Fatalf("Failed to execute hostname command: %v %s", err, out)
+ }
+ want := strings.Trim(string(out), "\r\n")
+ if hostname != want {
+ t.Fatalf("Hostname() = %q, want %q", hostname, want)
+ }
+}
+
func TestHostname(t *testing.T) {
// There is no other way to fetch hostname on windows, but via winapi.
// On Plan 9 it can be taken from #c/sysname as Hostname() does.
switch runtime.GOOS {
- case "android", "nacl", "plan9", "windows":
- t.Skipf("skipping on %s", runtime.GOOS)
+ case "android", "plan9":
+ t.Skipf("%s doesn't have /bin/hostname", runtime.GOOS)
+ case "windows":
+ testWindowsHostname(t)
+ return
}
+ testenv.MustHaveExec(t)
+
// Check internal Hostname() against the output of /bin/hostname.
// Allow that the internal Hostname returns a Fully Qualified Domain Name
// and the /bin/hostname only returns the first component
@@ -1115,6 +1365,7 @@ func writeFile(t *testing.T, fname string, flag int, text string) string {
}
func TestAppend(t *testing.T) {
+ defer chtmpdir(t)()
const f = "append.txt"
defer Remove(f)
s := writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
@@ -1178,6 +1429,7 @@ func TestNilProcessStateString(t *testing.T) {
}
func TestSameFile(t *testing.T) {
+ defer chtmpdir(t)()
fa, err := Create("a")
if err != nil {
t.Fatalf("Create(a): %v", err)
@@ -1297,45 +1549,11 @@ func TestReadAtEOF(t *testing.T) {
}
func testKillProcess(t *testing.T, processKiller func(p *Process)) {
- t.Skip("gccgo does not have a go command")
- switch runtime.GOOS {
- case "android", "nacl":
- t.Skipf("skipping on %s", runtime.GOOS)
- }
-
- dir, err := ioutil.TempDir("", "go-build")
- if err != nil {
- t.Fatalf("Failed to create temp directory: %v", err)
- }
- defer RemoveAll(dir)
-
- src := filepath.Join(dir, "main.go")
- f, err := Create(src)
- if err != nil {
- t.Fatalf("Failed to create %v: %v", src, err)
- }
- st := template.Must(template.New("source").Parse(`
-package main
-import "time"
-func main() {
- time.Sleep(time.Second)
-}
-`))
- err = st.Execute(f, nil)
- if err != nil {
- f.Close()
- t.Fatalf("Failed to execute template: %v", err)
- }
- f.Close()
-
- exe := filepath.Join(dir, "main.exe")
- output, err := osexec.Command("go", "build", "-o", exe, src).CombinedOutput()
- if err != nil {
- t.Fatalf("Failed to build exe %v: %v %v", exe, err, string(output))
- }
+ testenv.MustHaveExec(t)
- cmd := osexec.Command(exe)
- err = cmd.Start()
+ // Re-exec the test binary itself to emulate "sleep 1".
+ cmd := osexec.Command(Args[0], "-test.run", "TestSleep")
+ err := cmd.Start()
if err != nil {
t.Fatalf("Failed to start test process: %v", err)
}
@@ -1349,6 +1567,15 @@ func main() {
}
}
+// TestSleep emulates "sleep 1". It is a helper for testKillProcess, so we
+// don't have to rely on an external "sleep" command being available.
+func TestSleep(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping in short mode")
+ }
+ time.Sleep(time.Second)
+}
+
func TestKillStartProcess(t *testing.T) {
testKillProcess(t, func(p *Process) {
err := p.Kill()
@@ -1359,14 +1586,13 @@ func TestKillStartProcess(t *testing.T) {
}
func TestGetppid(t *testing.T) {
- switch runtime.GOOS {
- case "nacl":
- t.Skip("skipping on nacl")
- case "plan9":
+ if runtime.GOOS == "plan9" {
// TODO: golang.org/issue/8206
t.Skipf("skipping test on plan9; see issue 8206")
}
+ testenv.MustHaveExec(t)
+
if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
fmt.Print(Getppid())
Exit(0)
OpenPOWER on IntegriCloud