1// Copyright © 2014 Steve Francia <spf@spf13.com>.
2// Copyright 2009 The Go Authors. All rights reserved.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package afero
16
17import (
18	"os"
19	"path/filepath"
20	"runtime"
21	"testing"
22)
23
24// contains returns true if vector contains the string s.
25func contains(vector []string, s string) bool {
26	for _, elem := range vector {
27		if elem == s {
28			return true
29		}
30	}
31	return false
32}
33
34func setupGlobDirRoot(t *testing.T, fs Fs) string {
35	path := testDir(fs)
36	setupGlobFiles(t, fs, path)
37	return path
38}
39
40func setupGlobDirReusePath(t *testing.T, fs Fs, path string) string {
41	testRegistry[fs] = append(testRegistry[fs], path)
42	return setupGlobFiles(t, fs, path)
43}
44
45func setupGlobFiles(t *testing.T, fs Fs, path string) string {
46	testSubDir := filepath.Join(path, "globs", "bobs")
47	err := fs.MkdirAll(testSubDir, 0700)
48	if err != nil && !os.IsExist(err) {
49		t.Fatal(err)
50	}
51
52	f, err := fs.Create(filepath.Join(testSubDir, "/matcher"))
53	if err != nil {
54		t.Fatal(err)
55	}
56	f.WriteString("Testfile 1 content")
57	f.Close()
58
59	f, err = fs.Create(filepath.Join(testSubDir, "/../submatcher"))
60	if err != nil {
61		t.Fatal(err)
62	}
63	f.WriteString("Testfile 2 content")
64	f.Close()
65
66	f, err = fs.Create(filepath.Join(testSubDir, "/../../match"))
67	if err != nil {
68		t.Fatal(err)
69	}
70	f.WriteString("Testfile 3 content")
71	f.Close()
72
73	return testSubDir
74}
75
76func TestGlob(t *testing.T) {
77	defer removeAllTestFiles(t)
78	var testDir string
79	for i, fs := range Fss {
80		if i == 0 {
81			testDir = setupGlobDirRoot(t, fs)
82		} else {
83			setupGlobDirReusePath(t, fs, testDir)
84		}
85	}
86
87	var globTests = []struct {
88		pattern, result string
89	}{
90		{testDir + "/globs/bobs/matcher", testDir + "/globs/bobs/matcher"},
91		{testDir + "/globs/*/mat?her", testDir + "/globs/bobs/matcher"},
92		{testDir + "/globs/bobs/../*", testDir + "/globs/submatcher"},
93		{testDir + "/match", testDir + "/match"},
94	}
95
96	for _, fs := range Fss {
97
98		for _, tt := range globTests {
99			pattern := tt.pattern
100			result := tt.result
101			if runtime.GOOS == "windows" {
102				pattern = filepath.Clean(pattern)
103				result = filepath.Clean(result)
104			}
105			matches, err := Glob(fs, pattern)
106			if err != nil {
107				t.Errorf("Glob error for %q: %s", pattern, err)
108				continue
109			}
110			if !contains(matches, result) {
111				t.Errorf("Glob(%#q) = %#v want %v", pattern, matches, result)
112			}
113		}
114		for _, pattern := range []string{"no_match", "../*/no_match"} {
115			matches, err := Glob(fs, pattern)
116			if err != nil {
117				t.Errorf("Glob error for %q: %s", pattern, err)
118				continue
119			}
120			if len(matches) != 0 {
121				t.Errorf("Glob(%#q) = %#v want []", pattern, matches)
122			}
123		}
124
125	}
126}
127
128func TestGlobSymlink(t *testing.T) {
129	defer removeAllTestFiles(t)
130
131	fs := &OsFs{}
132	testDir := setupGlobDirRoot(t, fs)
133
134	err := os.Symlink("target", filepath.Join(testDir, "symlink"))
135	if err != nil {
136		t.Skipf("skipping on %s", runtime.GOOS)
137	}
138
139	var globSymlinkTests = []struct {
140		path, dest string
141		brokenLink bool
142	}{
143		{"test1", "link1", false},
144		{"test2", "link2", true},
145	}
146
147	for _, tt := range globSymlinkTests {
148		path := filepath.Join(testDir, tt.path)
149		dest := filepath.Join(testDir, tt.dest)
150		f, err := fs.Create(path)
151		if err != nil {
152			t.Fatal(err)
153		}
154		if err := f.Close(); err != nil {
155			t.Fatal(err)
156		}
157		err = os.Symlink(path, dest)
158		if err != nil {
159			t.Fatal(err)
160		}
161		if tt.brokenLink {
162			// Break the symlink.
163			fs.Remove(path)
164		}
165		matches, err := Glob(fs, dest)
166		if err != nil {
167			t.Errorf("GlobSymlink error for %q: %s", dest, err)
168		}
169		if !contains(matches, dest) {
170			t.Errorf("Glob(%#q) = %#v want %v", dest, matches, dest)
171		}
172	}
173}
174
175
176func TestGlobError(t *testing.T) {
177	for _, fs := range Fss {
178		_, err := Glob(fs, "[7]")
179		if err != nil {
180			t.Error("expected error for bad pattern; got none")
181		}
182	}
183}
184