github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/pkg/fileutils/fileutils_test.go (about)

     1  package fileutils // import "github.com/demonoid81/moby/pkg/fileutils"
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path"
     8  	"path/filepath"
     9  	"runtime"
    10  	"strings"
    11  	"testing"
    12  
    13  	"gotest.tools/v3/assert"
    14  	is "gotest.tools/v3/assert/cmp"
    15  )
    16  
    17  // CopyFile with invalid src
    18  func TestCopyFileWithInvalidSrc(t *testing.T) {
    19  	tempFolder, err := ioutil.TempDir("", "docker-fileutils-test") // #nosec G303
    20  	defer os.RemoveAll(tempFolder)
    21  	if err != nil {
    22  		t.Fatal(err)
    23  	}
    24  	bytes, err := CopyFile("/invalid/file/path", path.Join(tempFolder, "dest"))
    25  	if err == nil {
    26  		t.Fatal("Should have fail to copy an invalid src file")
    27  	}
    28  	if bytes != 0 {
    29  		t.Fatal("Should have written 0 bytes")
    30  	}
    31  
    32  }
    33  
    34  // CopyFile with invalid dest
    35  func TestCopyFileWithInvalidDest(t *testing.T) {
    36  	tempFolder, err := ioutil.TempDir("", "docker-fileutils-test")
    37  	defer os.RemoveAll(tempFolder)
    38  	if err != nil {
    39  		t.Fatal(err)
    40  	}
    41  	src := path.Join(tempFolder, "file")
    42  	err = ioutil.WriteFile(src, []byte("content"), 0740)
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  	bytes, err := CopyFile(src, path.Join(tempFolder, "/invalid/dest/path"))
    47  	if err == nil {
    48  		t.Fatal("Should have fail to copy an invalid src file")
    49  	}
    50  	if bytes != 0 {
    51  		t.Fatal("Should have written 0 bytes")
    52  	}
    53  
    54  }
    55  
    56  // CopyFile with same src and dest
    57  func TestCopyFileWithSameSrcAndDest(t *testing.T) {
    58  	tempFolder, err := ioutil.TempDir("", "docker-fileutils-test")
    59  	defer os.RemoveAll(tempFolder)
    60  	if err != nil {
    61  		t.Fatal(err)
    62  	}
    63  	file := path.Join(tempFolder, "file")
    64  	err = ioutil.WriteFile(file, []byte("content"), 0740)
    65  	if err != nil {
    66  		t.Fatal(err)
    67  	}
    68  	bytes, err := CopyFile(file, file)
    69  	if err != nil {
    70  		t.Fatal(err)
    71  	}
    72  	if bytes != 0 {
    73  		t.Fatal("Should have written 0 bytes as it is the same file.")
    74  	}
    75  }
    76  
    77  // CopyFile with same src and dest but path is different and not clean
    78  func TestCopyFileWithSameSrcAndDestWithPathNameDifferent(t *testing.T) {
    79  	tempFolder, err := ioutil.TempDir("", "docker-fileutils-test")
    80  	defer os.RemoveAll(tempFolder)
    81  	if err != nil {
    82  		t.Fatal(err)
    83  	}
    84  	testFolder := path.Join(tempFolder, "test")
    85  	err = os.MkdirAll(testFolder, 0740)
    86  	if err != nil {
    87  		t.Fatal(err)
    88  	}
    89  	file := path.Join(testFolder, "file")
    90  	sameFile := testFolder + "/../test/file"
    91  	err = ioutil.WriteFile(file, []byte("content"), 0740)
    92  	if err != nil {
    93  		t.Fatal(err)
    94  	}
    95  	bytes, err := CopyFile(file, sameFile)
    96  	if err != nil {
    97  		t.Fatal(err)
    98  	}
    99  	if bytes != 0 {
   100  		t.Fatal("Should have written 0 bytes as it is the same file.")
   101  	}
   102  }
   103  
   104  func TestCopyFile(t *testing.T) {
   105  	tempFolder, err := ioutil.TempDir("", "docker-fileutils-test")
   106  	defer os.RemoveAll(tempFolder)
   107  	if err != nil {
   108  		t.Fatal(err)
   109  	}
   110  	src := path.Join(tempFolder, "src")
   111  	dest := path.Join(tempFolder, "dest")
   112  	ioutil.WriteFile(src, []byte("content"), 0777)
   113  	ioutil.WriteFile(dest, []byte("destContent"), 0777)
   114  	bytes, err := CopyFile(src, dest)
   115  	if err != nil {
   116  		t.Fatal(err)
   117  	}
   118  	if bytes != 7 {
   119  		t.Fatalf("Should have written %d bytes but wrote %d", 7, bytes)
   120  	}
   121  	actual, err := ioutil.ReadFile(dest)
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  	if string(actual) != "content" {
   126  		t.Fatalf("Dest content was '%s', expected '%s'", string(actual), "content")
   127  	}
   128  }
   129  
   130  // Reading a symlink to a directory must return the directory
   131  func TestReadSymlinkedDirectoryExistingDirectory(t *testing.T) {
   132  	// TODO Windows: Port this test
   133  	if runtime.GOOS == "windows" {
   134  		t.Skip("Needs porting to Windows")
   135  	}
   136  	var err error
   137  	if err = os.Mkdir("/tmp/testReadSymlinkToExistingDirectory", 0777); err != nil {
   138  		t.Errorf("failed to create directory: %s", err)
   139  	}
   140  
   141  	if err = os.Symlink("/tmp/testReadSymlinkToExistingDirectory", "/tmp/dirLinkTest"); err != nil {
   142  		t.Errorf("failed to create symlink: %s", err)
   143  	}
   144  
   145  	var path string
   146  	if path, err = ReadSymlinkedDirectory("/tmp/dirLinkTest"); err != nil {
   147  		t.Fatalf("failed to read symlink to directory: %s", err)
   148  	}
   149  
   150  	if path != "/tmp/testReadSymlinkToExistingDirectory" {
   151  		t.Fatalf("symlink returned unexpected directory: %s", path)
   152  	}
   153  
   154  	if err = os.Remove("/tmp/testReadSymlinkToExistingDirectory"); err != nil {
   155  		t.Errorf("failed to remove temporary directory: %s", err)
   156  	}
   157  
   158  	if err = os.Remove("/tmp/dirLinkTest"); err != nil {
   159  		t.Errorf("failed to remove symlink: %s", err)
   160  	}
   161  }
   162  
   163  // Reading a non-existing symlink must fail
   164  func TestReadSymlinkedDirectoryNonExistingSymlink(t *testing.T) {
   165  	var path string
   166  	var err error
   167  	if path, err = ReadSymlinkedDirectory("/tmp/test/foo/Non/ExistingPath"); err == nil {
   168  		t.Fatalf("error expected for non-existing symlink")
   169  	}
   170  
   171  	if path != "" {
   172  		t.Fatalf("expected empty path, but '%s' was returned", path)
   173  	}
   174  }
   175  
   176  // Reading a symlink to a file must fail
   177  func TestReadSymlinkedDirectoryToFile(t *testing.T) {
   178  	// TODO Windows: Port this test
   179  	if runtime.GOOS == "windows" {
   180  		t.Skip("Needs porting to Windows")
   181  	}
   182  	var err error
   183  	var file *os.File
   184  
   185  	// #nosec G303
   186  	if file, err = os.Create("/tmp/testReadSymlinkToFile"); err != nil {
   187  		t.Fatalf("failed to create file: %s", err)
   188  	}
   189  
   190  	file.Close()
   191  
   192  	if err = os.Symlink("/tmp/testReadSymlinkToFile", "/tmp/fileLinkTest"); err != nil {
   193  		t.Errorf("failed to create symlink: %s", err)
   194  	}
   195  
   196  	var path string
   197  	if path, err = ReadSymlinkedDirectory("/tmp/fileLinkTest"); err == nil {
   198  		t.Fatalf("ReadSymlinkedDirectory on a symlink to a file should've failed")
   199  	}
   200  
   201  	if path != "" {
   202  		t.Fatalf("path should've been empty: %s", path)
   203  	}
   204  
   205  	if err = os.Remove("/tmp/testReadSymlinkToFile"); err != nil {
   206  		t.Errorf("failed to remove file: %s", err)
   207  	}
   208  
   209  	if err = os.Remove("/tmp/fileLinkTest"); err != nil {
   210  		t.Errorf("failed to remove symlink: %s", err)
   211  	}
   212  }
   213  
   214  func TestWildcardMatches(t *testing.T) {
   215  	match, _ := Matches("fileutils.go", []string{"*"})
   216  	if !match {
   217  		t.Errorf("failed to get a wildcard match, got %v", match)
   218  	}
   219  }
   220  
   221  // A simple pattern match should return true.
   222  func TestPatternMatches(t *testing.T) {
   223  	match, _ := Matches("fileutils.go", []string{"*.go"})
   224  	if !match {
   225  		t.Errorf("failed to get a match, got %v", match)
   226  	}
   227  }
   228  
   229  // An exclusion followed by an inclusion should return true.
   230  func TestExclusionPatternMatchesPatternBefore(t *testing.T) {
   231  	match, _ := Matches("fileutils.go", []string{"!fileutils.go", "*.go"})
   232  	if !match {
   233  		t.Errorf("failed to get true match on exclusion pattern, got %v", match)
   234  	}
   235  }
   236  
   237  // A folder pattern followed by an exception should return false.
   238  func TestPatternMatchesFolderExclusions(t *testing.T) {
   239  	match, _ := Matches("docs/README.md", []string{"docs", "!docs/README.md"})
   240  	if match {
   241  		t.Errorf("failed to get a false match on exclusion pattern, got %v", match)
   242  	}
   243  }
   244  
   245  // A folder pattern followed by an exception should return false.
   246  func TestPatternMatchesFolderWithSlashExclusions(t *testing.T) {
   247  	match, _ := Matches("docs/README.md", []string{"docs/", "!docs/README.md"})
   248  	if match {
   249  		t.Errorf("failed to get a false match on exclusion pattern, got %v", match)
   250  	}
   251  }
   252  
   253  // A folder pattern followed by an exception should return false.
   254  func TestPatternMatchesFolderWildcardExclusions(t *testing.T) {
   255  	match, _ := Matches("docs/README.md", []string{"docs/*", "!docs/README.md"})
   256  	if match {
   257  		t.Errorf("failed to get a false match on exclusion pattern, got %v", match)
   258  	}
   259  }
   260  
   261  // A pattern followed by an exclusion should return false.
   262  func TestExclusionPatternMatchesPatternAfter(t *testing.T) {
   263  	match, _ := Matches("fileutils.go", []string{"*.go", "!fileutils.go"})
   264  	if match {
   265  		t.Errorf("failed to get false match on exclusion pattern, got %v", match)
   266  	}
   267  }
   268  
   269  // A filename evaluating to . should return false.
   270  func TestExclusionPatternMatchesWholeDirectory(t *testing.T) {
   271  	match, _ := Matches(".", []string{"*.go"})
   272  	if match {
   273  		t.Errorf("failed to get false match on ., got %v", match)
   274  	}
   275  }
   276  
   277  // A single ! pattern should return an error.
   278  func TestSingleExclamationError(t *testing.T) {
   279  	_, err := Matches("fileutils.go", []string{"!"})
   280  	if err == nil {
   281  		t.Errorf("failed to get an error for a single exclamation point, got %v", err)
   282  	}
   283  }
   284  
   285  // Matches with no patterns
   286  func TestMatchesWithNoPatterns(t *testing.T) {
   287  	matches, err := Matches("/any/path/there", []string{})
   288  	if err != nil {
   289  		t.Fatal(err)
   290  	}
   291  	if matches {
   292  		t.Fatalf("Should not have match anything")
   293  	}
   294  }
   295  
   296  // Matches with malformed patterns
   297  func TestMatchesWithMalformedPatterns(t *testing.T) {
   298  	matches, err := Matches("/any/path/there", []string{"["})
   299  	if err == nil {
   300  		t.Fatal("Should have failed because of a malformed syntax in the pattern")
   301  	}
   302  	if matches {
   303  		t.Fatalf("Should not have match anything")
   304  	}
   305  }
   306  
   307  type matchesTestCase struct {
   308  	pattern string
   309  	text    string
   310  	pass    bool
   311  }
   312  
   313  func TestMatches(t *testing.T) {
   314  	tests := []matchesTestCase{
   315  		{"**", "file", true},
   316  		{"**", "file/", true},
   317  		{"**/", "file", true}, // weird one
   318  		{"**/", "file/", true},
   319  		{"**", "/", true},
   320  		{"**/", "/", true},
   321  		{"**", "dir/file", true},
   322  		{"**/", "dir/file", true},
   323  		{"**", "dir/file/", true},
   324  		{"**/", "dir/file/", true},
   325  		{"**/**", "dir/file", true},
   326  		{"**/**", "dir/file/", true},
   327  		{"dir/**", "dir/file", true},
   328  		{"dir/**", "dir/file/", true},
   329  		{"dir/**", "dir/dir2/file", true},
   330  		{"dir/**", "dir/dir2/file/", true},
   331  		{"**/dir2/*", "dir/dir2/file", true},
   332  		{"**/dir2/*", "dir/dir2/file/", true},
   333  		{"**/dir2/**", "dir/dir2/dir3/file", true},
   334  		{"**/dir2/**", "dir/dir2/dir3/file/", true},
   335  		{"**file", "file", true},
   336  		{"**file", "dir/file", true},
   337  		{"**/file", "dir/file", true},
   338  		{"**file", "dir/dir/file", true},
   339  		{"**/file", "dir/dir/file", true},
   340  		{"**/file*", "dir/dir/file", true},
   341  		{"**/file*", "dir/dir/file.txt", true},
   342  		{"**/file*txt", "dir/dir/file.txt", true},
   343  		{"**/file*.txt", "dir/dir/file.txt", true},
   344  		{"**/file*.txt*", "dir/dir/file.txt", true},
   345  		{"**/**/*.txt", "dir/dir/file.txt", true},
   346  		{"**/**/*.txt2", "dir/dir/file.txt", false},
   347  		{"**/*.txt", "file.txt", true},
   348  		{"**/**/*.txt", "file.txt", true},
   349  		{"a**/*.txt", "a/file.txt", true},
   350  		{"a**/*.txt", "a/dir/file.txt", true},
   351  		{"a**/*.txt", "a/dir/dir/file.txt", true},
   352  		{"a/*.txt", "a/dir/file.txt", false},
   353  		{"a/*.txt", "a/file.txt", true},
   354  		{"a/*.txt**", "a/file.txt", true},
   355  		{"a[b-d]e", "ae", false},
   356  		{"a[b-d]e", "ace", true},
   357  		{"a[b-d]e", "aae", false},
   358  		{"a[^b-d]e", "aze", true},
   359  		{".*", ".foo", true},
   360  		{".*", "foo", false},
   361  		{"abc.def", "abcdef", false},
   362  		{"abc.def", "abc.def", true},
   363  		{"abc.def", "abcZdef", false},
   364  		{"abc?def", "abcZdef", true},
   365  		{"abc?def", "abcdef", false},
   366  		{"a\\\\", "a\\", true},
   367  		{"**/foo/bar", "foo/bar", true},
   368  		{"**/foo/bar", "dir/foo/bar", true},
   369  		{"**/foo/bar", "dir/dir2/foo/bar", true},
   370  		{"abc/**", "abc", false},
   371  		{"abc/**", "abc/def", true},
   372  		{"abc/**", "abc/def/ghi", true},
   373  		{"**/.foo", ".foo", true},
   374  		{"**/.foo", "bar.foo", false},
   375  	}
   376  
   377  	if runtime.GOOS != "windows" {
   378  		tests = append(tests, []matchesTestCase{
   379  			{"a\\*b", "a*b", true},
   380  			{"a\\", "a", false},
   381  			{"a\\", "a\\", false},
   382  		}...)
   383  	}
   384  
   385  	for _, test := range tests {
   386  		desc := fmt.Sprintf("pattern=%q text=%q", test.pattern, test.text)
   387  		pm, err := NewPatternMatcher([]string{test.pattern})
   388  		assert.NilError(t, err, desc)
   389  		res, _ := pm.Matches(test.text)
   390  		assert.Check(t, is.Equal(test.pass, res), desc)
   391  	}
   392  }
   393  
   394  func TestCleanPatterns(t *testing.T) {
   395  	patterns := []string{"docs", "config"}
   396  	pm, err := NewPatternMatcher(patterns)
   397  	if err != nil {
   398  		t.Fatalf("invalid pattern %v", patterns)
   399  	}
   400  	cleaned := pm.Patterns()
   401  	if len(cleaned) != 2 {
   402  		t.Errorf("expected 2 element slice, got %v", len(cleaned))
   403  	}
   404  }
   405  
   406  func TestCleanPatternsStripEmptyPatterns(t *testing.T) {
   407  	patterns := []string{"docs", "config", ""}
   408  	pm, err := NewPatternMatcher(patterns)
   409  	if err != nil {
   410  		t.Fatalf("invalid pattern %v", patterns)
   411  	}
   412  	cleaned := pm.Patterns()
   413  	if len(cleaned) != 2 {
   414  		t.Errorf("expected 2 element slice, got %v", len(cleaned))
   415  	}
   416  }
   417  
   418  func TestCleanPatternsExceptionFlag(t *testing.T) {
   419  	patterns := []string{"docs", "!docs/README.md"}
   420  	pm, err := NewPatternMatcher(patterns)
   421  	if err != nil {
   422  		t.Fatalf("invalid pattern %v", patterns)
   423  	}
   424  	if !pm.Exclusions() {
   425  		t.Errorf("expected exceptions to be true, got %v", pm.Exclusions())
   426  	}
   427  }
   428  
   429  func TestCleanPatternsLeadingSpaceTrimmed(t *testing.T) {
   430  	patterns := []string{"docs", "  !docs/README.md"}
   431  	pm, err := NewPatternMatcher(patterns)
   432  	if err != nil {
   433  		t.Fatalf("invalid pattern %v", patterns)
   434  	}
   435  	if !pm.Exclusions() {
   436  		t.Errorf("expected exceptions to be true, got %v", pm.Exclusions())
   437  	}
   438  }
   439  
   440  func TestCleanPatternsTrailingSpaceTrimmed(t *testing.T) {
   441  	patterns := []string{"docs", "!docs/README.md  "}
   442  	pm, err := NewPatternMatcher(patterns)
   443  	if err != nil {
   444  		t.Fatalf("invalid pattern %v", patterns)
   445  	}
   446  	if !pm.Exclusions() {
   447  		t.Errorf("expected exceptions to be true, got %v", pm.Exclusions())
   448  	}
   449  }
   450  
   451  func TestCleanPatternsErrorSingleException(t *testing.T) {
   452  	patterns := []string{"!"}
   453  	_, err := NewPatternMatcher(patterns)
   454  	if err == nil {
   455  		t.Errorf("expected error on single exclamation point, got %v", err)
   456  	}
   457  }
   458  
   459  func TestCreateIfNotExistsDir(t *testing.T) {
   460  	tempFolder, err := ioutil.TempDir("", "docker-fileutils-test")
   461  	if err != nil {
   462  		t.Fatal(err)
   463  	}
   464  	defer os.RemoveAll(tempFolder)
   465  
   466  	folderToCreate := filepath.Join(tempFolder, "tocreate")
   467  
   468  	if err := CreateIfNotExists(folderToCreate, true); err != nil {
   469  		t.Fatal(err)
   470  	}
   471  	fileinfo, err := os.Stat(folderToCreate)
   472  	if err != nil {
   473  		t.Fatalf("Should have create a folder, got %v", err)
   474  	}
   475  
   476  	if !fileinfo.IsDir() {
   477  		t.Fatalf("Should have been a dir, seems it's not")
   478  	}
   479  }
   480  
   481  func TestCreateIfNotExistsFile(t *testing.T) {
   482  	tempFolder, err := ioutil.TempDir("", "docker-fileutils-test")
   483  	if err != nil {
   484  		t.Fatal(err)
   485  	}
   486  	defer os.RemoveAll(tempFolder)
   487  
   488  	fileToCreate := filepath.Join(tempFolder, "file/to/create")
   489  
   490  	if err := CreateIfNotExists(fileToCreate, false); err != nil {
   491  		t.Fatal(err)
   492  	}
   493  	fileinfo, err := os.Stat(fileToCreate)
   494  	if err != nil {
   495  		t.Fatalf("Should have create a file, got %v", err)
   496  	}
   497  
   498  	if fileinfo.IsDir() {
   499  		t.Fatalf("Should have been a file, seems it's not")
   500  	}
   501  }
   502  
   503  // These matchTests are stolen from go's filepath Match tests.
   504  type matchTest struct {
   505  	pattern, s string
   506  	match      bool
   507  	err        error
   508  }
   509  
   510  var matchTests = []matchTest{
   511  	{"abc", "abc", true, nil},
   512  	{"*", "abc", true, nil},
   513  	{"*c", "abc", true, nil},
   514  	{"a*", "a", true, nil},
   515  	{"a*", "abc", true, nil},
   516  	{"a*", "ab/c", true, nil},
   517  	{"a*/b", "abc/b", true, nil},
   518  	{"a*/b", "a/c/b", false, nil},
   519  	{"a*b*c*d*e*/f", "axbxcxdxe/f", true, nil},
   520  	{"a*b*c*d*e*/f", "axbxcxdxexxx/f", true, nil},
   521  	{"a*b*c*d*e*/f", "axbxcxdxe/xxx/f", false, nil},
   522  	{"a*b*c*d*e*/f", "axbxcxdxexxx/fff", false, nil},
   523  	{"a*b?c*x", "abxbbxdbxebxczzx", true, nil},
   524  	{"a*b?c*x", "abxbbxdbxebxczzy", false, nil},
   525  	{"ab[c]", "abc", true, nil},
   526  	{"ab[b-d]", "abc", true, nil},
   527  	{"ab[e-g]", "abc", false, nil},
   528  	{"ab[^c]", "abc", false, nil},
   529  	{"ab[^b-d]", "abc", false, nil},
   530  	{"ab[^e-g]", "abc", true, nil},
   531  	{"a\\*b", "a*b", true, nil},
   532  	{"a\\*b", "ab", false, nil},
   533  	{"a?b", "a☺b", true, nil},
   534  	{"a[^a]b", "a☺b", true, nil},
   535  	{"a???b", "a☺b", false, nil},
   536  	{"a[^a][^a][^a]b", "a☺b", false, nil},
   537  	{"[a-ζ]*", "α", true, nil},
   538  	{"*[a-ζ]", "A", false, nil},
   539  	{"a?b", "a/b", false, nil},
   540  	{"a*b", "a/b", false, nil},
   541  	{"[\\]a]", "]", true, nil},
   542  	{"[\\-]", "-", true, nil},
   543  	{"[x\\-]", "x", true, nil},
   544  	{"[x\\-]", "-", true, nil},
   545  	{"[x\\-]", "z", false, nil},
   546  	{"[\\-x]", "x", true, nil},
   547  	{"[\\-x]", "-", true, nil},
   548  	{"[\\-x]", "a", false, nil},
   549  	{"[]a]", "]", false, filepath.ErrBadPattern},
   550  	{"[-]", "-", false, filepath.ErrBadPattern},
   551  	{"[x-]", "x", false, filepath.ErrBadPattern},
   552  	{"[x-]", "-", false, filepath.ErrBadPattern},
   553  	{"[x-]", "z", false, filepath.ErrBadPattern},
   554  	{"[-x]", "x", false, filepath.ErrBadPattern},
   555  	{"[-x]", "-", false, filepath.ErrBadPattern},
   556  	{"[-x]", "a", false, filepath.ErrBadPattern},
   557  	{"\\", "a", false, filepath.ErrBadPattern},
   558  	{"[a-b-c]", "a", false, filepath.ErrBadPattern},
   559  	{"[", "a", false, filepath.ErrBadPattern},
   560  	{"[^", "a", false, filepath.ErrBadPattern},
   561  	{"[^bc", "a", false, filepath.ErrBadPattern},
   562  	{"a[", "a", false, filepath.ErrBadPattern}, // was nil but IMO its wrong
   563  	{"a[", "ab", false, filepath.ErrBadPattern},
   564  	{"*x", "xxx", true, nil},
   565  }
   566  
   567  func errp(e error) string {
   568  	if e == nil {
   569  		return "<nil>"
   570  	}
   571  	return e.Error()
   572  }
   573  
   574  // TestMatch test's our version of filepath.Match, called regexpMatch.
   575  func TestMatch(t *testing.T) {
   576  	for _, tt := range matchTests {
   577  		pattern := tt.pattern
   578  		s := tt.s
   579  		if runtime.GOOS == "windows" {
   580  			if strings.Contains(pattern, "\\") {
   581  				// no escape allowed on windows.
   582  				continue
   583  			}
   584  			pattern = filepath.Clean(pattern)
   585  			s = filepath.Clean(s)
   586  		}
   587  		ok, err := Matches(s, []string{pattern})
   588  		if ok != tt.match || err != tt.err {
   589  			t.Fatalf("Match(%#q, %#q) = %v, %q want %v, %q", pattern, s, ok, errp(err), tt.match, errp(tt.err))
   590  		}
   591  	}
   592  }