OSDN Git Service

Update Go library to last weekly.
[pf3gnuchains/gcc-fork.git] / libgo / go / path / filepath / path_test.go
index 0249af4..f8e055b 100644 (file)
@@ -66,9 +66,35 @@ var cleantests = []PathTest{
        {"abc/../../././../def", "../../def"},
 }
 
+var wincleantests = []PathTest{
+       {`c:`, `c:.`},
+       {`c:\`, `c:\`},
+       {`c:\abc`, `c:\abc`},
+       {`c:abc\..\..\.\.\..\def`, `c:..\..\def`},
+       {`c:\abc\def\..\..`, `c:\`},
+       {`c:\..\abc`, `c:\abc`},
+       {`c:..\abc`, `c:..\abc`},
+       {`\`, `\`},
+       {`/`, `\`},
+       {`\\i\..\c$`, `\c$`},
+       {`\\i\..\i\c$`, `\i\c$`},
+       {`\\i\..\I\c$`, `\I\c$`},
+       {`\\host\share\foo\..\bar`, `\\host\share\bar`},
+       {`//host/share/foo/../baz`, `\\host\share\baz`},
+       {`\\a\b\..\c`, `\\a\b\c`},
+       {`\\a\b`, `\\a\b`},
+}
+
 func TestClean(t *testing.T) {
-       for _, test := range cleantests {
-               if s := filepath.ToSlash(filepath.Clean(test.path)); s != test.result {
+       tests := cleantests
+       if runtime.GOOS == "windows" {
+               for i := range tests {
+                       tests[i].result = filepath.FromSlash(tests[i].result)
+               }
+               tests = append(tests, wincleantests...)
+       }
+       for _, test := range tests {
+               if s := filepath.Clean(test.path); s != test.result {
                        t.Errorf("Clean(%q) = %q, want %q", test.path, s, test.result)
                }
        }
@@ -127,9 +153,25 @@ var unixsplittests = []SplitTest{
        {"/", "/", ""},
 }
 
+var winsplittests = []SplitTest{
+       {`c:`, `c:`, ``},
+       {`c:/`, `c:/`, ``},
+       {`c:/foo`, `c:/`, `foo`},
+       {`c:/foo/bar`, `c:/foo/`, `bar`},
+       {`//host/share`, `//host/share`, ``},
+       {`//host/share/`, `//host/share/`, ``},
+       {`//host/share/foo`, `//host/share/`, `foo`},
+       {`\\host\share`, `\\host\share`, ``},
+       {`\\host\share\`, `\\host\share\`, ``},
+       {`\\host\share\foo`, `\\host\share\`, `foo`},
+}
+
 func TestSplit(t *testing.T) {
        var splittests []SplitTest
        splittests = unixsplittests
+       if runtime.GOOS == "windows" {
+               splittests = append(splittests, winsplittests...)
+       }
        for _, test := range splittests {
                if d, f := filepath.Split(test.path); d != test.dir || f != test.file {
                        t.Errorf("Split(%q) = %q, %q, want %q, %q", test.path, d, f, test.dir, test.file)
@@ -167,6 +209,8 @@ var winjointests = []JoinTest{
        {[]string{`C:\Windows\`, ``}, `C:\Windows`},
        {[]string{`C:\`, `Windows`}, `C:\Windows`},
        {[]string{`C:`, `Windows`}, `C:\Windows`},
+       {[]string{`\\host\share`, `foo`}, `\\host\share\foo`},
+       {[]string{`//host/share`, `foo/bar`}, `\\host\share\foo\bar`},
 }
 
 // join takes a []string and passes it to Join.
@@ -248,7 +292,7 @@ func walkTree(n *Node, path string, f func(path string, n *Node)) {
 func makeTree(t *testing.T) {
        walkTree(tree, tree.name, func(path string, n *Node) {
                if n.entries == nil {
-                       fd, err := os.Open(path, os.O_CREAT, 0660)
+                       fd, err := os.Create(path)
                        if err != nil {
                                t.Errorf("makeTree: %v", err)
                        }
@@ -261,9 +305,9 @@ func makeTree(t *testing.T) {
 
 func markTree(n *Node) { walkTree(n, "", func(path string, n *Node) { n.mark++ }) }
 
-func checkMarks(t *testing.T) {
+func checkMarks(t *testing.T, report bool) {
        walkTree(tree, tree.name, func(path string, n *Node) {
-               if n.mark != 1 {
+               if n.mark != 1 && report {
                        t.Errorf("node %s mark = %d; expected 1", path, n.mark)
                }
                n.mark = 0
@@ -271,87 +315,93 @@ func checkMarks(t *testing.T) {
 }
 
 // Assumes that each node name is unique. Good enough for a test.
-func mark(name string) {
-       name = filepath.ToSlash(name)
+// If clear is true, any incoming error is cleared before return. The errors
+// are always accumulated, though.
+func mark(path string, info *os.FileInfo, err os.Error, errors *[]os.Error, clear bool) os.Error {
+       if err != nil {
+               *errors = append(*errors, err)
+               if clear {
+                       return nil
+               }
+               return err
+       }
        walkTree(tree, tree.name, func(path string, n *Node) {
-               if n.name == name {
+               if n.name == info.Name {
                        n.mark++
                }
        })
-}
-
-type TestVisitor struct{}
-
-func (v *TestVisitor) VisitDir(path string, f *os.FileInfo) bool {
-       mark(f.Name)
-       return true
-}
-
-func (v *TestVisitor) VisitFile(path string, f *os.FileInfo) {
-       mark(f.Name)
+       return nil
 }
 
 func TestWalk(t *testing.T) {
-       // TODO(brainman): enable test once Windows version is implemented.
-       if runtime.GOOS == "windows" {
-               return
-       }
        makeTree(t)
-
-       // 1) ignore error handling, expect none
-       v := &TestVisitor{}
-       filepath.Walk(tree.name, v, nil)
-       checkMarks(t)
-
-       // 2) handle errors, expect none
-       errors := make(chan os.Error, 64)
-       filepath.Walk(tree.name, v, errors)
-       select {
-       case err := <-errors:
+       errors := make([]os.Error, 0, 10)
+       clear := true
+       markFn := func(path string, info *os.FileInfo, err os.Error) os.Error {
+               return mark(path, info, err, &errors, clear)
+       }
+       // Expect no errors.
+       err := filepath.Walk(tree.name, markFn)
+       if err != nil {
                t.Errorf("no error expected, found: %s", err)
-       default:
-               // ok
        }
-       checkMarks(t)
+       if len(errors) != 0 {
+               t.Errorf("unexpected errors: %s", errors)
+       }
+       checkMarks(t, true)
+       errors = errors[0:0]
 
-       if os.Getuid() > 0 {
+       // Test permission errors.  Only possible if we're not root
+       // and only on some file systems (AFS, FAT).  To avoid errors during
+       // all.bash on those file systems, skip during gotest -short.
+       if os.Getuid() > 0 && !testing.Short() {
                // introduce 2 errors: chmod top-level directories to 0
                os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0)
                os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0)
+
+               // 3) capture errors, expect two.
                // mark respective subtrees manually
                markTree(tree.entries[1])
                markTree(tree.entries[3])
                // correct double-marking of directory itself
                tree.entries[1].mark--
                tree.entries[3].mark--
+               err := filepath.Walk(tree.name, markFn)
+               if err != nil {
+                       t.Errorf("expected no error return from Walk, %s", err)
+               }
+               if len(errors) != 2 {
+                       t.Errorf("expected 2 errors, got %d: %s", len(errors), errors)
+               }
+               // the inaccessible subtrees were marked manually
+               checkMarks(t, true)
+               errors = errors[0:0]
 
-               // 3) handle errors, expect two
-               errors = make(chan os.Error, 64)
-               os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0)
-               filepath.Walk(tree.name, v, errors)
-       Loop:
-               for i := 1; i <= 2; i++ {
-                       select {
-                       case <-errors:
-                               // ok
-                       default:
-                               t.Errorf("%d. error expected, none found", i)
-                               break Loop
-                       }
+               // 4) capture errors, stop after first error.
+               // mark respective subtrees manually
+               markTree(tree.entries[1])
+               markTree(tree.entries[3])
+               // correct double-marking of directory itself
+               tree.entries[1].mark--
+               tree.entries[3].mark--
+               clear = false // error will stop processing
+               err = filepath.Walk(tree.name, markFn)
+               if err == nil {
+                       t.Errorf("expected error return from Walk")
                }
-               select {
-               case err := <-errors:
-                       t.Errorf("only two errors expected, found 3rd: %v", err)
-               default:
-                       // ok
+               if len(errors) != 1 {
+                       t.Errorf("expected 1 error, got %d: %s", len(errors), errors)
                }
                // the inaccessible subtrees were marked manually
-               checkMarks(t)
+               checkMarks(t, false)
+               errors = errors[0:0]
+
+               // restore permissions
+               os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0770)
+               os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0770)
        }
 
        // cleanup
-       os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0770)
-       os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0770)
        if err := os.RemoveAll(tree.name); err != nil {
                t.Errorf("removeTree: %v", err)
        }
@@ -399,16 +449,32 @@ var winisabstests = []IsAbsTest{
        {`C:\`, true},
        {`c\`, false},
        {`c::`, false},
-       {`/`, true},
-       {`\`, true},
-       {`\Windows`, true},
+       {`c:`, false},
+       {`/`, false},
+       {`\`, false},
+       {`\Windows`, false},
+       {`c:a\b`, false},
+       {`\\host\share\foo`, true},
+       {`//host/share/foo/bar`, true},
 }
 
 func TestIsAbs(t *testing.T) {
+       var tests []IsAbsTest
        if runtime.GOOS == "windows" {
-               isabstests = append(isabstests, winisabstests...)
+               tests = append(tests, winisabstests...)
+               // All non-windows tests should fail, because they have no volume letter.
+               for _, test := range isabstests {
+                       tests = append(tests, IsAbsTest{test.path, false})
+               }
+               // All non-windows test should work as intended if prefixed with volume letter.
+               for _, test := range isabstests {
+                       tests = append(tests, IsAbsTest{"c:" + test.path, test.isAbs})
+               }
+       } else {
+               tests = isabstests
        }
-       for _, test := range isabstests {
+
+       for _, test := range tests {
                if r := filepath.IsAbs(test.path); r != test.isAbs {
                        t.Errorf("IsAbs(%q) = %v, want %v", test.path, r, test.isAbs)
                }
@@ -439,31 +505,48 @@ var EvalSymlinksTests = []EvalSymlinksTest{
        {"test/link2/link3/test", "test"},
 }
 
-func TestEvalSymlinks(t *testing.T) {
-       // Symlinks are not supported under windows.
-       if runtime.GOOS == "windows" {
-               return
+var EvalSymlinksAbsWindowsTests = []EvalSymlinksTest{
+       {`c:\`, `c:\`},
+}
+
+func testEvalSymlinks(t *testing.T, tests []EvalSymlinksTest) {
+       for _, d := range tests {
+               if p, err := filepath.EvalSymlinks(d.path); err != nil {
+                       t.Errorf("EvalSymlinks(%q) error: %v", d.path, err)
+               } else if filepath.Clean(p) != filepath.Clean(d.dest) {
+                       t.Errorf("EvalSymlinks(%q)=%q, want %q", d.path, p, d.dest)
+               }
        }
+}
+
+func TestEvalSymlinks(t *testing.T) {
        defer os.RemoveAll("test")
        for _, d := range EvalSymlinksTestDirs {
                var err os.Error
                if d.dest == "" {
                        err = os.Mkdir(d.path, 0755)
                } else {
-                       err = os.Symlink(d.dest, d.path)
+                       if runtime.GOOS != "windows" {
+                               err = os.Symlink(d.dest, d.path)
+                       }
                }
                if err != nil {
                        t.Fatal(err)
                }
        }
-       // relative
-       for _, d := range EvalSymlinksTests {
-               if p, err := filepath.EvalSymlinks(d.path); err != nil {
-                       t.Errorf("EvalSymlinks(%v) error: %v", d.path, err)
-               } else if p != d.dest {
-                       t.Errorf("EvalSymlinks(%v)=%v, want %v", d.path, p, d.dest)
+       var tests []EvalSymlinksTest
+       if runtime.GOOS == "windows" {
+               for _, d := range EvalSymlinksTests {
+                       if d.path == d.dest {
+                               // will test only real files and directories
+                               tests = append(tests, d)
+                       }
                }
+       } else {
+               tests = EvalSymlinksTests
        }
+       // relative
+       testEvalSymlinks(t, tests)
        // absolute
 /* These tests do not work in the gccgo test environment.
        goroot, err := filepath.EvalSymlinks(os.Getenv("GOROOT"))
@@ -471,16 +554,176 @@ func TestEvalSymlinks(t *testing.T) {
                t.Fatalf("EvalSymlinks(%q) error: %v", os.Getenv("GOROOT"), err)
        }
        testroot := filepath.Join(goroot, "src", "pkg", "path", "filepath")
-       for _, d := range EvalSymlinksTests {
-               a := EvalSymlinksTest{
-                       filepath.Join(testroot, d.path),
-                       filepath.Join(testroot, d.dest),
+       for i, d := range tests {
+               tests[i].path = filepath.Join(testroot, d.path)
+               tests[i].dest = filepath.Join(testroot, d.dest)
+       }
+       if runtime.GOOS == "windows" {
+               for _, d := range EvalSymlinksAbsWindowsTests {
+                       tests = append(tests, d)
                }
-               if p, err := filepath.EvalSymlinks(a.path); err != nil {
-                       t.Errorf("EvalSymlinks(%v) error: %v", a.path, err)
-               } else if p != a.dest {
-                       t.Errorf("EvalSymlinks(%v)=%v, want %v", a.path, p, a.dest)
+       }
+       testEvalSymlinks(t, tests)
+*/
+}
+
+/* These tests do not work in the gccgo test environment.
+
+// Test paths relative to $GOROOT/src
+var abstests = []string{
+       "../AUTHORS",
+       "pkg/../../AUTHORS",
+       "Make.pkg",
+       "pkg/Makefile",
+       ".",
+       "$GOROOT/src/Make.pkg",
+       "$GOROOT/src/../src/Make.pkg",
+       "$GOROOT/misc/cgo",
+       "$GOROOT",
+}
+
+func TestAbs(t *testing.T) {
+       oldwd, err := os.Getwd()
+       if err != nil {
+               t.Fatal("Getwd failed: " + err.String())
+       }
+       defer os.Chdir(oldwd)
+       goroot := os.Getenv("GOROOT")
+       cwd := filepath.Join(goroot, "src")
+       os.Chdir(cwd)
+       for _, path := range abstests {
+               path = strings.Replace(path, "$GOROOT", goroot, -1)
+               info, err := os.Stat(path)
+               if err != nil {
+                       t.Errorf("%s: %s", path, err)
+               }
+
+               abspath, err := filepath.Abs(path)
+               if err != nil {
+                       t.Errorf("Abs(%q) error: %v", path, err)
+               }
+               absinfo, err := os.Stat(abspath)
+               if err != nil || absinfo.Ino != info.Ino {
+                       t.Errorf("Abs(%q)=%q, not the same file", path, abspath)
+               }
+               if !filepath.IsAbs(abspath) {
+                       t.Errorf("Abs(%q)=%q, not an absolute path", path, abspath)
+               }
+               if filepath.IsAbs(path) && abspath != filepath.Clean(path) {
+                       t.Errorf("Abs(%q)=%q, isn't clean", path, abspath)
                }
        }
+}
+
 */
+
+type RelTests struct {
+       root, path, want string
+}
+
+var reltests = []RelTests{
+       {"a/b", "a/b", "."},
+       {"a/b/.", "a/b", "."},
+       {"a/b", "a/b/.", "."},
+       {"./a/b", "a/b", "."},
+       {"a/b", "./a/b", "."},
+       {"ab/cd", "ab/cde", "../cde"},
+       {"ab/cd", "ab/c", "../c"},
+       {"a/b", "a/b/c/d", "c/d"},
+       {"a/b", "a/b/../c", "../c"},
+       {"a/b/../c", "a/b", "../b"},
+       {"a/b/c", "a/c/d", "../../c/d"},
+       {"a/b", "c/d", "../../c/d"},
+       {"../../a/b", "../../a/b/c/d", "c/d"},
+       {"/a/b", "/a/b", "."},
+       {"/a/b/.", "/a/b", "."},
+       {"/a/b", "/a/b/.", "."},
+       {"/ab/cd", "/ab/cde", "../cde"},
+       {"/ab/cd", "/ab/c", "../c"},
+       {"/a/b", "/a/b/c/d", "c/d"},
+       {"/a/b", "/a/b/../c", "../c"},
+       {"/a/b/../c", "/a/b", "../b"},
+       {"/a/b/c", "/a/c/d", "../../c/d"},
+       {"/a/b", "/c/d", "../../c/d"},
+       {"/../../a/b", "/../../a/b/c/d", "c/d"},
+       {".", "a/b", "a/b"},
+       {".", "..", ".."},
+
+       // can't do purely lexically
+       {"..", ".", "err"},
+       {"..", "a", "err"},
+       {"../..", "..", "err"},
+       {"a", "/a", "err"},
+       {"/a", "a", "err"},
+}
+
+var winreltests = []RelTests{
+       {`C:a\b\c`, `C:a/b/d`, `..\d`},
+       {`C:\`, `D:\`, `err`},
+       {`C:`, `D:`, `err`},
+}
+
+func TestRel(t *testing.T) {
+       tests := append([]RelTests{}, reltests...)
+       if runtime.GOOS == "windows" {
+               for i := range tests {
+                       tests[i].want = filepath.FromSlash(tests[i].want)
+               }
+               tests = append(tests, winreltests...)
+       }
+       for _, test := range tests {
+               got, err := filepath.Rel(test.root, test.path)
+               if test.want == "err" {
+                       if err == nil {
+                               t.Errorf("Rel(%q, %q)=%q, want error", test.root, test.path, got)
+                       }
+                       continue
+               }
+               if err != nil {
+                       t.Errorf("Rel(%q, %q): want %q, got error: %s", test.root, test.path, test.want, err)
+               }
+               if got != test.want {
+                       t.Errorf("Rel(%q, %q)=%q, want %q", test.root, test.path, got, test.want)
+               }
+       }
+}
+
+type VolumeNameTest struct {
+       path string
+       vol  string
+}
+
+var volumenametests = []VolumeNameTest{
+       {`c:/foo/bar`, `c:`},
+       {`c:`, `c:`},
+       {``, ``},
+       {`\\\host`, ``},
+       {`\\\host\`, ``},
+       {`\\\host\share`, ``},
+       {`\\\host\\share`, ``},
+       {`\\host`, ``},
+       {`//host`, ``},
+       {`\\host\`, ``},
+       {`//host/`, ``},
+       {`\\host\share`, `\\host\share`},
+       {`//host/share`, `//host/share`},
+       {`\\host\share\`, `\\host\share`},
+       {`//host/share/`, `//host/share`},
+       {`\\host\share\foo`, `\\host\share`},
+       {`//host/share/foo`, `//host/share`},
+       {`\\host\share\\foo\\\bar\\\\baz`, `\\host\share`},
+       {`//host/share//foo///bar////baz`, `//host/share`},
+       {`\\host\share\foo\..\bar`, `\\host\share`},
+       {`//host/share/foo/../bar`, `//host/share`},
+}
+
+func TestVolumeName(t *testing.T) {
+       if runtime.GOOS != "windows" {
+               return
+       }
+       for _, v := range volumenametests {
+               if vol := filepath.VolumeName(v.path); vol != v.vol {
+                       t.Errorf("VolumeName(%q)=%q, want %q", v.path, vol, v.vol)
+               }
+       }
 }