xref: /aosp_15_r20/build/soong/finder/finder_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2017 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage finder
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"fmt"
19*333d2b36SAndroid Build Coastguard Worker	"io/ioutil"
20*333d2b36SAndroid Build Coastguard Worker	"log"
21*333d2b36SAndroid Build Coastguard Worker	"os"
22*333d2b36SAndroid Build Coastguard Worker	"path/filepath"
23*333d2b36SAndroid Build Coastguard Worker	"sort"
24*333d2b36SAndroid Build Coastguard Worker	"strings"
25*333d2b36SAndroid Build Coastguard Worker	"testing"
26*333d2b36SAndroid Build Coastguard Worker
27*333d2b36SAndroid Build Coastguard Worker	"android/soong/finder/fs"
28*333d2b36SAndroid Build Coastguard Worker)
29*333d2b36SAndroid Build Coastguard Worker
30*333d2b36SAndroid Build Coastguard Worker// some utils for tests to use
31*333d2b36SAndroid Build Coastguard Workerfunc newFs() *fs.MockFs {
32*333d2b36SAndroid Build Coastguard Worker	return fs.NewMockFs(map[string][]byte{})
33*333d2b36SAndroid Build Coastguard Worker}
34*333d2b36SAndroid Build Coastguard Worker
35*333d2b36SAndroid Build Coastguard Workerfunc newFinder(t *testing.T, filesystem *fs.MockFs, cacheParams CacheParams) *Finder {
36*333d2b36SAndroid Build Coastguard Worker	return newFinderWithNumThreads(t, filesystem, cacheParams, 2)
37*333d2b36SAndroid Build Coastguard Worker}
38*333d2b36SAndroid Build Coastguard Worker
39*333d2b36SAndroid Build Coastguard Workerfunc newFinderWithNumThreads(t *testing.T, filesystem *fs.MockFs, cacheParams CacheParams, numThreads int) *Finder {
40*333d2b36SAndroid Build Coastguard Worker	f, err := newFinderAndErr(t, filesystem, cacheParams, numThreads)
41*333d2b36SAndroid Build Coastguard Worker	if err != nil {
42*333d2b36SAndroid Build Coastguard Worker		t.Fatal(err.Error())
43*333d2b36SAndroid Build Coastguard Worker	}
44*333d2b36SAndroid Build Coastguard Worker	return f
45*333d2b36SAndroid Build Coastguard Worker}
46*333d2b36SAndroid Build Coastguard Worker
47*333d2b36SAndroid Build Coastguard Workerfunc newFinderAndErr(t *testing.T, filesystem *fs.MockFs, cacheParams CacheParams, numThreads int) (*Finder, error) {
48*333d2b36SAndroid Build Coastguard Worker	cachePath := "/finder/finder-db"
49*333d2b36SAndroid Build Coastguard Worker	cacheDir := filepath.Dir(cachePath)
50*333d2b36SAndroid Build Coastguard Worker	filesystem.MkDirs(cacheDir)
51*333d2b36SAndroid Build Coastguard Worker	if cacheParams.WorkingDirectory == "" {
52*333d2b36SAndroid Build Coastguard Worker		cacheParams.WorkingDirectory = "/cwd"
53*333d2b36SAndroid Build Coastguard Worker	}
54*333d2b36SAndroid Build Coastguard Worker
55*333d2b36SAndroid Build Coastguard Worker	logger := log.New(ioutil.Discard, "", 0)
56*333d2b36SAndroid Build Coastguard Worker	f, err := newImpl(cacheParams, filesystem, logger, cachePath, numThreads)
57*333d2b36SAndroid Build Coastguard Worker	return f, err
58*333d2b36SAndroid Build Coastguard Worker}
59*333d2b36SAndroid Build Coastguard Worker
60*333d2b36SAndroid Build Coastguard Workerfunc finderWithSameParams(t *testing.T, original *Finder) *Finder {
61*333d2b36SAndroid Build Coastguard Worker	f, err := finderAndErrorWithSameParams(t, original)
62*333d2b36SAndroid Build Coastguard Worker	if err != nil {
63*333d2b36SAndroid Build Coastguard Worker		t.Fatal(err.Error())
64*333d2b36SAndroid Build Coastguard Worker	}
65*333d2b36SAndroid Build Coastguard Worker	return f
66*333d2b36SAndroid Build Coastguard Worker}
67*333d2b36SAndroid Build Coastguard Worker
68*333d2b36SAndroid Build Coastguard Workerfunc finderAndErrorWithSameParams(t *testing.T, original *Finder) (*Finder, error) {
69*333d2b36SAndroid Build Coastguard Worker	f, err := newImpl(
70*333d2b36SAndroid Build Coastguard Worker		original.cacheMetadata.Config.CacheParams,
71*333d2b36SAndroid Build Coastguard Worker		original.filesystem,
72*333d2b36SAndroid Build Coastguard Worker		original.logger,
73*333d2b36SAndroid Build Coastguard Worker		original.DbPath,
74*333d2b36SAndroid Build Coastguard Worker		original.numDbLoadingThreads,
75*333d2b36SAndroid Build Coastguard Worker	)
76*333d2b36SAndroid Build Coastguard Worker	return f, err
77*333d2b36SAndroid Build Coastguard Worker}
78*333d2b36SAndroid Build Coastguard Worker
79*333d2b36SAndroid Build Coastguard Worker// runSimpleTests creates a few files, searches for findme.txt, and checks for the expected matches
80*333d2b36SAndroid Build Coastguard Workerfunc runSimpleTest(t *testing.T, existentPaths []string, expectedMatches []string) {
81*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
82*333d2b36SAndroid Build Coastguard Worker	root := "/tmp"
83*333d2b36SAndroid Build Coastguard Worker	filesystem.MkDirs(root)
84*333d2b36SAndroid Build Coastguard Worker	for _, path := range existentPaths {
85*333d2b36SAndroid Build Coastguard Worker		fs.Create(t, filepath.Join(root, path), filesystem)
86*333d2b36SAndroid Build Coastguard Worker	}
87*333d2b36SAndroid Build Coastguard Worker
88*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(t,
89*333d2b36SAndroid Build Coastguard Worker		filesystem,
90*333d2b36SAndroid Build Coastguard Worker		CacheParams{
91*333d2b36SAndroid Build Coastguard Worker			"/cwd",
92*333d2b36SAndroid Build Coastguard Worker			[]string{root},
93*333d2b36SAndroid Build Coastguard Worker			false,
94*333d2b36SAndroid Build Coastguard Worker			nil,
95*333d2b36SAndroid Build Coastguard Worker			nil,
96*333d2b36SAndroid Build Coastguard Worker			[]string{"findme.txt", "skipme.txt"},
97*333d2b36SAndroid Build Coastguard Worker			nil,
98*333d2b36SAndroid Build Coastguard Worker		},
99*333d2b36SAndroid Build Coastguard Worker	)
100*333d2b36SAndroid Build Coastguard Worker	defer finder.Shutdown()
101*333d2b36SAndroid Build Coastguard Worker
102*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt(root, "findme.txt")
103*333d2b36SAndroid Build Coastguard Worker	absoluteMatches := []string{}
104*333d2b36SAndroid Build Coastguard Worker	for i := range expectedMatches {
105*333d2b36SAndroid Build Coastguard Worker		absoluteMatches = append(absoluteMatches, filepath.Join(root, expectedMatches[i]))
106*333d2b36SAndroid Build Coastguard Worker	}
107*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, absoluteMatches)
108*333d2b36SAndroid Build Coastguard Worker}
109*333d2b36SAndroid Build Coastguard Worker
110*333d2b36SAndroid Build Coastguard Worker// runTestWithSuffixes creates a few files, searches for findme.txt or any file
111*333d2b36SAndroid Build Coastguard Worker// with suffix `.findme_ext` and checks for the expected matches
112*333d2b36SAndroid Build Coastguard Workerfunc runTestWithSuffixes(t *testing.T, existentPaths []string, expectedMatches []string) {
113*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
114*333d2b36SAndroid Build Coastguard Worker	root := "/tmp"
115*333d2b36SAndroid Build Coastguard Worker	filesystem.MkDirs(root)
116*333d2b36SAndroid Build Coastguard Worker	for _, path := range existentPaths {
117*333d2b36SAndroid Build Coastguard Worker		fs.Create(t, filepath.Join(root, path), filesystem)
118*333d2b36SAndroid Build Coastguard Worker	}
119*333d2b36SAndroid Build Coastguard Worker
120*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(t,
121*333d2b36SAndroid Build Coastguard Worker		filesystem,
122*333d2b36SAndroid Build Coastguard Worker		CacheParams{
123*333d2b36SAndroid Build Coastguard Worker			"/cwd",
124*333d2b36SAndroid Build Coastguard Worker			[]string{root},
125*333d2b36SAndroid Build Coastguard Worker			false,
126*333d2b36SAndroid Build Coastguard Worker			nil,
127*333d2b36SAndroid Build Coastguard Worker			nil,
128*333d2b36SAndroid Build Coastguard Worker			[]string{"findme.txt", "skipme.txt"},
129*333d2b36SAndroid Build Coastguard Worker			[]string{".findme_ext"},
130*333d2b36SAndroid Build Coastguard Worker		},
131*333d2b36SAndroid Build Coastguard Worker	)
132*333d2b36SAndroid Build Coastguard Worker	defer finder.Shutdown()
133*333d2b36SAndroid Build Coastguard Worker
134*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindMatching(root,
135*333d2b36SAndroid Build Coastguard Worker		func(entries DirEntries) (dirs []string, files []string) {
136*333d2b36SAndroid Build Coastguard Worker			matches := []string{}
137*333d2b36SAndroid Build Coastguard Worker			for _, foundName := range entries.FileNames {
138*333d2b36SAndroid Build Coastguard Worker				if foundName == "findme.txt" || strings.HasSuffix(foundName, ".findme_ext") {
139*333d2b36SAndroid Build Coastguard Worker					matches = append(matches, foundName)
140*333d2b36SAndroid Build Coastguard Worker				}
141*333d2b36SAndroid Build Coastguard Worker			}
142*333d2b36SAndroid Build Coastguard Worker			return entries.DirNames, matches
143*333d2b36SAndroid Build Coastguard Worker		})
144*333d2b36SAndroid Build Coastguard Worker	absoluteMatches := []string{}
145*333d2b36SAndroid Build Coastguard Worker	for i := range expectedMatches {
146*333d2b36SAndroid Build Coastguard Worker		absoluteMatches = append(absoluteMatches, filepath.Join(root, expectedMatches[i]))
147*333d2b36SAndroid Build Coastguard Worker	}
148*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, absoluteMatches)
149*333d2b36SAndroid Build Coastguard Worker}
150*333d2b36SAndroid Build Coastguard Worker
151*333d2b36SAndroid Build Coastguard Worker// testAgainstSeveralThreadcounts runs the given test for each threadcount that we care to test
152*333d2b36SAndroid Build Coastguard Workerfunc testAgainstSeveralThreadcounts(t *testing.T, tester func(t *testing.T, numThreads int)) {
153*333d2b36SAndroid Build Coastguard Worker	// test singlethreaded, multithreaded, and also using the same number of threads as
154*333d2b36SAndroid Build Coastguard Worker	// will be used on the current system
155*333d2b36SAndroid Build Coastguard Worker	threadCounts := []int{1, 2, defaultNumThreads}
156*333d2b36SAndroid Build Coastguard Worker	for _, numThreads := range threadCounts {
157*333d2b36SAndroid Build Coastguard Worker		testName := fmt.Sprintf("%v threads", numThreads)
158*333d2b36SAndroid Build Coastguard Worker		// store numThreads in a new variable to prevent numThreads from changing in each loop
159*333d2b36SAndroid Build Coastguard Worker		localNumThreads := numThreads
160*333d2b36SAndroid Build Coastguard Worker		t.Run(testName, func(t *testing.T) {
161*333d2b36SAndroid Build Coastguard Worker			tester(t, localNumThreads)
162*333d2b36SAndroid Build Coastguard Worker		})
163*333d2b36SAndroid Build Coastguard Worker	}
164*333d2b36SAndroid Build Coastguard Worker}
165*333d2b36SAndroid Build Coastguard Worker
166*333d2b36SAndroid Build Coastguard Worker// end of utils, start of individual tests
167*333d2b36SAndroid Build Coastguard Worker
168*333d2b36SAndroid Build Coastguard Workerfunc TestSingleFile(t *testing.T) {
169*333d2b36SAndroid Build Coastguard Worker	runSimpleTest(t,
170*333d2b36SAndroid Build Coastguard Worker		[]string{"findme.txt"},
171*333d2b36SAndroid Build Coastguard Worker		[]string{"findme.txt"},
172*333d2b36SAndroid Build Coastguard Worker	)
173*333d2b36SAndroid Build Coastguard Worker}
174*333d2b36SAndroid Build Coastguard Worker
175*333d2b36SAndroid Build Coastguard Workerfunc TestIncludeFiles(t *testing.T) {
176*333d2b36SAndroid Build Coastguard Worker	runSimpleTest(t,
177*333d2b36SAndroid Build Coastguard Worker		[]string{"findme.txt", "skipme.txt"},
178*333d2b36SAndroid Build Coastguard Worker		[]string{"findme.txt"},
179*333d2b36SAndroid Build Coastguard Worker	)
180*333d2b36SAndroid Build Coastguard Worker}
181*333d2b36SAndroid Build Coastguard Worker
182*333d2b36SAndroid Build Coastguard Workerfunc TestIncludeFilesAndSuffixes(t *testing.T) {
183*333d2b36SAndroid Build Coastguard Worker	runTestWithSuffixes(t,
184*333d2b36SAndroid Build Coastguard Worker		[]string{"findme.txt", "skipme.txt", "alsome.findme_ext"},
185*333d2b36SAndroid Build Coastguard Worker		[]string{"findme.txt", "alsome.findme_ext"},
186*333d2b36SAndroid Build Coastguard Worker	)
187*333d2b36SAndroid Build Coastguard Worker}
188*333d2b36SAndroid Build Coastguard Worker
189*333d2b36SAndroid Build Coastguard Workerfunc TestNestedDirectories(t *testing.T) {
190*333d2b36SAndroid Build Coastguard Worker	runSimpleTest(t,
191*333d2b36SAndroid Build Coastguard Worker		[]string{"findme.txt", "skipme.txt", "subdir/findme.txt", "subdir/skipme.txt"},
192*333d2b36SAndroid Build Coastguard Worker		[]string{"findme.txt", "subdir/findme.txt"},
193*333d2b36SAndroid Build Coastguard Worker	)
194*333d2b36SAndroid Build Coastguard Worker}
195*333d2b36SAndroid Build Coastguard Worker
196*333d2b36SAndroid Build Coastguard Workerfunc TestNestedDirectoriesWithSuffixes(t *testing.T) {
197*333d2b36SAndroid Build Coastguard Worker	runTestWithSuffixes(t,
198*333d2b36SAndroid Build Coastguard Worker		[]string{"findme.txt", "skipme.txt", "subdir/findme.txt", "subdir/skipme.txt", "subdir/alsome.findme_ext"},
199*333d2b36SAndroid Build Coastguard Worker		[]string{"findme.txt", "subdir/findme.txt", "subdir/alsome.findme_ext"},
200*333d2b36SAndroid Build Coastguard Worker	)
201*333d2b36SAndroid Build Coastguard Worker}
202*333d2b36SAndroid Build Coastguard Worker
203*333d2b36SAndroid Build Coastguard Workerfunc TestEmptyDirectory(t *testing.T) {
204*333d2b36SAndroid Build Coastguard Worker	runSimpleTest(t,
205*333d2b36SAndroid Build Coastguard Worker		[]string{},
206*333d2b36SAndroid Build Coastguard Worker		[]string{},
207*333d2b36SAndroid Build Coastguard Worker	)
208*333d2b36SAndroid Build Coastguard Worker}
209*333d2b36SAndroid Build Coastguard Worker
210*333d2b36SAndroid Build Coastguard Workerfunc TestEmptyPath(t *testing.T) {
211*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
212*333d2b36SAndroid Build Coastguard Worker	root := "/tmp"
213*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, filepath.Join(root, "findme.txt"), filesystem)
214*333d2b36SAndroid Build Coastguard Worker
215*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
216*333d2b36SAndroid Build Coastguard Worker		t,
217*333d2b36SAndroid Build Coastguard Worker		filesystem,
218*333d2b36SAndroid Build Coastguard Worker		CacheParams{
219*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{root},
220*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt", "skipme.txt"},
221*333d2b36SAndroid Build Coastguard Worker		},
222*333d2b36SAndroid Build Coastguard Worker	)
223*333d2b36SAndroid Build Coastguard Worker	defer finder.Shutdown()
224*333d2b36SAndroid Build Coastguard Worker
225*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("", "findme.txt")
226*333d2b36SAndroid Build Coastguard Worker
227*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{})
228*333d2b36SAndroid Build Coastguard Worker}
229*333d2b36SAndroid Build Coastguard Worker
230*333d2b36SAndroid Build Coastguard Workerfunc TestFilesystemRoot(t *testing.T) {
231*333d2b36SAndroid Build Coastguard Worker
232*333d2b36SAndroid Build Coastguard Worker	testWithNumThreads := func(t *testing.T, numThreads int) {
233*333d2b36SAndroid Build Coastguard Worker		filesystem := newFs()
234*333d2b36SAndroid Build Coastguard Worker		root := "/"
235*333d2b36SAndroid Build Coastguard Worker		createdPath := "/findme.txt"
236*333d2b36SAndroid Build Coastguard Worker		fs.Create(t, createdPath, filesystem)
237*333d2b36SAndroid Build Coastguard Worker
238*333d2b36SAndroid Build Coastguard Worker		finder := newFinderWithNumThreads(
239*333d2b36SAndroid Build Coastguard Worker			t,
240*333d2b36SAndroid Build Coastguard Worker			filesystem,
241*333d2b36SAndroid Build Coastguard Worker			CacheParams{
242*333d2b36SAndroid Build Coastguard Worker				RootDirs:     []string{root},
243*333d2b36SAndroid Build Coastguard Worker				IncludeFiles: []string{"findme.txt", "skipme.txt"},
244*333d2b36SAndroid Build Coastguard Worker			},
245*333d2b36SAndroid Build Coastguard Worker			numThreads,
246*333d2b36SAndroid Build Coastguard Worker		)
247*333d2b36SAndroid Build Coastguard Worker		defer finder.Shutdown()
248*333d2b36SAndroid Build Coastguard Worker
249*333d2b36SAndroid Build Coastguard Worker		foundPaths := finder.FindNamedAt(root, "findme.txt")
250*333d2b36SAndroid Build Coastguard Worker
251*333d2b36SAndroid Build Coastguard Worker		fs.AssertSameResponse(t, foundPaths, []string{createdPath})
252*333d2b36SAndroid Build Coastguard Worker	}
253*333d2b36SAndroid Build Coastguard Worker
254*333d2b36SAndroid Build Coastguard Worker	testAgainstSeveralThreadcounts(t, testWithNumThreads)
255*333d2b36SAndroid Build Coastguard Worker}
256*333d2b36SAndroid Build Coastguard Worker
257*333d2b36SAndroid Build Coastguard Workerfunc TestNonexistentDir(t *testing.T) {
258*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
259*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", filesystem)
260*333d2b36SAndroid Build Coastguard Worker
261*333d2b36SAndroid Build Coastguard Worker	_, err := newFinderAndErr(
262*333d2b36SAndroid Build Coastguard Worker		t,
263*333d2b36SAndroid Build Coastguard Worker		filesystem,
264*333d2b36SAndroid Build Coastguard Worker		CacheParams{
265*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp/IDontExist"},
266*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt", "skipme.txt"},
267*333d2b36SAndroid Build Coastguard Worker		},
268*333d2b36SAndroid Build Coastguard Worker		1,
269*333d2b36SAndroid Build Coastguard Worker	)
270*333d2b36SAndroid Build Coastguard Worker	if err == nil {
271*333d2b36SAndroid Build Coastguard Worker		t.Fatal("Did not fail when given a nonexistent root directory")
272*333d2b36SAndroid Build Coastguard Worker	}
273*333d2b36SAndroid Build Coastguard Worker}
274*333d2b36SAndroid Build Coastguard Worker
275*333d2b36SAndroid Build Coastguard Workerfunc TestExcludeDirs(t *testing.T) {
276*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
277*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/exclude/findme.txt", filesystem)
278*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/exclude/subdir/findme.txt", filesystem)
279*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/subdir/exclude/findme.txt", filesystem)
280*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/subdir/subdir/findme.txt", filesystem)
281*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/subdir/findme.txt", filesystem)
282*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", filesystem)
283*333d2b36SAndroid Build Coastguard Worker
284*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
285*333d2b36SAndroid Build Coastguard Worker		t,
286*333d2b36SAndroid Build Coastguard Worker		filesystem,
287*333d2b36SAndroid Build Coastguard Worker		CacheParams{
288*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
289*333d2b36SAndroid Build Coastguard Worker			ExcludeDirs:  []string{"exclude"},
290*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt", "skipme.txt"},
291*333d2b36SAndroid Build Coastguard Worker		},
292*333d2b36SAndroid Build Coastguard Worker	)
293*333d2b36SAndroid Build Coastguard Worker	defer finder.Shutdown()
294*333d2b36SAndroid Build Coastguard Worker
295*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
296*333d2b36SAndroid Build Coastguard Worker
297*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
298*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/findme.txt",
299*333d2b36SAndroid Build Coastguard Worker			"/tmp/subdir/findme.txt",
300*333d2b36SAndroid Build Coastguard Worker			"/tmp/subdir/subdir/findme.txt"})
301*333d2b36SAndroid Build Coastguard Worker}
302*333d2b36SAndroid Build Coastguard Worker
303*333d2b36SAndroid Build Coastguard Workerfunc TestPruneFiles(t *testing.T) {
304*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
305*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/out/findme.txt", filesystem)
306*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/out/.ignore-out-dir", filesystem)
307*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/out/child/findme.txt", filesystem)
308*333d2b36SAndroid Build Coastguard Worker
309*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/out2/.ignore-out-dir", filesystem)
310*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/out2/sub/findme.txt", filesystem)
311*333d2b36SAndroid Build Coastguard Worker
312*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", filesystem)
313*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/include/findme.txt", filesystem)
314*333d2b36SAndroid Build Coastguard Worker
315*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
316*333d2b36SAndroid Build Coastguard Worker		t,
317*333d2b36SAndroid Build Coastguard Worker		filesystem,
318*333d2b36SAndroid Build Coastguard Worker		CacheParams{
319*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
320*333d2b36SAndroid Build Coastguard Worker			PruneFiles:   []string{".ignore-out-dir"},
321*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
322*333d2b36SAndroid Build Coastguard Worker		},
323*333d2b36SAndroid Build Coastguard Worker	)
324*333d2b36SAndroid Build Coastguard Worker	defer finder.Shutdown()
325*333d2b36SAndroid Build Coastguard Worker
326*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
327*333d2b36SAndroid Build Coastguard Worker
328*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
329*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/findme.txt",
330*333d2b36SAndroid Build Coastguard Worker			"/tmp/include/findme.txt"})
331*333d2b36SAndroid Build Coastguard Worker}
332*333d2b36SAndroid Build Coastguard Worker
333*333d2b36SAndroid Build Coastguard Worker// TestRootDir tests that the value of RootDirs is used
334*333d2b36SAndroid Build Coastguard Worker// tests of the filesystem root are in TestFilesystemRoot
335*333d2b36SAndroid Build Coastguard Workerfunc TestRootDir(t *testing.T) {
336*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
337*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
338*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/subdir/findme.txt", filesystem)
339*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/findme.txt", filesystem)
340*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/subdir/findme.txt", filesystem)
341*333d2b36SAndroid Build Coastguard Worker
342*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
343*333d2b36SAndroid Build Coastguard Worker		t,
344*333d2b36SAndroid Build Coastguard Worker		filesystem,
345*333d2b36SAndroid Build Coastguard Worker		CacheParams{
346*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp/a"},
347*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
348*333d2b36SAndroid Build Coastguard Worker		},
349*333d2b36SAndroid Build Coastguard Worker	)
350*333d2b36SAndroid Build Coastguard Worker	defer finder.Shutdown()
351*333d2b36SAndroid Build Coastguard Worker
352*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp/a", "findme.txt")
353*333d2b36SAndroid Build Coastguard Worker
354*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
355*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/a/findme.txt",
356*333d2b36SAndroid Build Coastguard Worker			"/tmp/a/subdir/findme.txt"})
357*333d2b36SAndroid Build Coastguard Worker}
358*333d2b36SAndroid Build Coastguard Worker
359*333d2b36SAndroid Build Coastguard Workerfunc TestUncachedDir(t *testing.T) {
360*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
361*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
362*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/subdir/findme.txt", filesystem)
363*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/findme.txt", filesystem)
364*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/subdir/findme.txt", filesystem)
365*333d2b36SAndroid Build Coastguard Worker
366*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
367*333d2b36SAndroid Build Coastguard Worker		t,
368*333d2b36SAndroid Build Coastguard Worker		filesystem,
369*333d2b36SAndroid Build Coastguard Worker		CacheParams{
370*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp/b"},
371*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
372*333d2b36SAndroid Build Coastguard Worker		},
373*333d2b36SAndroid Build Coastguard Worker	)
374*333d2b36SAndroid Build Coastguard Worker
375*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp/a", "findme.txt")
376*333d2b36SAndroid Build Coastguard Worker	// If the caller queries for a file that is in the cache, then computing the
377*333d2b36SAndroid Build Coastguard Worker	// correct answer won't be fast, and it would be easy for the caller to
378*333d2b36SAndroid Build Coastguard Worker	// fail to notice its slowness. Instead, we only ever search the cache for files
379*333d2b36SAndroid Build Coastguard Worker	// to return, which enforces that we can determine which files will be
380*333d2b36SAndroid Build Coastguard Worker	// interesting upfront.
381*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{})
382*333d2b36SAndroid Build Coastguard Worker
383*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
384*333d2b36SAndroid Build Coastguard Worker}
385*333d2b36SAndroid Build Coastguard Worker
386*333d2b36SAndroid Build Coastguard Workerfunc TestSearchingForFilesExcludedFromCache(t *testing.T) {
387*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
388*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
389*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", filesystem)
390*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
391*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/misc.txt", filesystem)
392*333d2b36SAndroid Build Coastguard Worker
393*333d2b36SAndroid Build Coastguard Worker	// set up the finder and run it
394*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
395*333d2b36SAndroid Build Coastguard Worker		t,
396*333d2b36SAndroid Build Coastguard Worker		filesystem,
397*333d2b36SAndroid Build Coastguard Worker		CacheParams{
398*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
399*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
400*333d2b36SAndroid Build Coastguard Worker		},
401*333d2b36SAndroid Build Coastguard Worker	)
402*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "misc.txt")
403*333d2b36SAndroid Build Coastguard Worker	// If the caller queries for a file that is in the cache, then computing the
404*333d2b36SAndroid Build Coastguard Worker	// correct answer won't be fast, and it would be easy for the caller to
405*333d2b36SAndroid Build Coastguard Worker	// fail to notice its slowness. Instead, we only ever search the cache for files
406*333d2b36SAndroid Build Coastguard Worker	// to return, which enforces that we can determine which files will be
407*333d2b36SAndroid Build Coastguard Worker	// interesting upfront.
408*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{})
409*333d2b36SAndroid Build Coastguard Worker
410*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
411*333d2b36SAndroid Build Coastguard Worker}
412*333d2b36SAndroid Build Coastguard Worker
413*333d2b36SAndroid Build Coastguard Workerfunc TestRelativeFilePaths(t *testing.T) {
414*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
415*333d2b36SAndroid Build Coastguard Worker
416*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/ignore/hi.txt", filesystem)
417*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/include/hi.txt", filesystem)
418*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/cwd/hi.txt", filesystem)
419*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/cwd/a/hi.txt", filesystem)
420*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/cwd/a/a/hi.txt", filesystem)
421*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/rel/a/hi.txt", filesystem)
422*333d2b36SAndroid Build Coastguard Worker
423*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
424*333d2b36SAndroid Build Coastguard Worker		t,
425*333d2b36SAndroid Build Coastguard Worker		filesystem,
426*333d2b36SAndroid Build Coastguard Worker		CacheParams{
427*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/cwd", "../rel", "/tmp/include"},
428*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"hi.txt"},
429*333d2b36SAndroid Build Coastguard Worker		},
430*333d2b36SAndroid Build Coastguard Worker	)
431*333d2b36SAndroid Build Coastguard Worker	defer finder.Shutdown()
432*333d2b36SAndroid Build Coastguard Worker
433*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("a", "hi.txt")
434*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
435*333d2b36SAndroid Build Coastguard Worker		[]string{"a/hi.txt",
436*333d2b36SAndroid Build Coastguard Worker			"a/a/hi.txt"})
437*333d2b36SAndroid Build Coastguard Worker
438*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder.FindNamedAt("/tmp/include", "hi.txt")
439*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/include/hi.txt"})
440*333d2b36SAndroid Build Coastguard Worker
441*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder.FindNamedAt(".", "hi.txt")
442*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
443*333d2b36SAndroid Build Coastguard Worker		[]string{"hi.txt",
444*333d2b36SAndroid Build Coastguard Worker			"a/hi.txt",
445*333d2b36SAndroid Build Coastguard Worker			"a/a/hi.txt"})
446*333d2b36SAndroid Build Coastguard Worker
447*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder.FindNamedAt("/rel", "hi.txt")
448*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
449*333d2b36SAndroid Build Coastguard Worker		[]string{"/rel/a/hi.txt"})
450*333d2b36SAndroid Build Coastguard Worker
451*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder.FindNamedAt("/tmp/include", "hi.txt")
452*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/include/hi.txt"})
453*333d2b36SAndroid Build Coastguard Worker}
454*333d2b36SAndroid Build Coastguard Worker
455*333d2b36SAndroid Build Coastguard Worker// have to run this test with the race-detector (`go test -race src/android/soong/finder/*.go`)
456*333d2b36SAndroid Build Coastguard Worker// for there to be much chance of the test actually detecting any error that may be present
457*333d2b36SAndroid Build Coastguard Workerfunc TestRootDirsContainedInOtherRootDirs(t *testing.T) {
458*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
459*333d2b36SAndroid Build Coastguard Worker
460*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/b/c/d/e/f/g/h/i/j/findme.txt", filesystem)
461*333d2b36SAndroid Build Coastguard Worker
462*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
463*333d2b36SAndroid Build Coastguard Worker		t,
464*333d2b36SAndroid Build Coastguard Worker		filesystem,
465*333d2b36SAndroid Build Coastguard Worker		CacheParams{
466*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/", "/tmp/a/b/c", "/tmp/a/b/c/d/e/f", "/tmp/a/b/c/d/e/f/g/h/i"},
467*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
468*333d2b36SAndroid Build Coastguard Worker		},
469*333d2b36SAndroid Build Coastguard Worker	)
470*333d2b36SAndroid Build Coastguard Worker	defer finder.Shutdown()
471*333d2b36SAndroid Build Coastguard Worker
472*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp/a", "findme.txt")
473*333d2b36SAndroid Build Coastguard Worker
474*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
475*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/a/b/c/d/e/f/g/h/i/j/findme.txt"})
476*333d2b36SAndroid Build Coastguard Worker}
477*333d2b36SAndroid Build Coastguard Worker
478*333d2b36SAndroid Build Coastguard Workerfunc TestFindFirst(t *testing.T) {
479*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
480*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/hi.txt", filesystem)
481*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/hi.txt", filesystem)
482*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/a/hi.txt", filesystem)
483*333d2b36SAndroid Build Coastguard Worker
484*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
485*333d2b36SAndroid Build Coastguard Worker		t,
486*333d2b36SAndroid Build Coastguard Worker		filesystem,
487*333d2b36SAndroid Build Coastguard Worker		CacheParams{
488*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
489*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"hi.txt"},
490*333d2b36SAndroid Build Coastguard Worker		},
491*333d2b36SAndroid Build Coastguard Worker	)
492*333d2b36SAndroid Build Coastguard Worker	defer finder.Shutdown()
493*333d2b36SAndroid Build Coastguard Worker
494*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindFirstNamed("hi.txt")
495*333d2b36SAndroid Build Coastguard Worker
496*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
497*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/a/hi.txt",
498*333d2b36SAndroid Build Coastguard Worker			"/tmp/b/hi.txt"},
499*333d2b36SAndroid Build Coastguard Worker	)
500*333d2b36SAndroid Build Coastguard Worker}
501*333d2b36SAndroid Build Coastguard Worker
502*333d2b36SAndroid Build Coastguard Workerfunc TestConcurrentFindSameDirectory(t *testing.T) {
503*333d2b36SAndroid Build Coastguard Worker
504*333d2b36SAndroid Build Coastguard Worker	testWithNumThreads := func(t *testing.T, numThreads int) {
505*333d2b36SAndroid Build Coastguard Worker		filesystem := newFs()
506*333d2b36SAndroid Build Coastguard Worker
507*333d2b36SAndroid Build Coastguard Worker		// create a bunch of files and directories
508*333d2b36SAndroid Build Coastguard Worker		paths := []string{}
509*333d2b36SAndroid Build Coastguard Worker		for i := 0; i < 10; i++ {
510*333d2b36SAndroid Build Coastguard Worker			parentDir := fmt.Sprintf("/tmp/%v", i)
511*333d2b36SAndroid Build Coastguard Worker			for j := 0; j < 10; j++ {
512*333d2b36SAndroid Build Coastguard Worker				filePath := filepath.Join(parentDir, fmt.Sprintf("%v/findme.txt", j))
513*333d2b36SAndroid Build Coastguard Worker				paths = append(paths, filePath)
514*333d2b36SAndroid Build Coastguard Worker			}
515*333d2b36SAndroid Build Coastguard Worker		}
516*333d2b36SAndroid Build Coastguard Worker		sort.Strings(paths)
517*333d2b36SAndroid Build Coastguard Worker		for _, path := range paths {
518*333d2b36SAndroid Build Coastguard Worker			fs.Create(t, path, filesystem)
519*333d2b36SAndroid Build Coastguard Worker		}
520*333d2b36SAndroid Build Coastguard Worker
521*333d2b36SAndroid Build Coastguard Worker		// set up a finder
522*333d2b36SAndroid Build Coastguard Worker		finder := newFinderWithNumThreads(
523*333d2b36SAndroid Build Coastguard Worker			t,
524*333d2b36SAndroid Build Coastguard Worker			filesystem,
525*333d2b36SAndroid Build Coastguard Worker			CacheParams{
526*333d2b36SAndroid Build Coastguard Worker				RootDirs:     []string{"/tmp"},
527*333d2b36SAndroid Build Coastguard Worker				IncludeFiles: []string{"findme.txt"},
528*333d2b36SAndroid Build Coastguard Worker			},
529*333d2b36SAndroid Build Coastguard Worker			numThreads,
530*333d2b36SAndroid Build Coastguard Worker		)
531*333d2b36SAndroid Build Coastguard Worker		defer finder.Shutdown()
532*333d2b36SAndroid Build Coastguard Worker
533*333d2b36SAndroid Build Coastguard Worker		numTests := 20
534*333d2b36SAndroid Build Coastguard Worker		results := make(chan []string, numTests)
535*333d2b36SAndroid Build Coastguard Worker		// make several parallel calls to the finder
536*333d2b36SAndroid Build Coastguard Worker		for i := 0; i < numTests; i++ {
537*333d2b36SAndroid Build Coastguard Worker			go func() {
538*333d2b36SAndroid Build Coastguard Worker				foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
539*333d2b36SAndroid Build Coastguard Worker				results <- foundPaths
540*333d2b36SAndroid Build Coastguard Worker			}()
541*333d2b36SAndroid Build Coastguard Worker		}
542*333d2b36SAndroid Build Coastguard Worker
543*333d2b36SAndroid Build Coastguard Worker		// check that each response was correct
544*333d2b36SAndroid Build Coastguard Worker		for i := 0; i < numTests; i++ {
545*333d2b36SAndroid Build Coastguard Worker			foundPaths := <-results
546*333d2b36SAndroid Build Coastguard Worker			fs.AssertSameResponse(t, foundPaths, paths)
547*333d2b36SAndroid Build Coastguard Worker		}
548*333d2b36SAndroid Build Coastguard Worker	}
549*333d2b36SAndroid Build Coastguard Worker
550*333d2b36SAndroid Build Coastguard Worker	testAgainstSeveralThreadcounts(t, testWithNumThreads)
551*333d2b36SAndroid Build Coastguard Worker}
552*333d2b36SAndroid Build Coastguard Worker
553*333d2b36SAndroid Build Coastguard Workerfunc TestConcurrentFindDifferentDirectories(t *testing.T) {
554*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
555*333d2b36SAndroid Build Coastguard Worker
556*333d2b36SAndroid Build Coastguard Worker	// create a bunch of files and directories
557*333d2b36SAndroid Build Coastguard Worker	allFiles := []string{}
558*333d2b36SAndroid Build Coastguard Worker	numSubdirs := 10
559*333d2b36SAndroid Build Coastguard Worker	rootPaths := []string{}
560*333d2b36SAndroid Build Coastguard Worker	queryAnswers := [][]string{}
561*333d2b36SAndroid Build Coastguard Worker	for i := 0; i < numSubdirs; i++ {
562*333d2b36SAndroid Build Coastguard Worker		parentDir := fmt.Sprintf("/tmp/%v", i)
563*333d2b36SAndroid Build Coastguard Worker		rootPaths = append(rootPaths, parentDir)
564*333d2b36SAndroid Build Coastguard Worker		queryAnswers = append(queryAnswers, []string{})
565*333d2b36SAndroid Build Coastguard Worker		for j := 0; j < 10; j++ {
566*333d2b36SAndroid Build Coastguard Worker			filePath := filepath.Join(parentDir, fmt.Sprintf("%v/findme.txt", j))
567*333d2b36SAndroid Build Coastguard Worker			queryAnswers[i] = append(queryAnswers[i], filePath)
568*333d2b36SAndroid Build Coastguard Worker			allFiles = append(allFiles, filePath)
569*333d2b36SAndroid Build Coastguard Worker		}
570*333d2b36SAndroid Build Coastguard Worker		sort.Strings(queryAnswers[i])
571*333d2b36SAndroid Build Coastguard Worker	}
572*333d2b36SAndroid Build Coastguard Worker	sort.Strings(allFiles)
573*333d2b36SAndroid Build Coastguard Worker	for _, path := range allFiles {
574*333d2b36SAndroid Build Coastguard Worker		fs.Create(t, path, filesystem)
575*333d2b36SAndroid Build Coastguard Worker	}
576*333d2b36SAndroid Build Coastguard Worker
577*333d2b36SAndroid Build Coastguard Worker	// set up a finder
578*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
579*333d2b36SAndroid Build Coastguard Worker		t,
580*333d2b36SAndroid Build Coastguard Worker		filesystem,
581*333d2b36SAndroid Build Coastguard Worker
582*333d2b36SAndroid Build Coastguard Worker		CacheParams{
583*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
584*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
585*333d2b36SAndroid Build Coastguard Worker		},
586*333d2b36SAndroid Build Coastguard Worker	)
587*333d2b36SAndroid Build Coastguard Worker	defer finder.Shutdown()
588*333d2b36SAndroid Build Coastguard Worker
589*333d2b36SAndroid Build Coastguard Worker	type testRun struct {
590*333d2b36SAndroid Build Coastguard Worker		path           string
591*333d2b36SAndroid Build Coastguard Worker		foundMatches   []string
592*333d2b36SAndroid Build Coastguard Worker		correctMatches []string
593*333d2b36SAndroid Build Coastguard Worker	}
594*333d2b36SAndroid Build Coastguard Worker
595*333d2b36SAndroid Build Coastguard Worker	numTests := numSubdirs + 1
596*333d2b36SAndroid Build Coastguard Worker	testRuns := make(chan testRun, numTests)
597*333d2b36SAndroid Build Coastguard Worker
598*333d2b36SAndroid Build Coastguard Worker	searchAt := func(path string, correctMatches []string) {
599*333d2b36SAndroid Build Coastguard Worker		foundPaths := finder.FindNamedAt(path, "findme.txt")
600*333d2b36SAndroid Build Coastguard Worker		testRuns <- testRun{path, foundPaths, correctMatches}
601*333d2b36SAndroid Build Coastguard Worker	}
602*333d2b36SAndroid Build Coastguard Worker
603*333d2b36SAndroid Build Coastguard Worker	// make several parallel calls to the finder
604*333d2b36SAndroid Build Coastguard Worker	go searchAt("/tmp", allFiles)
605*333d2b36SAndroid Build Coastguard Worker	for i := 0; i < len(rootPaths); i++ {
606*333d2b36SAndroid Build Coastguard Worker		go searchAt(rootPaths[i], queryAnswers[i])
607*333d2b36SAndroid Build Coastguard Worker	}
608*333d2b36SAndroid Build Coastguard Worker
609*333d2b36SAndroid Build Coastguard Worker	// check that each response was correct
610*333d2b36SAndroid Build Coastguard Worker	for i := 0; i < numTests; i++ {
611*333d2b36SAndroid Build Coastguard Worker		testRun := <-testRuns
612*333d2b36SAndroid Build Coastguard Worker		fs.AssertSameResponse(t, testRun.foundMatches, testRun.correctMatches)
613*333d2b36SAndroid Build Coastguard Worker	}
614*333d2b36SAndroid Build Coastguard Worker}
615*333d2b36SAndroid Build Coastguard Worker
616*333d2b36SAndroid Build Coastguard Workerfunc TestStrangelyFormattedPaths(t *testing.T) {
617*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
618*333d2b36SAndroid Build Coastguard Worker
619*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", filesystem)
620*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
621*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/findme.txt", filesystem)
622*333d2b36SAndroid Build Coastguard Worker
623*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
624*333d2b36SAndroid Build Coastguard Worker		t,
625*333d2b36SAndroid Build Coastguard Worker		filesystem,
626*333d2b36SAndroid Build Coastguard Worker		CacheParams{
627*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"//tmp//a//.."},
628*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
629*333d2b36SAndroid Build Coastguard Worker		},
630*333d2b36SAndroid Build Coastguard Worker	)
631*333d2b36SAndroid Build Coastguard Worker	defer finder.Shutdown()
632*333d2b36SAndroid Build Coastguard Worker
633*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("//tmp//a//..", "findme.txt")
634*333d2b36SAndroid Build Coastguard Worker
635*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
636*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/a/findme.txt",
637*333d2b36SAndroid Build Coastguard Worker			"/tmp/b/findme.txt",
638*333d2b36SAndroid Build Coastguard Worker			"/tmp/findme.txt"})
639*333d2b36SAndroid Build Coastguard Worker}
640*333d2b36SAndroid Build Coastguard Worker
641*333d2b36SAndroid Build Coastguard Workerfunc TestCorruptedCacheHeader(t *testing.T) {
642*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
643*333d2b36SAndroid Build Coastguard Worker
644*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", filesystem)
645*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
646*333d2b36SAndroid Build Coastguard Worker	fs.Write(t, "/finder/finder-db", "sample header", filesystem)
647*333d2b36SAndroid Build Coastguard Worker
648*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
649*333d2b36SAndroid Build Coastguard Worker		t,
650*333d2b36SAndroid Build Coastguard Worker		filesystem,
651*333d2b36SAndroid Build Coastguard Worker		CacheParams{
652*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
653*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
654*333d2b36SAndroid Build Coastguard Worker		},
655*333d2b36SAndroid Build Coastguard Worker	)
656*333d2b36SAndroid Build Coastguard Worker	defer finder.Shutdown()
657*333d2b36SAndroid Build Coastguard Worker
658*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
659*333d2b36SAndroid Build Coastguard Worker
660*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
661*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/a/findme.txt",
662*333d2b36SAndroid Build Coastguard Worker			"/tmp/findme.txt"})
663*333d2b36SAndroid Build Coastguard Worker}
664*333d2b36SAndroid Build Coastguard Worker
665*333d2b36SAndroid Build Coastguard Workerfunc TestCanUseCache(t *testing.T) {
666*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
667*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
668*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", filesystem)
669*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
670*333d2b36SAndroid Build Coastguard Worker
671*333d2b36SAndroid Build Coastguard Worker	// run the first finder
672*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
673*333d2b36SAndroid Build Coastguard Worker		t,
674*333d2b36SAndroid Build Coastguard Worker		filesystem,
675*333d2b36SAndroid Build Coastguard Worker		CacheParams{
676*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
677*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
678*333d2b36SAndroid Build Coastguard Worker		},
679*333d2b36SAndroid Build Coastguard Worker	)
680*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
681*333d2b36SAndroid Build Coastguard Worker	// check the response of the first finder
682*333d2b36SAndroid Build Coastguard Worker	correctResponse := []string{"/tmp/a/findme.txt",
683*333d2b36SAndroid Build Coastguard Worker		"/tmp/findme.txt"}
684*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, correctResponse)
685*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
686*333d2b36SAndroid Build Coastguard Worker
687*333d2b36SAndroid Build Coastguard Worker	// check results
688*333d2b36SAndroid Build Coastguard Worker	cacheText := fs.Read(t, finder.DbPath, filesystem)
689*333d2b36SAndroid Build Coastguard Worker	if len(cacheText) < 1 {
690*333d2b36SAndroid Build Coastguard Worker		t.Fatalf("saved cache db is empty\n")
691*333d2b36SAndroid Build Coastguard Worker	}
692*333d2b36SAndroid Build Coastguard Worker	if len(filesystem.StatCalls) == 0 {
693*333d2b36SAndroid Build Coastguard Worker		t.Fatal("No Stat calls recorded by mock filesystem")
694*333d2b36SAndroid Build Coastguard Worker	}
695*333d2b36SAndroid Build Coastguard Worker	if len(filesystem.ReadDirCalls) == 0 {
696*333d2b36SAndroid Build Coastguard Worker		t.Fatal("No ReadDir calls recorded by filesystem")
697*333d2b36SAndroid Build Coastguard Worker	}
698*333d2b36SAndroid Build Coastguard Worker	statCalls := filesystem.StatCalls
699*333d2b36SAndroid Build Coastguard Worker	filesystem.ClearMetrics()
700*333d2b36SAndroid Build Coastguard Worker
701*333d2b36SAndroid Build Coastguard Worker	// run the second finder
702*333d2b36SAndroid Build Coastguard Worker	finder2 := finderWithSameParams(t, finder)
703*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
704*333d2b36SAndroid Build Coastguard Worker	// check results
705*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{})
706*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, filesystem.StatCalls, statCalls)
707*333d2b36SAndroid Build Coastguard Worker
708*333d2b36SAndroid Build Coastguard Worker	finder2.Shutdown()
709*333d2b36SAndroid Build Coastguard Worker}
710*333d2b36SAndroid Build Coastguard Worker
711*333d2b36SAndroid Build Coastguard Workerfunc TestCorruptedCacheBody(t *testing.T) {
712*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
713*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
714*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", filesystem)
715*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
716*333d2b36SAndroid Build Coastguard Worker
717*333d2b36SAndroid Build Coastguard Worker	// run the first finder
718*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
719*333d2b36SAndroid Build Coastguard Worker		t,
720*333d2b36SAndroid Build Coastguard Worker		filesystem,
721*333d2b36SAndroid Build Coastguard Worker		CacheParams{
722*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
723*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
724*333d2b36SAndroid Build Coastguard Worker		},
725*333d2b36SAndroid Build Coastguard Worker	)
726*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
727*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
728*333d2b36SAndroid Build Coastguard Worker
729*333d2b36SAndroid Build Coastguard Worker	// check the response of the first finder
730*333d2b36SAndroid Build Coastguard Worker	correctResponse := []string{"/tmp/a/findme.txt",
731*333d2b36SAndroid Build Coastguard Worker		"/tmp/findme.txt"}
732*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, correctResponse)
733*333d2b36SAndroid Build Coastguard Worker	numStatCalls := len(filesystem.StatCalls)
734*333d2b36SAndroid Build Coastguard Worker	numReadDirCalls := len(filesystem.ReadDirCalls)
735*333d2b36SAndroid Build Coastguard Worker
736*333d2b36SAndroid Build Coastguard Worker	// load the cache file, corrupt it, and save it
737*333d2b36SAndroid Build Coastguard Worker	cacheReader, err := filesystem.Open(finder.DbPath)
738*333d2b36SAndroid Build Coastguard Worker	if err != nil {
739*333d2b36SAndroid Build Coastguard Worker		t.Fatal(err)
740*333d2b36SAndroid Build Coastguard Worker	}
741*333d2b36SAndroid Build Coastguard Worker	cacheData, err := ioutil.ReadAll(cacheReader)
742*333d2b36SAndroid Build Coastguard Worker	if err != nil {
743*333d2b36SAndroid Build Coastguard Worker		t.Fatal(err)
744*333d2b36SAndroid Build Coastguard Worker	}
745*333d2b36SAndroid Build Coastguard Worker	cacheData = append(cacheData, []byte("DontMindMe")...)
746*333d2b36SAndroid Build Coastguard Worker	filesystem.WriteFile(finder.DbPath, cacheData, 0777)
747*333d2b36SAndroid Build Coastguard Worker	filesystem.ClearMetrics()
748*333d2b36SAndroid Build Coastguard Worker
749*333d2b36SAndroid Build Coastguard Worker	// run the second finder
750*333d2b36SAndroid Build Coastguard Worker	finder2 := finderWithSameParams(t, finder)
751*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
752*333d2b36SAndroid Build Coastguard Worker	// check results
753*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, correctResponse)
754*333d2b36SAndroid Build Coastguard Worker	numNewStatCalls := len(filesystem.StatCalls)
755*333d2b36SAndroid Build Coastguard Worker	numNewReadDirCalls := len(filesystem.ReadDirCalls)
756*333d2b36SAndroid Build Coastguard Worker	// It's permissable to make more Stat calls with a corrupted cache because
757*333d2b36SAndroid Build Coastguard Worker	// the Finder may restart once it detects corruption.
758*333d2b36SAndroid Build Coastguard Worker	// However, it may have already issued many Stat calls.
759*333d2b36SAndroid Build Coastguard Worker	// Because a corrupted db is not expected to be a common (or even a supported case),
760*333d2b36SAndroid Build Coastguard Worker	// we don't care to optimize it and don't cache the already-issued Stat calls
761*333d2b36SAndroid Build Coastguard Worker	if numNewReadDirCalls < numReadDirCalls {
762*333d2b36SAndroid Build Coastguard Worker		t.Fatalf(
763*333d2b36SAndroid Build Coastguard Worker			"Finder made fewer ReadDir calls with a corrupted cache (%v calls) than with no cache"+
764*333d2b36SAndroid Build Coastguard Worker				" (%v calls)",
765*333d2b36SAndroid Build Coastguard Worker			numNewReadDirCalls, numReadDirCalls)
766*333d2b36SAndroid Build Coastguard Worker	}
767*333d2b36SAndroid Build Coastguard Worker	if numNewStatCalls < numStatCalls {
768*333d2b36SAndroid Build Coastguard Worker		t.Fatalf(
769*333d2b36SAndroid Build Coastguard Worker			"Finder made fewer Stat calls with a corrupted cache (%v calls) than with no cache (%v calls)",
770*333d2b36SAndroid Build Coastguard Worker			numNewStatCalls, numStatCalls)
771*333d2b36SAndroid Build Coastguard Worker	}
772*333d2b36SAndroid Build Coastguard Worker	finder2.Shutdown()
773*333d2b36SAndroid Build Coastguard Worker}
774*333d2b36SAndroid Build Coastguard Worker
775*333d2b36SAndroid Build Coastguard Workerfunc TestStatCalls(t *testing.T) {
776*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
777*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
778*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
779*333d2b36SAndroid Build Coastguard Worker
780*333d2b36SAndroid Build Coastguard Worker	// run finder
781*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
782*333d2b36SAndroid Build Coastguard Worker		t,
783*333d2b36SAndroid Build Coastguard Worker		filesystem,
784*333d2b36SAndroid Build Coastguard Worker		CacheParams{
785*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
786*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
787*333d2b36SAndroid Build Coastguard Worker		},
788*333d2b36SAndroid Build Coastguard Worker	)
789*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
790*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
791*333d2b36SAndroid Build Coastguard Worker
792*333d2b36SAndroid Build Coastguard Worker	// check response
793*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/findme.txt"})
794*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameStatCalls(t, filesystem.StatCalls, []string{"/tmp", "/tmp/a"})
795*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp", "/tmp/a"})
796*333d2b36SAndroid Build Coastguard Worker}
797*333d2b36SAndroid Build Coastguard Worker
798*333d2b36SAndroid Build Coastguard Workerfunc TestFileAdded(t *testing.T) {
799*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
800*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
801*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/ignoreme.txt", filesystem)
802*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
803*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/ignore.txt", filesystem)
804*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/c/nope.txt", filesystem)
805*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/c/d/irrelevant.txt", filesystem)
806*333d2b36SAndroid Build Coastguard Worker
807*333d2b36SAndroid Build Coastguard Worker	// run the first finder
808*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
809*333d2b36SAndroid Build Coastguard Worker		t,
810*333d2b36SAndroid Build Coastguard Worker		filesystem,
811*333d2b36SAndroid Build Coastguard Worker		CacheParams{
812*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
813*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
814*333d2b36SAndroid Build Coastguard Worker		},
815*333d2b36SAndroid Build Coastguard Worker	)
816*333d2b36SAndroid Build Coastguard Worker	finder.WaitForDbDump()
817*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
818*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
819*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
820*333d2b36SAndroid Build Coastguard Worker	// check the response of the first finder
821*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/findme.txt"})
822*333d2b36SAndroid Build Coastguard Worker
823*333d2b36SAndroid Build Coastguard Worker	// modify the filesystem
824*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
825*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/c/findme.txt", filesystem)
826*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
827*333d2b36SAndroid Build Coastguard Worker	filesystem.ClearMetrics()
828*333d2b36SAndroid Build Coastguard Worker
829*333d2b36SAndroid Build Coastguard Worker	// run the second finder
830*333d2b36SAndroid Build Coastguard Worker	finder2 := finderWithSameParams(t, finder)
831*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
832*333d2b36SAndroid Build Coastguard Worker
833*333d2b36SAndroid Build Coastguard Worker	// check results
834*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/findme.txt", "/tmp/b/c/findme.txt"})
835*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameStatCalls(t, filesystem.StatCalls, []string{"/tmp", "/tmp/a", "/tmp/b", "/tmp/b/c", "/tmp/b/c/d"})
836*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp/b/c"})
837*333d2b36SAndroid Build Coastguard Worker	finder2.Shutdown()
838*333d2b36SAndroid Build Coastguard Worker
839*333d2b36SAndroid Build Coastguard Worker}
840*333d2b36SAndroid Build Coastguard Worker
841*333d2b36SAndroid Build Coastguard Workerfunc TestDirectoriesAdded(t *testing.T) {
842*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
843*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
844*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/ignoreme.txt", filesystem)
845*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
846*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/ignore.txt", filesystem)
847*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/c/nope.txt", filesystem)
848*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/c/d/irrelevant.txt", filesystem)
849*333d2b36SAndroid Build Coastguard Worker
850*333d2b36SAndroid Build Coastguard Worker	// run the first finder
851*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
852*333d2b36SAndroid Build Coastguard Worker		t,
853*333d2b36SAndroid Build Coastguard Worker		filesystem,
854*333d2b36SAndroid Build Coastguard Worker		CacheParams{
855*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
856*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
857*333d2b36SAndroid Build Coastguard Worker		},
858*333d2b36SAndroid Build Coastguard Worker	)
859*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
860*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
861*333d2b36SAndroid Build Coastguard Worker	// check the response of the first finder
862*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/findme.txt"})
863*333d2b36SAndroid Build Coastguard Worker
864*333d2b36SAndroid Build Coastguard Worker	// modify the filesystem
865*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
866*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/c/new/findme.txt", filesystem)
867*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/c/new/new2/findme.txt", filesystem)
868*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/c/new/new2/ignoreme.txt", filesystem)
869*333d2b36SAndroid Build Coastguard Worker	filesystem.ClearMetrics()
870*333d2b36SAndroid Build Coastguard Worker
871*333d2b36SAndroid Build Coastguard Worker	// run the second finder
872*333d2b36SAndroid Build Coastguard Worker	finder2 := finderWithSameParams(t, finder)
873*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
874*333d2b36SAndroid Build Coastguard Worker
875*333d2b36SAndroid Build Coastguard Worker	// check results
876*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
877*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/a/findme.txt", "/tmp/b/c/new/findme.txt", "/tmp/b/c/new/new2/findme.txt"})
878*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameStatCalls(t, filesystem.StatCalls,
879*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp", "/tmp/a", "/tmp/b", "/tmp/b/c", "/tmp/b/c/d", "/tmp/b/c/new", "/tmp/b/c/new/new2"})
880*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp/b/c", "/tmp/b/c/new", "/tmp/b/c/new/new2"})
881*333d2b36SAndroid Build Coastguard Worker
882*333d2b36SAndroid Build Coastguard Worker	finder2.Shutdown()
883*333d2b36SAndroid Build Coastguard Worker}
884*333d2b36SAndroid Build Coastguard Worker
885*333d2b36SAndroid Build Coastguard Workerfunc TestDirectoryAndSubdirectoryBothUpdated(t *testing.T) {
886*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
887*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
888*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/hi1.txt", filesystem)
889*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/hi1.txt", filesystem)
890*333d2b36SAndroid Build Coastguard Worker
891*333d2b36SAndroid Build Coastguard Worker	// run the first finder
892*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
893*333d2b36SAndroid Build Coastguard Worker		t,
894*333d2b36SAndroid Build Coastguard Worker		filesystem,
895*333d2b36SAndroid Build Coastguard Worker		CacheParams{
896*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
897*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"hi1.txt", "hi2.txt"},
898*333d2b36SAndroid Build Coastguard Worker		},
899*333d2b36SAndroid Build Coastguard Worker	)
900*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "hi1.txt")
901*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
902*333d2b36SAndroid Build Coastguard Worker	// check the response of the first finder
903*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/hi1.txt", "/tmp/a/hi1.txt"})
904*333d2b36SAndroid Build Coastguard Worker
905*333d2b36SAndroid Build Coastguard Worker	// modify the filesystem
906*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
907*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/hi2.txt", filesystem)
908*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/hi2.txt", filesystem)
909*333d2b36SAndroid Build Coastguard Worker	filesystem.ClearMetrics()
910*333d2b36SAndroid Build Coastguard Worker
911*333d2b36SAndroid Build Coastguard Worker	// run the second finder
912*333d2b36SAndroid Build Coastguard Worker	finder2 := finderWithSameParams(t, finder)
913*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder2.FindAll()
914*333d2b36SAndroid Build Coastguard Worker
915*333d2b36SAndroid Build Coastguard Worker	// check results
916*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
917*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/hi1.txt", "/tmp/hi2.txt", "/tmp/a/hi1.txt", "/tmp/a/hi2.txt"})
918*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameStatCalls(t, filesystem.StatCalls,
919*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp", "/tmp/a"})
920*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp", "/tmp/a"})
921*333d2b36SAndroid Build Coastguard Worker
922*333d2b36SAndroid Build Coastguard Worker	finder2.Shutdown()
923*333d2b36SAndroid Build Coastguard Worker}
924*333d2b36SAndroid Build Coastguard Worker
925*333d2b36SAndroid Build Coastguard Workerfunc TestFileDeleted(t *testing.T) {
926*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
927*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
928*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/ignoreme.txt", filesystem)
929*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
930*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/findme.txt", filesystem)
931*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/c/nope.txt", filesystem)
932*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/c/d/irrelevant.txt", filesystem)
933*333d2b36SAndroid Build Coastguard Worker
934*333d2b36SAndroid Build Coastguard Worker	// run the first finder
935*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
936*333d2b36SAndroid Build Coastguard Worker		t,
937*333d2b36SAndroid Build Coastguard Worker		filesystem,
938*333d2b36SAndroid Build Coastguard Worker		CacheParams{
939*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
940*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
941*333d2b36SAndroid Build Coastguard Worker		},
942*333d2b36SAndroid Build Coastguard Worker	)
943*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
944*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
945*333d2b36SAndroid Build Coastguard Worker	// check the response of the first finder
946*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/findme.txt", "/tmp/b/findme.txt"})
947*333d2b36SAndroid Build Coastguard Worker
948*333d2b36SAndroid Build Coastguard Worker	// modify the filesystem
949*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
950*333d2b36SAndroid Build Coastguard Worker	fs.Delete(t, "/tmp/b/findme.txt", filesystem)
951*333d2b36SAndroid Build Coastguard Worker	filesystem.ClearMetrics()
952*333d2b36SAndroid Build Coastguard Worker
953*333d2b36SAndroid Build Coastguard Worker	// run the second finder
954*333d2b36SAndroid Build Coastguard Worker	finder2 := finderWithSameParams(t, finder)
955*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
956*333d2b36SAndroid Build Coastguard Worker
957*333d2b36SAndroid Build Coastguard Worker	// check results
958*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/findme.txt"})
959*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameStatCalls(t, filesystem.StatCalls, []string{"/tmp", "/tmp/a", "/tmp/b", "/tmp/b/c", "/tmp/b/c/d"})
960*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp/b"})
961*333d2b36SAndroid Build Coastguard Worker
962*333d2b36SAndroid Build Coastguard Worker	finder2.Shutdown()
963*333d2b36SAndroid Build Coastguard Worker}
964*333d2b36SAndroid Build Coastguard Worker
965*333d2b36SAndroid Build Coastguard Workerfunc TestDirectoriesDeleted(t *testing.T) {
966*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
967*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
968*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", filesystem)
969*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
970*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/1/findme.txt", filesystem)
971*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/1/2/findme.txt", filesystem)
972*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/findme.txt", filesystem)
973*333d2b36SAndroid Build Coastguard Worker
974*333d2b36SAndroid Build Coastguard Worker	// run the first finder
975*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
976*333d2b36SAndroid Build Coastguard Worker		t,
977*333d2b36SAndroid Build Coastguard Worker		filesystem,
978*333d2b36SAndroid Build Coastguard Worker		CacheParams{
979*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
980*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
981*333d2b36SAndroid Build Coastguard Worker		},
982*333d2b36SAndroid Build Coastguard Worker	)
983*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
984*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
985*333d2b36SAndroid Build Coastguard Worker	// check the response of the first finder
986*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
987*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/findme.txt",
988*333d2b36SAndroid Build Coastguard Worker			"/tmp/a/findme.txt",
989*333d2b36SAndroid Build Coastguard Worker			"/tmp/a/1/findme.txt",
990*333d2b36SAndroid Build Coastguard Worker			"/tmp/a/1/2/findme.txt",
991*333d2b36SAndroid Build Coastguard Worker			"/tmp/b/findme.txt"})
992*333d2b36SAndroid Build Coastguard Worker
993*333d2b36SAndroid Build Coastguard Worker	// modify the filesystem
994*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
995*333d2b36SAndroid Build Coastguard Worker	fs.RemoveAll(t, "/tmp/a/1", filesystem)
996*333d2b36SAndroid Build Coastguard Worker	filesystem.ClearMetrics()
997*333d2b36SAndroid Build Coastguard Worker
998*333d2b36SAndroid Build Coastguard Worker	// run the second finder
999*333d2b36SAndroid Build Coastguard Worker	finder2 := finderWithSameParams(t, finder)
1000*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
1001*333d2b36SAndroid Build Coastguard Worker
1002*333d2b36SAndroid Build Coastguard Worker	// check results
1003*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
1004*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/findme.txt", "/tmp/a/findme.txt", "/tmp/b/findme.txt"})
1005*333d2b36SAndroid Build Coastguard Worker	// Technically, we don't care whether /tmp/a/1/2 gets Statted or gets skipped
1006*333d2b36SAndroid Build Coastguard Worker	// if the Finder detects the nonexistence of /tmp/a/1
1007*333d2b36SAndroid Build Coastguard Worker	// However, when resuming from cache, we don't want the Finder to necessarily wait
1008*333d2b36SAndroid Build Coastguard Worker	// to stat a directory until after statting its parent.
1009*333d2b36SAndroid Build Coastguard Worker	// So here we just include /tmp/a/1/2 in the list.
1010*333d2b36SAndroid Build Coastguard Worker	// The Finder is currently implemented to always restat every dir and
1011*333d2b36SAndroid Build Coastguard Worker	// to not short-circuit due to nonexistence of parents (but it will remove
1012*333d2b36SAndroid Build Coastguard Worker	// missing dirs from the cache for next time)
1013*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameStatCalls(t, filesystem.StatCalls,
1014*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp", "/tmp/a", "/tmp/a/1", "/tmp/a/1/2", "/tmp/b"})
1015*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp/a"})
1016*333d2b36SAndroid Build Coastguard Worker
1017*333d2b36SAndroid Build Coastguard Worker	finder2.Shutdown()
1018*333d2b36SAndroid Build Coastguard Worker}
1019*333d2b36SAndroid Build Coastguard Worker
1020*333d2b36SAndroid Build Coastguard Workerfunc TestDirectoriesMoved(t *testing.T) {
1021*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
1022*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
1023*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", filesystem)
1024*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
1025*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/1/findme.txt", filesystem)
1026*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/1/2/findme.txt", filesystem)
1027*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/findme.txt", filesystem)
1028*333d2b36SAndroid Build Coastguard Worker
1029*333d2b36SAndroid Build Coastguard Worker	// run the first finder
1030*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
1031*333d2b36SAndroid Build Coastguard Worker		t,
1032*333d2b36SAndroid Build Coastguard Worker		filesystem,
1033*333d2b36SAndroid Build Coastguard Worker		CacheParams{
1034*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
1035*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
1036*333d2b36SAndroid Build Coastguard Worker		},
1037*333d2b36SAndroid Build Coastguard Worker	)
1038*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
1039*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
1040*333d2b36SAndroid Build Coastguard Worker	// check the response of the first finder
1041*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
1042*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/findme.txt",
1043*333d2b36SAndroid Build Coastguard Worker			"/tmp/a/findme.txt",
1044*333d2b36SAndroid Build Coastguard Worker			"/tmp/a/1/findme.txt",
1045*333d2b36SAndroid Build Coastguard Worker			"/tmp/a/1/2/findme.txt",
1046*333d2b36SAndroid Build Coastguard Worker			"/tmp/b/findme.txt"})
1047*333d2b36SAndroid Build Coastguard Worker
1048*333d2b36SAndroid Build Coastguard Worker	// modify the filesystem
1049*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
1050*333d2b36SAndroid Build Coastguard Worker	fs.Move(t, "/tmp/a", "/tmp/c", filesystem)
1051*333d2b36SAndroid Build Coastguard Worker	filesystem.ClearMetrics()
1052*333d2b36SAndroid Build Coastguard Worker
1053*333d2b36SAndroid Build Coastguard Worker	// run the second finder
1054*333d2b36SAndroid Build Coastguard Worker	finder2 := finderWithSameParams(t, finder)
1055*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
1056*333d2b36SAndroid Build Coastguard Worker
1057*333d2b36SAndroid Build Coastguard Worker	// check results
1058*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
1059*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/findme.txt",
1060*333d2b36SAndroid Build Coastguard Worker			"/tmp/b/findme.txt",
1061*333d2b36SAndroid Build Coastguard Worker			"/tmp/c/findme.txt",
1062*333d2b36SAndroid Build Coastguard Worker			"/tmp/c/1/findme.txt",
1063*333d2b36SAndroid Build Coastguard Worker			"/tmp/c/1/2/findme.txt"})
1064*333d2b36SAndroid Build Coastguard Worker	// Technically, we don't care whether /tmp/a/1/2 gets Statted or gets skipped
1065*333d2b36SAndroid Build Coastguard Worker	// if the Finder detects the nonexistence of /tmp/a/1
1066*333d2b36SAndroid Build Coastguard Worker	// However, when resuming from cache, we don't want the Finder to necessarily wait
1067*333d2b36SAndroid Build Coastguard Worker	// to stat a directory until after statting its parent.
1068*333d2b36SAndroid Build Coastguard Worker	// So here we just include /tmp/a/1/2 in the list.
1069*333d2b36SAndroid Build Coastguard Worker	// The Finder is currently implemented to always restat every dir and
1070*333d2b36SAndroid Build Coastguard Worker	// to not short-circuit due to nonexistence of parents (but it will remove
1071*333d2b36SAndroid Build Coastguard Worker	// missing dirs from the cache for next time)
1072*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameStatCalls(t, filesystem.StatCalls,
1073*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp", "/tmp/a", "/tmp/a/1", "/tmp/a/1/2", "/tmp/b", "/tmp/c", "/tmp/c/1", "/tmp/c/1/2"})
1074*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp", "/tmp/c", "/tmp/c/1", "/tmp/c/1/2"})
1075*333d2b36SAndroid Build Coastguard Worker	finder2.Shutdown()
1076*333d2b36SAndroid Build Coastguard Worker}
1077*333d2b36SAndroid Build Coastguard Worker
1078*333d2b36SAndroid Build Coastguard Workerfunc TestDirectoriesSwapped(t *testing.T) {
1079*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
1080*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
1081*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", filesystem)
1082*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
1083*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/1/findme.txt", filesystem)
1084*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/1/2/findme.txt", filesystem)
1085*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/findme.txt", filesystem)
1086*333d2b36SAndroid Build Coastguard Worker
1087*333d2b36SAndroid Build Coastguard Worker	// run the first finder
1088*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
1089*333d2b36SAndroid Build Coastguard Worker		t,
1090*333d2b36SAndroid Build Coastguard Worker		filesystem,
1091*333d2b36SAndroid Build Coastguard Worker		CacheParams{
1092*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
1093*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
1094*333d2b36SAndroid Build Coastguard Worker		},
1095*333d2b36SAndroid Build Coastguard Worker	)
1096*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
1097*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
1098*333d2b36SAndroid Build Coastguard Worker	// check the response of the first finder
1099*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
1100*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/findme.txt",
1101*333d2b36SAndroid Build Coastguard Worker			"/tmp/a/findme.txt",
1102*333d2b36SAndroid Build Coastguard Worker			"/tmp/a/1/findme.txt",
1103*333d2b36SAndroid Build Coastguard Worker			"/tmp/a/1/2/findme.txt",
1104*333d2b36SAndroid Build Coastguard Worker			"/tmp/b/findme.txt"})
1105*333d2b36SAndroid Build Coastguard Worker
1106*333d2b36SAndroid Build Coastguard Worker	// modify the filesystem
1107*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
1108*333d2b36SAndroid Build Coastguard Worker	fs.Move(t, "/tmp/a", "/tmp/temp", filesystem)
1109*333d2b36SAndroid Build Coastguard Worker	fs.Move(t, "/tmp/b", "/tmp/a", filesystem)
1110*333d2b36SAndroid Build Coastguard Worker	fs.Move(t, "/tmp/temp", "/tmp/b", filesystem)
1111*333d2b36SAndroid Build Coastguard Worker	filesystem.ClearMetrics()
1112*333d2b36SAndroid Build Coastguard Worker
1113*333d2b36SAndroid Build Coastguard Worker	// run the second finder
1114*333d2b36SAndroid Build Coastguard Worker	finder2 := finderWithSameParams(t, finder)
1115*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
1116*333d2b36SAndroid Build Coastguard Worker
1117*333d2b36SAndroid Build Coastguard Worker	// check results
1118*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
1119*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/findme.txt",
1120*333d2b36SAndroid Build Coastguard Worker			"/tmp/a/findme.txt",
1121*333d2b36SAndroid Build Coastguard Worker			"/tmp/b/findme.txt",
1122*333d2b36SAndroid Build Coastguard Worker			"/tmp/b/1/findme.txt",
1123*333d2b36SAndroid Build Coastguard Worker			"/tmp/b/1/2/findme.txt"})
1124*333d2b36SAndroid Build Coastguard Worker	// Technically, we don't care whether /tmp/a/1/2 gets Statted or gets skipped
1125*333d2b36SAndroid Build Coastguard Worker	// if the Finder detects the nonexistence of /tmp/a/1
1126*333d2b36SAndroid Build Coastguard Worker	// However, when resuming from cache, we don't want the Finder to necessarily wait
1127*333d2b36SAndroid Build Coastguard Worker	// to stat a directory until after statting its parent.
1128*333d2b36SAndroid Build Coastguard Worker	// So here we just include /tmp/a/1/2 in the list.
1129*333d2b36SAndroid Build Coastguard Worker	// The Finder is currently implemented to always restat every dir and
1130*333d2b36SAndroid Build Coastguard Worker	// to not short-circuit due to nonexistence of parents (but it will remove
1131*333d2b36SAndroid Build Coastguard Worker	// missing dirs from the cache for next time)
1132*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameStatCalls(t, filesystem.StatCalls,
1133*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp", "/tmp/a", "/tmp/a/1", "/tmp/a/1/2", "/tmp/b", "/tmp/b/1", "/tmp/b/1/2"})
1134*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp", "/tmp/a", "/tmp/b", "/tmp/b/1", "/tmp/b/1/2"})
1135*333d2b36SAndroid Build Coastguard Worker	finder2.Shutdown()
1136*333d2b36SAndroid Build Coastguard Worker}
1137*333d2b36SAndroid Build Coastguard Worker
1138*333d2b36SAndroid Build Coastguard Worker// runFsReplacementTest tests a change modifying properties of the filesystem itself:
1139*333d2b36SAndroid Build Coastguard Worker// runFsReplacementTest tests changing the user, the hostname, or the device number
1140*333d2b36SAndroid Build Coastguard Worker// runFsReplacementTest is a helper method called by other tests
1141*333d2b36SAndroid Build Coastguard Workerfunc runFsReplacementTest(t *testing.T, fs1 *fs.MockFs, fs2 *fs.MockFs) {
1142*333d2b36SAndroid Build Coastguard Worker	// setup fs1
1143*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", fs1)
1144*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", fs1)
1145*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/a/findme.txt", fs1)
1146*333d2b36SAndroid Build Coastguard Worker
1147*333d2b36SAndroid Build Coastguard Worker	// setup fs2 to have the same directories but different files
1148*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", fs2)
1149*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", fs2)
1150*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/a/ignoreme.txt", fs2)
1151*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/b/findme.txt", fs2)
1152*333d2b36SAndroid Build Coastguard Worker
1153*333d2b36SAndroid Build Coastguard Worker	// run the first finder
1154*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
1155*333d2b36SAndroid Build Coastguard Worker		t,
1156*333d2b36SAndroid Build Coastguard Worker		fs1,
1157*333d2b36SAndroid Build Coastguard Worker		CacheParams{
1158*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
1159*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
1160*333d2b36SAndroid Build Coastguard Worker		},
1161*333d2b36SAndroid Build Coastguard Worker	)
1162*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
1163*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
1164*333d2b36SAndroid Build Coastguard Worker	// check the response of the first finder
1165*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
1166*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/findme.txt", "/tmp/a/findme.txt", "/tmp/a/a/findme.txt"})
1167*333d2b36SAndroid Build Coastguard Worker
1168*333d2b36SAndroid Build Coastguard Worker	// copy the cache data from the first filesystem to the second
1169*333d2b36SAndroid Build Coastguard Worker	cacheContent := fs.Read(t, finder.DbPath, fs1)
1170*333d2b36SAndroid Build Coastguard Worker	fs.Write(t, finder.DbPath, cacheContent, fs2)
1171*333d2b36SAndroid Build Coastguard Worker
1172*333d2b36SAndroid Build Coastguard Worker	// run the second finder, with the same config and same cache contents but a different filesystem
1173*333d2b36SAndroid Build Coastguard Worker	finder2 := newFinder(
1174*333d2b36SAndroid Build Coastguard Worker		t,
1175*333d2b36SAndroid Build Coastguard Worker		fs2,
1176*333d2b36SAndroid Build Coastguard Worker		CacheParams{
1177*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
1178*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
1179*333d2b36SAndroid Build Coastguard Worker		},
1180*333d2b36SAndroid Build Coastguard Worker	)
1181*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
1182*333d2b36SAndroid Build Coastguard Worker
1183*333d2b36SAndroid Build Coastguard Worker	// check results
1184*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
1185*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/findme.txt", "/tmp/a/findme.txt", "/tmp/a/b/findme.txt"})
1186*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameStatCalls(t, fs2.StatCalls,
1187*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp", "/tmp/a", "/tmp/a/a", "/tmp/a/b"})
1188*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, fs2.ReadDirCalls,
1189*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp", "/tmp/a", "/tmp/a/a", "/tmp/a/b"})
1190*333d2b36SAndroid Build Coastguard Worker	finder2.Shutdown()
1191*333d2b36SAndroid Build Coastguard Worker}
1192*333d2b36SAndroid Build Coastguard Worker
1193*333d2b36SAndroid Build Coastguard Workerfunc TestChangeOfDevice(t *testing.T) {
1194*333d2b36SAndroid Build Coastguard Worker	fs1 := newFs()
1195*333d2b36SAndroid Build Coastguard Worker	// not as fine-grained mounting controls as a real filesystem, but should be adequate
1196*333d2b36SAndroid Build Coastguard Worker	fs1.SetDeviceNumber(0)
1197*333d2b36SAndroid Build Coastguard Worker
1198*333d2b36SAndroid Build Coastguard Worker	fs2 := newFs()
1199*333d2b36SAndroid Build Coastguard Worker	fs2.SetDeviceNumber(1)
1200*333d2b36SAndroid Build Coastguard Worker
1201*333d2b36SAndroid Build Coastguard Worker	runFsReplacementTest(t, fs1, fs2)
1202*333d2b36SAndroid Build Coastguard Worker}
1203*333d2b36SAndroid Build Coastguard Worker
1204*333d2b36SAndroid Build Coastguard Workerfunc TestChangeOfUserOrHost(t *testing.T) {
1205*333d2b36SAndroid Build Coastguard Worker	fs1 := newFs()
1206*333d2b36SAndroid Build Coastguard Worker	fs1.SetViewId("me@here")
1207*333d2b36SAndroid Build Coastguard Worker
1208*333d2b36SAndroid Build Coastguard Worker	fs2 := newFs()
1209*333d2b36SAndroid Build Coastguard Worker	fs2.SetViewId("you@there")
1210*333d2b36SAndroid Build Coastguard Worker
1211*333d2b36SAndroid Build Coastguard Worker	runFsReplacementTest(t, fs1, fs2)
1212*333d2b36SAndroid Build Coastguard Worker}
1213*333d2b36SAndroid Build Coastguard Worker
1214*333d2b36SAndroid Build Coastguard Workerfunc TestConsistentCacheOrdering(t *testing.T) {
1215*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
1216*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
1217*333d2b36SAndroid Build Coastguard Worker	for i := 0; i < 5; i++ {
1218*333d2b36SAndroid Build Coastguard Worker		fs.Create(t, fmt.Sprintf("/tmp/%v/findme.txt", i), filesystem)
1219*333d2b36SAndroid Build Coastguard Worker	}
1220*333d2b36SAndroid Build Coastguard Worker
1221*333d2b36SAndroid Build Coastguard Worker	// run the first finder
1222*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
1223*333d2b36SAndroid Build Coastguard Worker		t,
1224*333d2b36SAndroid Build Coastguard Worker		filesystem,
1225*333d2b36SAndroid Build Coastguard Worker		CacheParams{
1226*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
1227*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
1228*333d2b36SAndroid Build Coastguard Worker		},
1229*333d2b36SAndroid Build Coastguard Worker	)
1230*333d2b36SAndroid Build Coastguard Worker	finder.FindNamedAt("/tmp", "findme.txt")
1231*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
1232*333d2b36SAndroid Build Coastguard Worker
1233*333d2b36SAndroid Build Coastguard Worker	// read db file
1234*333d2b36SAndroid Build Coastguard Worker	string1 := fs.Read(t, finder.DbPath, filesystem)
1235*333d2b36SAndroid Build Coastguard Worker
1236*333d2b36SAndroid Build Coastguard Worker	err := filesystem.Remove(finder.DbPath)
1237*333d2b36SAndroid Build Coastguard Worker	if err != nil {
1238*333d2b36SAndroid Build Coastguard Worker		t.Fatal(err)
1239*333d2b36SAndroid Build Coastguard Worker	}
1240*333d2b36SAndroid Build Coastguard Worker
1241*333d2b36SAndroid Build Coastguard Worker	// run another finder
1242*333d2b36SAndroid Build Coastguard Worker	finder2 := finderWithSameParams(t, finder)
1243*333d2b36SAndroid Build Coastguard Worker	finder2.FindNamedAt("/tmp", "findme.txt")
1244*333d2b36SAndroid Build Coastguard Worker	finder2.Shutdown()
1245*333d2b36SAndroid Build Coastguard Worker
1246*333d2b36SAndroid Build Coastguard Worker	string2 := fs.Read(t, finder.DbPath, filesystem)
1247*333d2b36SAndroid Build Coastguard Worker
1248*333d2b36SAndroid Build Coastguard Worker	if string1 != string2 {
1249*333d2b36SAndroid Build Coastguard Worker		t.Errorf("Running Finder twice generated two dbs not having identical contents.\n"+
1250*333d2b36SAndroid Build Coastguard Worker			"Content of first file:\n"+
1251*333d2b36SAndroid Build Coastguard Worker			"\n"+
1252*333d2b36SAndroid Build Coastguard Worker			"%v"+
1253*333d2b36SAndroid Build Coastguard Worker			"\n"+
1254*333d2b36SAndroid Build Coastguard Worker			"\n"+
1255*333d2b36SAndroid Build Coastguard Worker			"Content of second file:\n"+
1256*333d2b36SAndroid Build Coastguard Worker			"\n"+
1257*333d2b36SAndroid Build Coastguard Worker			"%v\n"+
1258*333d2b36SAndroid Build Coastguard Worker			"\n",
1259*333d2b36SAndroid Build Coastguard Worker			string1,
1260*333d2b36SAndroid Build Coastguard Worker			string2,
1261*333d2b36SAndroid Build Coastguard Worker		)
1262*333d2b36SAndroid Build Coastguard Worker	}
1263*333d2b36SAndroid Build Coastguard Worker
1264*333d2b36SAndroid Build Coastguard Worker}
1265*333d2b36SAndroid Build Coastguard Worker
1266*333d2b36SAndroid Build Coastguard Workerfunc TestNumSyscallsOfSecondFind(t *testing.T) {
1267*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
1268*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
1269*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", filesystem)
1270*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
1271*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/misc.txt", filesystem)
1272*333d2b36SAndroid Build Coastguard Worker
1273*333d2b36SAndroid Build Coastguard Worker	// set up the finder and run it once
1274*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
1275*333d2b36SAndroid Build Coastguard Worker		t,
1276*333d2b36SAndroid Build Coastguard Worker		filesystem,
1277*333d2b36SAndroid Build Coastguard Worker		CacheParams{
1278*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
1279*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt"},
1280*333d2b36SAndroid Build Coastguard Worker		},
1281*333d2b36SAndroid Build Coastguard Worker	)
1282*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
1283*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/findme.txt", "/tmp/a/findme.txt"})
1284*333d2b36SAndroid Build Coastguard Worker
1285*333d2b36SAndroid Build Coastguard Worker	filesystem.ClearMetrics()
1286*333d2b36SAndroid Build Coastguard Worker
1287*333d2b36SAndroid Build Coastguard Worker	// run the finder again and confirm it doesn't check the filesystem
1288*333d2b36SAndroid Build Coastguard Worker	refoundPaths := finder.FindNamedAt("/tmp", "findme.txt")
1289*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, refoundPaths, foundPaths)
1290*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameStatCalls(t, filesystem.StatCalls, []string{})
1291*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{})
1292*333d2b36SAndroid Build Coastguard Worker
1293*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
1294*333d2b36SAndroid Build Coastguard Worker}
1295*333d2b36SAndroid Build Coastguard Worker
1296*333d2b36SAndroid Build Coastguard Workerfunc TestChangingParamsOfSecondFind(t *testing.T) {
1297*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
1298*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
1299*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/findme.txt", filesystem)
1300*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/findme.txt", filesystem)
1301*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/metoo.txt", filesystem)
1302*333d2b36SAndroid Build Coastguard Worker
1303*333d2b36SAndroid Build Coastguard Worker	// set up the finder and run it once
1304*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
1305*333d2b36SAndroid Build Coastguard Worker		t,
1306*333d2b36SAndroid Build Coastguard Worker		filesystem,
1307*333d2b36SAndroid Build Coastguard Worker		CacheParams{
1308*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
1309*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"findme.txt", "metoo.txt"},
1310*333d2b36SAndroid Build Coastguard Worker		},
1311*333d2b36SAndroid Build Coastguard Worker	)
1312*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
1313*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/findme.txt", "/tmp/a/findme.txt"})
1314*333d2b36SAndroid Build Coastguard Worker
1315*333d2b36SAndroid Build Coastguard Worker	filesystem.ClearMetrics()
1316*333d2b36SAndroid Build Coastguard Worker
1317*333d2b36SAndroid Build Coastguard Worker	// run the finder again and confirm it gets the right answer without asking the filesystem
1318*333d2b36SAndroid Build Coastguard Worker	refoundPaths := finder.FindNamedAt("/tmp", "metoo.txt")
1319*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, refoundPaths, []string{"/tmp/a/metoo.txt"})
1320*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameStatCalls(t, filesystem.StatCalls, []string{})
1321*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{})
1322*333d2b36SAndroid Build Coastguard Worker
1323*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
1324*333d2b36SAndroid Build Coastguard Worker}
1325*333d2b36SAndroid Build Coastguard Worker
1326*333d2b36SAndroid Build Coastguard Workerfunc TestSymlinkPointingToFile(t *testing.T) {
1327*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
1328*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
1329*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/hi.txt", filesystem)
1330*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/ignoreme.txt", filesystem)
1331*333d2b36SAndroid Build Coastguard Worker	fs.Link(t, "/tmp/hi.txt", "a/hi.txt", filesystem)
1332*333d2b36SAndroid Build Coastguard Worker	fs.Link(t, "/tmp/b/hi.txt", "../a/hi.txt", filesystem)
1333*333d2b36SAndroid Build Coastguard Worker	fs.Link(t, "/tmp/c/hi.txt", "/tmp/hi.txt", filesystem)
1334*333d2b36SAndroid Build Coastguard Worker	fs.Link(t, "/tmp/d/hi.txt", "../a/bye.txt", filesystem)
1335*333d2b36SAndroid Build Coastguard Worker	fs.Link(t, "/tmp/d/bye.txt", "../a/hi.txt", filesystem)
1336*333d2b36SAndroid Build Coastguard Worker	fs.Link(t, "/tmp/e/bye.txt", "../a/bye.txt", filesystem)
1337*333d2b36SAndroid Build Coastguard Worker	fs.Link(t, "/tmp/f/hi.txt", "somethingThatDoesntExist", filesystem)
1338*333d2b36SAndroid Build Coastguard Worker
1339*333d2b36SAndroid Build Coastguard Worker	// set up the finder and run it once
1340*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
1341*333d2b36SAndroid Build Coastguard Worker		t,
1342*333d2b36SAndroid Build Coastguard Worker		filesystem,
1343*333d2b36SAndroid Build Coastguard Worker		CacheParams{
1344*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
1345*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"hi.txt"},
1346*333d2b36SAndroid Build Coastguard Worker		},
1347*333d2b36SAndroid Build Coastguard Worker	)
1348*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "hi.txt")
1349*333d2b36SAndroid Build Coastguard Worker	// should search based on the name of the link rather than the destination or validity of the link
1350*333d2b36SAndroid Build Coastguard Worker	correctResponse := []string{
1351*333d2b36SAndroid Build Coastguard Worker		"/tmp/a/hi.txt",
1352*333d2b36SAndroid Build Coastguard Worker		"/tmp/hi.txt",
1353*333d2b36SAndroid Build Coastguard Worker		"/tmp/b/hi.txt",
1354*333d2b36SAndroid Build Coastguard Worker		"/tmp/c/hi.txt",
1355*333d2b36SAndroid Build Coastguard Worker		"/tmp/d/hi.txt",
1356*333d2b36SAndroid Build Coastguard Worker		"/tmp/f/hi.txt",
1357*333d2b36SAndroid Build Coastguard Worker	}
1358*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, correctResponse)
1359*333d2b36SAndroid Build Coastguard Worker
1360*333d2b36SAndroid Build Coastguard Worker}
1361*333d2b36SAndroid Build Coastguard Worker
1362*333d2b36SAndroid Build Coastguard Workerfunc TestSymlinkPointingToDirectory(t *testing.T) {
1363*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
1364*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
1365*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/dir/hi.txt", filesystem)
1366*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/dir/ignoreme.txt", filesystem)
1367*333d2b36SAndroid Build Coastguard Worker
1368*333d2b36SAndroid Build Coastguard Worker	fs.Link(t, "/tmp/links/dir", "../dir", filesystem)
1369*333d2b36SAndroid Build Coastguard Worker	fs.Link(t, "/tmp/links/link", "../dir", filesystem)
1370*333d2b36SAndroid Build Coastguard Worker	fs.Link(t, "/tmp/links/hi.txt", "../dir", filesystem)
1371*333d2b36SAndroid Build Coastguard Worker	fs.Link(t, "/tmp/links/broken", "nothingHere", filesystem)
1372*333d2b36SAndroid Build Coastguard Worker	fs.Link(t, "/tmp/links/recursive", "recursive", filesystem)
1373*333d2b36SAndroid Build Coastguard Worker
1374*333d2b36SAndroid Build Coastguard Worker	// set up the finder and run it once
1375*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
1376*333d2b36SAndroid Build Coastguard Worker		t,
1377*333d2b36SAndroid Build Coastguard Worker		filesystem,
1378*333d2b36SAndroid Build Coastguard Worker		CacheParams{
1379*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
1380*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"hi.txt"},
1381*333d2b36SAndroid Build Coastguard Worker		},
1382*333d2b36SAndroid Build Coastguard Worker	)
1383*333d2b36SAndroid Build Coastguard Worker
1384*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "hi.txt")
1385*333d2b36SAndroid Build Coastguard Worker
1386*333d2b36SAndroid Build Coastguard Worker	// should completely ignore symlinks that point to directories
1387*333d2b36SAndroid Build Coastguard Worker	correctResponse := []string{
1388*333d2b36SAndroid Build Coastguard Worker		"/tmp/dir/hi.txt",
1389*333d2b36SAndroid Build Coastguard Worker	}
1390*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, correctResponse)
1391*333d2b36SAndroid Build Coastguard Worker
1392*333d2b36SAndroid Build Coastguard Worker}
1393*333d2b36SAndroid Build Coastguard Worker
1394*333d2b36SAndroid Build Coastguard Worker// TestAddPruneFile confirms that adding a prune-file (into a directory for which we
1395*333d2b36SAndroid Build Coastguard Worker// already had a cache) causes the directory to be ignored
1396*333d2b36SAndroid Build Coastguard Workerfunc TestAddPruneFile(t *testing.T) {
1397*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
1398*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
1399*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/out/hi.txt", filesystem)
1400*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/out/a/hi.txt", filesystem)
1401*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/hi.txt", filesystem)
1402*333d2b36SAndroid Build Coastguard Worker
1403*333d2b36SAndroid Build Coastguard Worker	// do find
1404*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
1405*333d2b36SAndroid Build Coastguard Worker		t,
1406*333d2b36SAndroid Build Coastguard Worker		filesystem,
1407*333d2b36SAndroid Build Coastguard Worker		CacheParams{
1408*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
1409*333d2b36SAndroid Build Coastguard Worker			PruneFiles:   []string{".ignore-out-dir"},
1410*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"hi.txt"},
1411*333d2b36SAndroid Build Coastguard Worker		},
1412*333d2b36SAndroid Build Coastguard Worker	)
1413*333d2b36SAndroid Build Coastguard Worker
1414*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindNamedAt("/tmp", "hi.txt")
1415*333d2b36SAndroid Build Coastguard Worker
1416*333d2b36SAndroid Build Coastguard Worker	// check result
1417*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths,
1418*333d2b36SAndroid Build Coastguard Worker		[]string{"/tmp/hi.txt",
1419*333d2b36SAndroid Build Coastguard Worker			"/tmp/out/hi.txt",
1420*333d2b36SAndroid Build Coastguard Worker			"/tmp/out/a/hi.txt"},
1421*333d2b36SAndroid Build Coastguard Worker	)
1422*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
1423*333d2b36SAndroid Build Coastguard Worker
1424*333d2b36SAndroid Build Coastguard Worker	// modify filesystem
1425*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
1426*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/out/.ignore-out-dir", filesystem)
1427*333d2b36SAndroid Build Coastguard Worker	// run another find and check its result
1428*333d2b36SAndroid Build Coastguard Worker	finder2 := finderWithSameParams(t, finder)
1429*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder2.FindNamedAt("/tmp", "hi.txt")
1430*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/hi.txt"})
1431*333d2b36SAndroid Build Coastguard Worker	finder2.Shutdown()
1432*333d2b36SAndroid Build Coastguard Worker}
1433*333d2b36SAndroid Build Coastguard Worker
1434*333d2b36SAndroid Build Coastguard Workerfunc TestUpdatingDbIffChanged(t *testing.T) {
1435*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
1436*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
1437*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/hi.txt", filesystem)
1438*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/bye.txt", filesystem)
1439*333d2b36SAndroid Build Coastguard Worker
1440*333d2b36SAndroid Build Coastguard Worker	// run the first finder
1441*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
1442*333d2b36SAndroid Build Coastguard Worker		t,
1443*333d2b36SAndroid Build Coastguard Worker		filesystem,
1444*333d2b36SAndroid Build Coastguard Worker		CacheParams{
1445*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
1446*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"hi.txt"},
1447*333d2b36SAndroid Build Coastguard Worker		},
1448*333d2b36SAndroid Build Coastguard Worker	)
1449*333d2b36SAndroid Build Coastguard Worker	finder.WaitForDbDump()
1450*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
1451*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindAll()
1452*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
1453*333d2b36SAndroid Build Coastguard Worker	// check results
1454*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/hi.txt"})
1455*333d2b36SAndroid Build Coastguard Worker
1456*333d2b36SAndroid Build Coastguard Worker	// modify the filesystem
1457*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
1458*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/hi.txt", filesystem)
1459*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
1460*333d2b36SAndroid Build Coastguard Worker	filesystem.ClearMetrics()
1461*333d2b36SAndroid Build Coastguard Worker
1462*333d2b36SAndroid Build Coastguard Worker	// run the second finder
1463*333d2b36SAndroid Build Coastguard Worker	finder2 := finderWithSameParams(t, finder)
1464*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder2.FindAll()
1465*333d2b36SAndroid Build Coastguard Worker	finder2.Shutdown()
1466*333d2b36SAndroid Build Coastguard Worker	// check results
1467*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/hi.txt", "/tmp/b/hi.txt"})
1468*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp/b"})
1469*333d2b36SAndroid Build Coastguard Worker	expectedDbWriteTime := filesystem.Clock.Time()
1470*333d2b36SAndroid Build Coastguard Worker	actualDbWriteTime := fs.ModTime(t, finder2.DbPath, filesystem)
1471*333d2b36SAndroid Build Coastguard Worker	if actualDbWriteTime != expectedDbWriteTime {
1472*333d2b36SAndroid Build Coastguard Worker		t.Fatalf("Expected to write db at %v, actually wrote db at %v\n",
1473*333d2b36SAndroid Build Coastguard Worker			expectedDbWriteTime, actualDbWriteTime)
1474*333d2b36SAndroid Build Coastguard Worker	}
1475*333d2b36SAndroid Build Coastguard Worker
1476*333d2b36SAndroid Build Coastguard Worker	// reset metrics
1477*333d2b36SAndroid Build Coastguard Worker	filesystem.ClearMetrics()
1478*333d2b36SAndroid Build Coastguard Worker
1479*333d2b36SAndroid Build Coastguard Worker	// run the third finder
1480*333d2b36SAndroid Build Coastguard Worker	finder3 := finderWithSameParams(t, finder2)
1481*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder3.FindAll()
1482*333d2b36SAndroid Build Coastguard Worker
1483*333d2b36SAndroid Build Coastguard Worker	// check results
1484*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/hi.txt", "/tmp/b/hi.txt"})
1485*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{})
1486*333d2b36SAndroid Build Coastguard Worker	finder3.Shutdown()
1487*333d2b36SAndroid Build Coastguard Worker	actualDbWriteTime = fs.ModTime(t, finder3.DbPath, filesystem)
1488*333d2b36SAndroid Build Coastguard Worker	if actualDbWriteTime != expectedDbWriteTime {
1489*333d2b36SAndroid Build Coastguard Worker		t.Fatalf("Re-wrote db even when contents did not change")
1490*333d2b36SAndroid Build Coastguard Worker	}
1491*333d2b36SAndroid Build Coastguard Worker
1492*333d2b36SAndroid Build Coastguard Worker}
1493*333d2b36SAndroid Build Coastguard Worker
1494*333d2b36SAndroid Build Coastguard Workerfunc TestDirectoryNotPermitted(t *testing.T) {
1495*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
1496*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
1497*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/hi.txt", filesystem)
1498*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/hi.txt", filesystem)
1499*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/a/hi.txt", filesystem)
1500*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/b/hi.txt", filesystem)
1501*333d2b36SAndroid Build Coastguard Worker
1502*333d2b36SAndroid Build Coastguard Worker	// run the first finder
1503*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
1504*333d2b36SAndroid Build Coastguard Worker		t,
1505*333d2b36SAndroid Build Coastguard Worker		filesystem,
1506*333d2b36SAndroid Build Coastguard Worker		CacheParams{
1507*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
1508*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"hi.txt"},
1509*333d2b36SAndroid Build Coastguard Worker		},
1510*333d2b36SAndroid Build Coastguard Worker	)
1511*333d2b36SAndroid Build Coastguard Worker	finder.WaitForDbDump()
1512*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
1513*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindAll()
1514*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
1515*333d2b36SAndroid Build Coastguard Worker	allPaths := []string{"/tmp/hi.txt", "/tmp/a/hi.txt", "/tmp/a/a/hi.txt", "/tmp/b/hi.txt"}
1516*333d2b36SAndroid Build Coastguard Worker	// check results
1517*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, allPaths)
1518*333d2b36SAndroid Build Coastguard Worker
1519*333d2b36SAndroid Build Coastguard Worker	// modify the filesystem
1520*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
1521*333d2b36SAndroid Build Coastguard Worker
1522*333d2b36SAndroid Build Coastguard Worker	fs.SetReadable(t, "/tmp/a", false, filesystem)
1523*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
1524*333d2b36SAndroid Build Coastguard Worker
1525*333d2b36SAndroid Build Coastguard Worker	// run the second finder
1526*333d2b36SAndroid Build Coastguard Worker	finder2 := finderWithSameParams(t, finder)
1527*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder2.FindAll()
1528*333d2b36SAndroid Build Coastguard Worker	finder2.Shutdown()
1529*333d2b36SAndroid Build Coastguard Worker	// check results
1530*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/hi.txt", "/tmp/b/hi.txt"})
1531*333d2b36SAndroid Build Coastguard Worker
1532*333d2b36SAndroid Build Coastguard Worker	// modify the filesystem back
1533*333d2b36SAndroid Build Coastguard Worker	fs.SetReadable(t, "/tmp/a", true, filesystem)
1534*333d2b36SAndroid Build Coastguard Worker
1535*333d2b36SAndroid Build Coastguard Worker	// run the third finder
1536*333d2b36SAndroid Build Coastguard Worker	finder3 := finderWithSameParams(t, finder2)
1537*333d2b36SAndroid Build Coastguard Worker	foundPaths = finder3.FindAll()
1538*333d2b36SAndroid Build Coastguard Worker	finder3.Shutdown()
1539*333d2b36SAndroid Build Coastguard Worker	// check results
1540*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, allPaths)
1541*333d2b36SAndroid Build Coastguard Worker}
1542*333d2b36SAndroid Build Coastguard Worker
1543*333d2b36SAndroid Build Coastguard Workerfunc TestFileNotPermitted(t *testing.T) {
1544*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
1545*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
1546*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/hi.txt", filesystem)
1547*333d2b36SAndroid Build Coastguard Worker	fs.SetReadable(t, "/tmp/hi.txt", false, filesystem)
1548*333d2b36SAndroid Build Coastguard Worker
1549*333d2b36SAndroid Build Coastguard Worker	// run the first finder
1550*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
1551*333d2b36SAndroid Build Coastguard Worker		t,
1552*333d2b36SAndroid Build Coastguard Worker		filesystem,
1553*333d2b36SAndroid Build Coastguard Worker		CacheParams{
1554*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
1555*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"hi.txt"},
1556*333d2b36SAndroid Build Coastguard Worker		},
1557*333d2b36SAndroid Build Coastguard Worker	)
1558*333d2b36SAndroid Build Coastguard Worker	finder.WaitForDbDump()
1559*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
1560*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindAll()
1561*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
1562*333d2b36SAndroid Build Coastguard Worker	// check results
1563*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/hi.txt"})
1564*333d2b36SAndroid Build Coastguard Worker}
1565*333d2b36SAndroid Build Coastguard Worker
1566*333d2b36SAndroid Build Coastguard Workerfunc TestCacheEntryPathUnexpectedError(t *testing.T) {
1567*333d2b36SAndroid Build Coastguard Worker	// setup filesystem
1568*333d2b36SAndroid Build Coastguard Worker	filesystem := newFs()
1569*333d2b36SAndroid Build Coastguard Worker	fs.Create(t, "/tmp/a/hi.txt", filesystem)
1570*333d2b36SAndroid Build Coastguard Worker
1571*333d2b36SAndroid Build Coastguard Worker	// run the first finder
1572*333d2b36SAndroid Build Coastguard Worker	finder := newFinder(
1573*333d2b36SAndroid Build Coastguard Worker		t,
1574*333d2b36SAndroid Build Coastguard Worker		filesystem,
1575*333d2b36SAndroid Build Coastguard Worker		CacheParams{
1576*333d2b36SAndroid Build Coastguard Worker			RootDirs:     []string{"/tmp"},
1577*333d2b36SAndroid Build Coastguard Worker			IncludeFiles: []string{"hi.txt"},
1578*333d2b36SAndroid Build Coastguard Worker		},
1579*333d2b36SAndroid Build Coastguard Worker	)
1580*333d2b36SAndroid Build Coastguard Worker	finder.WaitForDbDump()
1581*333d2b36SAndroid Build Coastguard Worker	filesystem.Clock.Tick()
1582*333d2b36SAndroid Build Coastguard Worker	foundPaths := finder.FindAll()
1583*333d2b36SAndroid Build Coastguard Worker	finder.Shutdown()
1584*333d2b36SAndroid Build Coastguard Worker	// check results
1585*333d2b36SAndroid Build Coastguard Worker	fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/hi.txt"})
1586*333d2b36SAndroid Build Coastguard Worker
1587*333d2b36SAndroid Build Coastguard Worker	// make the directory not readable
1588*333d2b36SAndroid Build Coastguard Worker	fs.SetReadErr(t, "/tmp/a", os.ErrInvalid, filesystem)
1589*333d2b36SAndroid Build Coastguard Worker
1590*333d2b36SAndroid Build Coastguard Worker	// run the second finder
1591*333d2b36SAndroid Build Coastguard Worker	_, err := finderAndErrorWithSameParams(t, finder)
1592*333d2b36SAndroid Build Coastguard Worker	if err == nil {
1593*333d2b36SAndroid Build Coastguard Worker		t.Fatal("Failed to detect unexpected filesystem error")
1594*333d2b36SAndroid Build Coastguard Worker	}
1595*333d2b36SAndroid Build Coastguard Worker}
1596