Home | History | Annotate | Download | only in filepath
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package filepath_test
      6 
      7 import (
      8 	"io/ioutil"
      9 	"os"
     10 	. "path/filepath"
     11 	"runtime"
     12 	"strings"
     13 	"testing"
     14 )
     15 
     16 type MatchTest struct {
     17 	pattern, s string
     18 	match      bool
     19 	err        error
     20 }
     21 
     22 var matchTests = []MatchTest{
     23 	{"abc", "abc", true, nil},
     24 	{"*", "abc", true, nil},
     25 	{"*c", "abc", true, nil},
     26 	{"a*", "a", true, nil},
     27 	{"a*", "abc", true, nil},
     28 	{"a*", "ab/c", false, nil},
     29 	{"a*/b", "abc/b", true, nil},
     30 	{"a*/b", "a/c/b", false, nil},
     31 	{"a*b*c*d*e*/f", "axbxcxdxe/f", true, nil},
     32 	{"a*b*c*d*e*/f", "axbxcxdxexxx/f", true, nil},
     33 	{"a*b*c*d*e*/f", "axbxcxdxe/xxx/f", false, nil},
     34 	{"a*b*c*d*e*/f", "axbxcxdxexxx/fff", false, nil},
     35 	{"a*b?c*x", "abxbbxdbxebxczzx", true, nil},
     36 	{"a*b?c*x", "abxbbxdbxebxczzy", false, nil},
     37 	{"ab[c]", "abc", true, nil},
     38 	{"ab[b-d]", "abc", true, nil},
     39 	{"ab[e-g]", "abc", false, nil},
     40 	{"ab[^c]", "abc", false, nil},
     41 	{"ab[^b-d]", "abc", false, nil},
     42 	{"ab[^e-g]", "abc", true, nil},
     43 	{"a\\*b", "a*b", true, nil},
     44 	{"a\\*b", "ab", false, nil},
     45 	{"a?b", "ab", true, nil},
     46 	{"a[^a]b", "ab", true, nil},
     47 	{"a???b", "ab", false, nil},
     48 	{"a[^a][^a][^a]b", "ab", false, nil},
     49 	{"[a-]*", "", true, nil},
     50 	{"*[a-]", "A", false, nil},
     51 	{"a?b", "a/b", false, nil},
     52 	{"a*b", "a/b", false, nil},
     53 	{"[\\]a]", "]", true, nil},
     54 	{"[\\-]", "-", true, nil},
     55 	{"[x\\-]", "x", true, nil},
     56 	{"[x\\-]", "-", true, nil},
     57 	{"[x\\-]", "z", false, nil},
     58 	{"[\\-x]", "x", true, nil},
     59 	{"[\\-x]", "-", true, nil},
     60 	{"[\\-x]", "a", false, nil},
     61 	{"[]a]", "]", false, ErrBadPattern},
     62 	{"[-]", "-", false, ErrBadPattern},
     63 	{"[x-]", "x", false, ErrBadPattern},
     64 	{"[x-]", "-", false, ErrBadPattern},
     65 	{"[x-]", "z", false, ErrBadPattern},
     66 	{"[-x]", "x", false, ErrBadPattern},
     67 	{"[-x]", "-", false, ErrBadPattern},
     68 	{"[-x]", "a", false, ErrBadPattern},
     69 	{"\\", "a", false, ErrBadPattern},
     70 	{"[a-b-c]", "a", false, ErrBadPattern},
     71 	{"[", "a", false, ErrBadPattern},
     72 	{"[^", "a", false, ErrBadPattern},
     73 	{"[^bc", "a", false, ErrBadPattern},
     74 	{"a[", "a", false, nil},
     75 	{"a[", "ab", false, ErrBadPattern},
     76 	{"*x", "xxx", true, nil},
     77 }
     78 
     79 func errp(e error) string {
     80 	if e == nil {
     81 		return "<nil>"
     82 	}
     83 	return e.Error()
     84 }
     85 
     86 func TestMatch(t *testing.T) {
     87 	for _, tt := range matchTests {
     88 		pattern := tt.pattern
     89 		s := tt.s
     90 		if runtime.GOOS == "windows" {
     91 			if strings.Index(pattern, "\\") >= 0 {
     92 				// no escape allowed on windows.
     93 				continue
     94 			}
     95 			pattern = Clean(pattern)
     96 			s = Clean(s)
     97 		}
     98 		ok, err := Match(pattern, s)
     99 		if ok != tt.match || err != tt.err {
    100 			t.Errorf("Match(%#q, %#q) = %v, %q want %v, %q", pattern, s, ok, errp(err), tt.match, errp(tt.err))
    101 		}
    102 	}
    103 }
    104 
    105 // contains returns true if vector contains the string s.
    106 func contains(vector []string, s string) bool {
    107 	for _, elem := range vector {
    108 		if elem == s {
    109 			return true
    110 		}
    111 	}
    112 	return false
    113 }
    114 
    115 var globTests = []struct {
    116 	pattern, result string
    117 }{
    118 	{"match.go", "match.go"},
    119 	{"mat?h.go", "match.go"},
    120 	{"*", "match.go"},
    121 	{"../*/match.go", "../filepath/match.go"},
    122 }
    123 
    124 func TestGlob(t *testing.T) {
    125 	for _, tt := range globTests {
    126 		pattern := tt.pattern
    127 		result := tt.result
    128 		if runtime.GOOS == "windows" {
    129 			pattern = Clean(pattern)
    130 			result = Clean(result)
    131 		}
    132 		matches, err := Glob(pattern)
    133 		if err != nil {
    134 			t.Errorf("Glob error for %q: %s", pattern, err)
    135 			continue
    136 		}
    137 		if !contains(matches, result) {
    138 			t.Errorf("Glob(%#q) = %#v want %v", pattern, matches, result)
    139 		}
    140 	}
    141 	for _, pattern := range []string{"no_match", "../*/no_match"} {
    142 		matches, err := Glob(pattern)
    143 		if err != nil {
    144 			t.Errorf("Glob error for %q: %s", pattern, err)
    145 			continue
    146 		}
    147 		if len(matches) != 0 {
    148 			t.Errorf("Glob(%#q) = %#v want []", pattern, matches)
    149 		}
    150 	}
    151 }
    152 
    153 func TestGlobError(t *testing.T) {
    154 	_, err := Glob("[7]")
    155 	if err != nil {
    156 		t.Error("expected error for bad pattern; got none")
    157 	}
    158 }
    159 
    160 var globSymlinkTests = []struct {
    161 	path, dest string
    162 	brokenLink bool
    163 }{
    164 	{"test1", "link1", false},
    165 	{"test2", "link2", true},
    166 }
    167 
    168 func TestGlobSymlink(t *testing.T) {
    169 	switch runtime.GOOS {
    170 	case "nacl", "plan9":
    171 		t.Skipf("skipping on %s", runtime.GOOS)
    172 	case "windows":
    173 		if !supportsSymlinks {
    174 			t.Skipf("skipping on %s", runtime.GOOS)
    175 		}
    176 
    177 	}
    178 
    179 	tmpDir, err := ioutil.TempDir("", "globsymlink")
    180 	if err != nil {
    181 		t.Fatal("creating temp dir:", err)
    182 	}
    183 	defer os.RemoveAll(tmpDir)
    184 
    185 	for _, tt := range globSymlinkTests {
    186 		path := Join(tmpDir, tt.path)
    187 		dest := Join(tmpDir, tt.dest)
    188 		f, err := os.Create(path)
    189 		if err != nil {
    190 			t.Fatal(err)
    191 		}
    192 		if err := f.Close(); err != nil {
    193 			t.Fatal(err)
    194 		}
    195 		err = os.Symlink(path, dest)
    196 		if err != nil {
    197 			t.Fatal(err)
    198 		}
    199 		if tt.brokenLink {
    200 			// Break the symlink.
    201 			os.Remove(path)
    202 		}
    203 		matches, err := Glob(dest)
    204 		if err != nil {
    205 			t.Errorf("GlobSymlink error for %q: %s", dest, err)
    206 		}
    207 		if !contains(matches, dest) {
    208 			t.Errorf("Glob(%#q) = %#v want %v", dest, matches, dest)
    209 		}
    210 	}
    211 }
    212