123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590 |
- // Copyright 2017 Google Inc. All rights reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package finder
- import (
- "fmt"
- "io/ioutil"
- "log"
- "os"
- "path/filepath"
- "sort"
- "strings"
- "testing"
- "android/soong/finder/fs"
- )
- // some utils for tests to use
- func newFs() *fs.MockFs {
- return fs.NewMockFs(map[string][]byte{})
- }
- func newFinder(t *testing.T, filesystem *fs.MockFs, cacheParams CacheParams) *Finder {
- return newFinderWithNumThreads(t, filesystem, cacheParams, 2)
- }
- func newFinderWithNumThreads(t *testing.T, filesystem *fs.MockFs, cacheParams CacheParams, numThreads int) *Finder {
- f, err := newFinderAndErr(t, filesystem, cacheParams, numThreads)
- if err != nil {
- t.Fatal(err.Error())
- }
- return f
- }
- func newFinderAndErr(t *testing.T, filesystem *fs.MockFs, cacheParams CacheParams, numThreads int) (*Finder, error) {
- cachePath := "/finder/finder-db"
- cacheDir := filepath.Dir(cachePath)
- filesystem.MkDirs(cacheDir)
- if cacheParams.WorkingDirectory == "" {
- cacheParams.WorkingDirectory = "/cwd"
- }
- logger := log.New(ioutil.Discard, "", 0)
- f, err := newImpl(cacheParams, filesystem, logger, cachePath, numThreads)
- return f, err
- }
- func finderWithSameParams(t *testing.T, original *Finder) *Finder {
- f, err := finderAndErrorWithSameParams(t, original)
- if err != nil {
- t.Fatal(err.Error())
- }
- return f
- }
- func finderAndErrorWithSameParams(t *testing.T, original *Finder) (*Finder, error) {
- f, err := newImpl(
- original.cacheMetadata.Config.CacheParams,
- original.filesystem,
- original.logger,
- original.DbPath,
- original.numDbLoadingThreads,
- )
- return f, err
- }
- // runSimpleTests creates a few files, searches for findme.txt, and checks for the expected matches
- func runSimpleTest(t *testing.T, existentPaths []string, expectedMatches []string) {
- filesystem := newFs()
- root := "/tmp"
- filesystem.MkDirs(root)
- for _, path := range existentPaths {
- fs.Create(t, filepath.Join(root, path), filesystem)
- }
- finder := newFinder(t,
- filesystem,
- CacheParams{
- "/cwd",
- []string{root},
- false,
- nil,
- nil,
- []string{"findme.txt", "skipme.txt"},
- nil,
- },
- )
- defer finder.Shutdown()
- foundPaths := finder.FindNamedAt(root, "findme.txt")
- absoluteMatches := []string{}
- for i := range expectedMatches {
- absoluteMatches = append(absoluteMatches, filepath.Join(root, expectedMatches[i]))
- }
- fs.AssertSameResponse(t, foundPaths, absoluteMatches)
- }
- // runTestWithSuffixes creates a few files, searches for findme.txt or any file
- // with suffix `.findme_ext` and checks for the expected matches
- func runTestWithSuffixes(t *testing.T, existentPaths []string, expectedMatches []string) {
- filesystem := newFs()
- root := "/tmp"
- filesystem.MkDirs(root)
- for _, path := range existentPaths {
- fs.Create(t, filepath.Join(root, path), filesystem)
- }
- finder := newFinder(t,
- filesystem,
- CacheParams{
- "/cwd",
- []string{root},
- false,
- nil,
- nil,
- []string{"findme.txt", "skipme.txt"},
- []string{".findme_ext"},
- },
- )
- defer finder.Shutdown()
- foundPaths := finder.FindMatching(root,
- func(entries DirEntries) (dirs []string, files []string) {
- matches := []string{}
- for _, foundName := range entries.FileNames {
- if foundName == "findme.txt" || strings.HasSuffix(foundName, ".findme_ext") {
- matches = append(matches, foundName)
- }
- }
- return entries.DirNames, matches
- })
- absoluteMatches := []string{}
- for i := range expectedMatches {
- absoluteMatches = append(absoluteMatches, filepath.Join(root, expectedMatches[i]))
- }
- fs.AssertSameResponse(t, foundPaths, absoluteMatches)
- }
- // testAgainstSeveralThreadcounts runs the given test for each threadcount that we care to test
- func testAgainstSeveralThreadcounts(t *testing.T, tester func(t *testing.T, numThreads int)) {
- // test singlethreaded, multithreaded, and also using the same number of threads as
- // will be used on the current system
- threadCounts := []int{1, 2, defaultNumThreads}
- for _, numThreads := range threadCounts {
- testName := fmt.Sprintf("%v threads", numThreads)
- // store numThreads in a new variable to prevent numThreads from changing in each loop
- localNumThreads := numThreads
- t.Run(testName, func(t *testing.T) {
- tester(t, localNumThreads)
- })
- }
- }
- // end of utils, start of individual tests
- func TestSingleFile(t *testing.T) {
- runSimpleTest(t,
- []string{"findme.txt"},
- []string{"findme.txt"},
- )
- }
- func TestIncludeFiles(t *testing.T) {
- runSimpleTest(t,
- []string{"findme.txt", "skipme.txt"},
- []string{"findme.txt"},
- )
- }
- func TestIncludeFilesAndSuffixes(t *testing.T) {
- runTestWithSuffixes(t,
- []string{"findme.txt", "skipme.txt", "alsome.findme_ext"},
- []string{"findme.txt", "alsome.findme_ext"},
- )
- }
- func TestNestedDirectories(t *testing.T) {
- runSimpleTest(t,
- []string{"findme.txt", "skipme.txt", "subdir/findme.txt", "subdir/skipme.txt"},
- []string{"findme.txt", "subdir/findme.txt"},
- )
- }
- func TestNestedDirectoriesWithSuffixes(t *testing.T) {
- runTestWithSuffixes(t,
- []string{"findme.txt", "skipme.txt", "subdir/findme.txt", "subdir/skipme.txt", "subdir/alsome.findme_ext"},
- []string{"findme.txt", "subdir/findme.txt", "subdir/alsome.findme_ext"},
- )
- }
- func TestEmptyDirectory(t *testing.T) {
- runSimpleTest(t,
- []string{},
- []string{},
- )
- }
- func TestEmptyPath(t *testing.T) {
- filesystem := newFs()
- root := "/tmp"
- fs.Create(t, filepath.Join(root, "findme.txt"), filesystem)
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{root},
- IncludeFiles: []string{"findme.txt", "skipme.txt"},
- },
- )
- defer finder.Shutdown()
- foundPaths := finder.FindNamedAt("", "findme.txt")
- fs.AssertSameResponse(t, foundPaths, []string{})
- }
- func TestFilesystemRoot(t *testing.T) {
- testWithNumThreads := func(t *testing.T, numThreads int) {
- filesystem := newFs()
- root := "/"
- createdPath := "/findme.txt"
- fs.Create(t, createdPath, filesystem)
- finder := newFinderWithNumThreads(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{root},
- IncludeFiles: []string{"findme.txt", "skipme.txt"},
- },
- numThreads,
- )
- defer finder.Shutdown()
- foundPaths := finder.FindNamedAt(root, "findme.txt")
- fs.AssertSameResponse(t, foundPaths, []string{createdPath})
- }
- testAgainstSeveralThreadcounts(t, testWithNumThreads)
- }
- func TestNonexistentDir(t *testing.T) {
- filesystem := newFs()
- fs.Create(t, "/tmp/findme.txt", filesystem)
- _, err := newFinderAndErr(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp/IDontExist"},
- IncludeFiles: []string{"findme.txt", "skipme.txt"},
- },
- 1,
- )
- if err == nil {
- t.Fatal("Did not fail when given a nonexistent root directory")
- }
- }
- func TestExcludeDirs(t *testing.T) {
- filesystem := newFs()
- fs.Create(t, "/tmp/exclude/findme.txt", filesystem)
- fs.Create(t, "/tmp/exclude/subdir/findme.txt", filesystem)
- fs.Create(t, "/tmp/subdir/exclude/findme.txt", filesystem)
- fs.Create(t, "/tmp/subdir/subdir/findme.txt", filesystem)
- fs.Create(t, "/tmp/subdir/findme.txt", filesystem)
- fs.Create(t, "/tmp/findme.txt", filesystem)
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- ExcludeDirs: []string{"exclude"},
- IncludeFiles: []string{"findme.txt", "skipme.txt"},
- },
- )
- defer finder.Shutdown()
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/findme.txt",
- "/tmp/subdir/findme.txt",
- "/tmp/subdir/subdir/findme.txt"})
- }
- func TestPruneFiles(t *testing.T) {
- filesystem := newFs()
- fs.Create(t, "/tmp/out/findme.txt", filesystem)
- fs.Create(t, "/tmp/out/.ignore-out-dir", filesystem)
- fs.Create(t, "/tmp/out/child/findme.txt", filesystem)
- fs.Create(t, "/tmp/out2/.ignore-out-dir", filesystem)
- fs.Create(t, "/tmp/out2/sub/findme.txt", filesystem)
- fs.Create(t, "/tmp/findme.txt", filesystem)
- fs.Create(t, "/tmp/include/findme.txt", filesystem)
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- PruneFiles: []string{".ignore-out-dir"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- defer finder.Shutdown()
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/findme.txt",
- "/tmp/include/findme.txt"})
- }
- // TestRootDir tests that the value of RootDirs is used
- // tests of the filesystem root are in TestFilesystemRoot
- func TestRootDir(t *testing.T) {
- filesystem := newFs()
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/subdir/findme.txt", filesystem)
- fs.Create(t, "/tmp/b/findme.txt", filesystem)
- fs.Create(t, "/tmp/b/subdir/findme.txt", filesystem)
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp/a"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- defer finder.Shutdown()
- foundPaths := finder.FindNamedAt("/tmp/a", "findme.txt")
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/a/findme.txt",
- "/tmp/a/subdir/findme.txt"})
- }
- func TestUncachedDir(t *testing.T) {
- filesystem := newFs()
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/subdir/findme.txt", filesystem)
- fs.Create(t, "/tmp/b/findme.txt", filesystem)
- fs.Create(t, "/tmp/b/subdir/findme.txt", filesystem)
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp/b"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp/a", "findme.txt")
- // If the caller queries for a file that is in the cache, then computing the
- // correct answer won't be fast, and it would be easy for the caller to
- // fail to notice its slowness. Instead, we only ever search the cache for files
- // to return, which enforces that we can determine which files will be
- // interesting upfront.
- fs.AssertSameResponse(t, foundPaths, []string{})
- finder.Shutdown()
- }
- func TestSearchingForFilesExcludedFromCache(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/misc.txt", filesystem)
- // set up the finder and run it
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "misc.txt")
- // If the caller queries for a file that is in the cache, then computing the
- // correct answer won't be fast, and it would be easy for the caller to
- // fail to notice its slowness. Instead, we only ever search the cache for files
- // to return, which enforces that we can determine which files will be
- // interesting upfront.
- fs.AssertSameResponse(t, foundPaths, []string{})
- finder.Shutdown()
- }
- func TestRelativeFilePaths(t *testing.T) {
- filesystem := newFs()
- fs.Create(t, "/tmp/ignore/hi.txt", filesystem)
- fs.Create(t, "/tmp/include/hi.txt", filesystem)
- fs.Create(t, "/cwd/hi.txt", filesystem)
- fs.Create(t, "/cwd/a/hi.txt", filesystem)
- fs.Create(t, "/cwd/a/a/hi.txt", filesystem)
- fs.Create(t, "/rel/a/hi.txt", filesystem)
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/cwd", "../rel", "/tmp/include"},
- IncludeFiles: []string{"hi.txt"},
- },
- )
- defer finder.Shutdown()
- foundPaths := finder.FindNamedAt("a", "hi.txt")
- fs.AssertSameResponse(t, foundPaths,
- []string{"a/hi.txt",
- "a/a/hi.txt"})
- foundPaths = finder.FindNamedAt("/tmp/include", "hi.txt")
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/include/hi.txt"})
- foundPaths = finder.FindNamedAt(".", "hi.txt")
- fs.AssertSameResponse(t, foundPaths,
- []string{"hi.txt",
- "a/hi.txt",
- "a/a/hi.txt"})
- foundPaths = finder.FindNamedAt("/rel", "hi.txt")
- fs.AssertSameResponse(t, foundPaths,
- []string{"/rel/a/hi.txt"})
- foundPaths = finder.FindNamedAt("/tmp/include", "hi.txt")
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/include/hi.txt"})
- }
- // have to run this test with the race-detector (`go test -race src/android/soong/finder/*.go`)
- // for there to be much chance of the test actually detecting any error that may be present
- func TestRootDirsContainedInOtherRootDirs(t *testing.T) {
- filesystem := newFs()
- fs.Create(t, "/tmp/a/b/c/d/e/f/g/h/i/j/findme.txt", filesystem)
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/", "/tmp/a/b/c", "/tmp/a/b/c/d/e/f", "/tmp/a/b/c/d/e/f/g/h/i"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- defer finder.Shutdown()
- foundPaths := finder.FindNamedAt("/tmp/a", "findme.txt")
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/a/b/c/d/e/f/g/h/i/j/findme.txt"})
- }
- func TestFindFirst(t *testing.T) {
- filesystem := newFs()
- fs.Create(t, "/tmp/a/hi.txt", filesystem)
- fs.Create(t, "/tmp/b/hi.txt", filesystem)
- fs.Create(t, "/tmp/b/a/hi.txt", filesystem)
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"hi.txt"},
- },
- )
- defer finder.Shutdown()
- foundPaths := finder.FindFirstNamed("hi.txt")
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/a/hi.txt",
- "/tmp/b/hi.txt"},
- )
- }
- func TestConcurrentFindSameDirectory(t *testing.T) {
- testWithNumThreads := func(t *testing.T, numThreads int) {
- filesystem := newFs()
- // create a bunch of files and directories
- paths := []string{}
- for i := 0; i < 10; i++ {
- parentDir := fmt.Sprintf("/tmp/%v", i)
- for j := 0; j < 10; j++ {
- filePath := filepath.Join(parentDir, fmt.Sprintf("%v/findme.txt", j))
- paths = append(paths, filePath)
- }
- }
- sort.Strings(paths)
- for _, path := range paths {
- fs.Create(t, path, filesystem)
- }
- // set up a finder
- finder := newFinderWithNumThreads(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- numThreads,
- )
- defer finder.Shutdown()
- numTests := 20
- results := make(chan []string, numTests)
- // make several parallel calls to the finder
- for i := 0; i < numTests; i++ {
- go func() {
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- results <- foundPaths
- }()
- }
- // check that each response was correct
- for i := 0; i < numTests; i++ {
- foundPaths := <-results
- fs.AssertSameResponse(t, foundPaths, paths)
- }
- }
- testAgainstSeveralThreadcounts(t, testWithNumThreads)
- }
- func TestConcurrentFindDifferentDirectories(t *testing.T) {
- filesystem := newFs()
- // create a bunch of files and directories
- allFiles := []string{}
- numSubdirs := 10
- rootPaths := []string{}
- queryAnswers := [][]string{}
- for i := 0; i < numSubdirs; i++ {
- parentDir := fmt.Sprintf("/tmp/%v", i)
- rootPaths = append(rootPaths, parentDir)
- queryAnswers = append(queryAnswers, []string{})
- for j := 0; j < 10; j++ {
- filePath := filepath.Join(parentDir, fmt.Sprintf("%v/findme.txt", j))
- queryAnswers[i] = append(queryAnswers[i], filePath)
- allFiles = append(allFiles, filePath)
- }
- sort.Strings(queryAnswers[i])
- }
- sort.Strings(allFiles)
- for _, path := range allFiles {
- fs.Create(t, path, filesystem)
- }
- // set up a finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- defer finder.Shutdown()
- type testRun struct {
- path string
- foundMatches []string
- correctMatches []string
- }
- numTests := numSubdirs + 1
- testRuns := make(chan testRun, numTests)
- searchAt := func(path string, correctMatches []string) {
- foundPaths := finder.FindNamedAt(path, "findme.txt")
- testRuns <- testRun{path, foundPaths, correctMatches}
- }
- // make several parallel calls to the finder
- go searchAt("/tmp", allFiles)
- for i := 0; i < len(rootPaths); i++ {
- go searchAt(rootPaths[i], queryAnswers[i])
- }
- // check that each response was correct
- for i := 0; i < numTests; i++ {
- testRun := <-testRuns
- fs.AssertSameResponse(t, testRun.foundMatches, testRun.correctMatches)
- }
- }
- func TestStrangelyFormattedPaths(t *testing.T) {
- filesystem := newFs()
- fs.Create(t, "/tmp/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- fs.Create(t, "/tmp/b/findme.txt", filesystem)
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"//tmp//a//.."},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- defer finder.Shutdown()
- foundPaths := finder.FindNamedAt("//tmp//a//..", "findme.txt")
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/a/findme.txt",
- "/tmp/b/findme.txt",
- "/tmp/findme.txt"})
- }
- func TestCorruptedCacheHeader(t *testing.T) {
- filesystem := newFs()
- fs.Create(t, "/tmp/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- fs.Write(t, "/finder/finder-db", "sample header", filesystem)
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- defer finder.Shutdown()
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/a/findme.txt",
- "/tmp/findme.txt"})
- }
- func TestCanUseCache(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- // run the first finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- // check the response of the first finder
- correctResponse := []string{"/tmp/a/findme.txt",
- "/tmp/findme.txt"}
- fs.AssertSameResponse(t, foundPaths, correctResponse)
- finder.Shutdown()
- // check results
- cacheText := fs.Read(t, finder.DbPath, filesystem)
- if len(cacheText) < 1 {
- t.Fatalf("saved cache db is empty\n")
- }
- if len(filesystem.StatCalls) == 0 {
- t.Fatal("No Stat calls recorded by mock filesystem")
- }
- if len(filesystem.ReadDirCalls) == 0 {
- t.Fatal("No ReadDir calls recorded by filesystem")
- }
- statCalls := filesystem.StatCalls
- filesystem.ClearMetrics()
- // run the second finder
- finder2 := finderWithSameParams(t, finder)
- foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
- // check results
- fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{})
- fs.AssertSameReadDirCalls(t, filesystem.StatCalls, statCalls)
- finder2.Shutdown()
- }
- func TestCorruptedCacheBody(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- // run the first finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- finder.Shutdown()
- // check the response of the first finder
- correctResponse := []string{"/tmp/a/findme.txt",
- "/tmp/findme.txt"}
- fs.AssertSameResponse(t, foundPaths, correctResponse)
- numStatCalls := len(filesystem.StatCalls)
- numReadDirCalls := len(filesystem.ReadDirCalls)
- // load the cache file, corrupt it, and save it
- cacheReader, err := filesystem.Open(finder.DbPath)
- if err != nil {
- t.Fatal(err)
- }
- cacheData, err := ioutil.ReadAll(cacheReader)
- if err != nil {
- t.Fatal(err)
- }
- cacheData = append(cacheData, []byte("DontMindMe")...)
- filesystem.WriteFile(finder.DbPath, cacheData, 0777)
- filesystem.ClearMetrics()
- // run the second finder
- finder2 := finderWithSameParams(t, finder)
- foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
- // check results
- fs.AssertSameResponse(t, foundPaths, correctResponse)
- numNewStatCalls := len(filesystem.StatCalls)
- numNewReadDirCalls := len(filesystem.ReadDirCalls)
- // It's permissable to make more Stat calls with a corrupted cache because
- // the Finder may restart once it detects corruption.
- // However, it may have already issued many Stat calls.
- // Because a corrupted db is not expected to be a common (or even a supported case),
- // we don't care to optimize it and don't cache the already-issued Stat calls
- if numNewReadDirCalls < numReadDirCalls {
- t.Fatalf(
- "Finder made fewer ReadDir calls with a corrupted cache (%v calls) than with no cache"+
- " (%v calls)",
- numNewReadDirCalls, numReadDirCalls)
- }
- if numNewStatCalls < numStatCalls {
- t.Fatalf(
- "Finder made fewer Stat calls with a corrupted cache (%v calls) than with no cache (%v calls)",
- numNewStatCalls, numStatCalls)
- }
- finder2.Shutdown()
- }
- func TestStatCalls(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- // run finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- finder.Shutdown()
- // check response
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/findme.txt"})
- fs.AssertSameStatCalls(t, filesystem.StatCalls, []string{"/tmp", "/tmp/a"})
- fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp", "/tmp/a"})
- }
- func TestFileAdded(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/ignoreme.txt", filesystem)
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- fs.Create(t, "/tmp/b/ignore.txt", filesystem)
- fs.Create(t, "/tmp/b/c/nope.txt", filesystem)
- fs.Create(t, "/tmp/b/c/d/irrelevant.txt", filesystem)
- // run the first finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- filesystem.Clock.Tick()
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- finder.Shutdown()
- // check the response of the first finder
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/findme.txt"})
- // modify the filesystem
- filesystem.Clock.Tick()
- fs.Create(t, "/tmp/b/c/findme.txt", filesystem)
- filesystem.Clock.Tick()
- filesystem.ClearMetrics()
- // run the second finder
- finder2 := finderWithSameParams(t, finder)
- foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
- // check results
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/findme.txt", "/tmp/b/c/findme.txt"})
- fs.AssertSameStatCalls(t, filesystem.StatCalls, []string{"/tmp", "/tmp/a", "/tmp/b", "/tmp/b/c", "/tmp/b/c/d"})
- fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp/b/c"})
- finder2.Shutdown()
- }
- func TestDirectoriesAdded(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/ignoreme.txt", filesystem)
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- fs.Create(t, "/tmp/b/ignore.txt", filesystem)
- fs.Create(t, "/tmp/b/c/nope.txt", filesystem)
- fs.Create(t, "/tmp/b/c/d/irrelevant.txt", filesystem)
- // run the first finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- finder.Shutdown()
- // check the response of the first finder
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/findme.txt"})
- // modify the filesystem
- filesystem.Clock.Tick()
- fs.Create(t, "/tmp/b/c/new/findme.txt", filesystem)
- fs.Create(t, "/tmp/b/c/new/new2/findme.txt", filesystem)
- fs.Create(t, "/tmp/b/c/new/new2/ignoreme.txt", filesystem)
- filesystem.ClearMetrics()
- // run the second finder
- finder2 := finderWithSameParams(t, finder)
- foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
- // check results
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/a/findme.txt", "/tmp/b/c/new/findme.txt", "/tmp/b/c/new/new2/findme.txt"})
- fs.AssertSameStatCalls(t, filesystem.StatCalls,
- []string{"/tmp", "/tmp/a", "/tmp/b", "/tmp/b/c", "/tmp/b/c/d", "/tmp/b/c/new", "/tmp/b/c/new/new2"})
- fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp/b/c", "/tmp/b/c/new", "/tmp/b/c/new/new2"})
- finder2.Shutdown()
- }
- func TestDirectoryAndSubdirectoryBothUpdated(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/hi1.txt", filesystem)
- fs.Create(t, "/tmp/a/hi1.txt", filesystem)
- // run the first finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"hi1.txt", "hi2.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "hi1.txt")
- finder.Shutdown()
- // check the response of the first finder
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/hi1.txt", "/tmp/a/hi1.txt"})
- // modify the filesystem
- filesystem.Clock.Tick()
- fs.Create(t, "/tmp/hi2.txt", filesystem)
- fs.Create(t, "/tmp/a/hi2.txt", filesystem)
- filesystem.ClearMetrics()
- // run the second finder
- finder2 := finderWithSameParams(t, finder)
- foundPaths = finder2.FindAll()
- // check results
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/hi1.txt", "/tmp/hi2.txt", "/tmp/a/hi1.txt", "/tmp/a/hi2.txt"})
- fs.AssertSameStatCalls(t, filesystem.StatCalls,
- []string{"/tmp", "/tmp/a"})
- fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp", "/tmp/a"})
- finder2.Shutdown()
- }
- func TestFileDeleted(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/ignoreme.txt", filesystem)
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- fs.Create(t, "/tmp/b/findme.txt", filesystem)
- fs.Create(t, "/tmp/b/c/nope.txt", filesystem)
- fs.Create(t, "/tmp/b/c/d/irrelevant.txt", filesystem)
- // run the first finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- finder.Shutdown()
- // check the response of the first finder
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/findme.txt", "/tmp/b/findme.txt"})
- // modify the filesystem
- filesystem.Clock.Tick()
- fs.Delete(t, "/tmp/b/findme.txt", filesystem)
- filesystem.ClearMetrics()
- // run the second finder
- finder2 := finderWithSameParams(t, finder)
- foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
- // check results
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/findme.txt"})
- fs.AssertSameStatCalls(t, filesystem.StatCalls, []string{"/tmp", "/tmp/a", "/tmp/b", "/tmp/b/c", "/tmp/b/c/d"})
- fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp/b"})
- finder2.Shutdown()
- }
- func TestDirectoriesDeleted(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/1/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/1/2/findme.txt", filesystem)
- fs.Create(t, "/tmp/b/findme.txt", filesystem)
- // run the first finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- finder.Shutdown()
- // check the response of the first finder
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/findme.txt",
- "/tmp/a/findme.txt",
- "/tmp/a/1/findme.txt",
- "/tmp/a/1/2/findme.txt",
- "/tmp/b/findme.txt"})
- // modify the filesystem
- filesystem.Clock.Tick()
- fs.RemoveAll(t, "/tmp/a/1", filesystem)
- filesystem.ClearMetrics()
- // run the second finder
- finder2 := finderWithSameParams(t, finder)
- foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
- // check results
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/findme.txt", "/tmp/a/findme.txt", "/tmp/b/findme.txt"})
- // Technically, we don't care whether /tmp/a/1/2 gets Statted or gets skipped
- // if the Finder detects the nonexistence of /tmp/a/1
- // However, when resuming from cache, we don't want the Finder to necessarily wait
- // to stat a directory until after statting its parent.
- // So here we just include /tmp/a/1/2 in the list.
- // The Finder is currently implemented to always restat every dir and
- // to not short-circuit due to nonexistence of parents (but it will remove
- // missing dirs from the cache for next time)
- fs.AssertSameStatCalls(t, filesystem.StatCalls,
- []string{"/tmp", "/tmp/a", "/tmp/a/1", "/tmp/a/1/2", "/tmp/b"})
- fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp/a"})
- finder2.Shutdown()
- }
- func TestDirectoriesMoved(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/1/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/1/2/findme.txt", filesystem)
- fs.Create(t, "/tmp/b/findme.txt", filesystem)
- // run the first finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- finder.Shutdown()
- // check the response of the first finder
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/findme.txt",
- "/tmp/a/findme.txt",
- "/tmp/a/1/findme.txt",
- "/tmp/a/1/2/findme.txt",
- "/tmp/b/findme.txt"})
- // modify the filesystem
- filesystem.Clock.Tick()
- fs.Move(t, "/tmp/a", "/tmp/c", filesystem)
- filesystem.ClearMetrics()
- // run the second finder
- finder2 := finderWithSameParams(t, finder)
- foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
- // check results
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/findme.txt",
- "/tmp/b/findme.txt",
- "/tmp/c/findme.txt",
- "/tmp/c/1/findme.txt",
- "/tmp/c/1/2/findme.txt"})
- // Technically, we don't care whether /tmp/a/1/2 gets Statted or gets skipped
- // if the Finder detects the nonexistence of /tmp/a/1
- // However, when resuming from cache, we don't want the Finder to necessarily wait
- // to stat a directory until after statting its parent.
- // So here we just include /tmp/a/1/2 in the list.
- // The Finder is currently implemented to always restat every dir and
- // to not short-circuit due to nonexistence of parents (but it will remove
- // missing dirs from the cache for next time)
- fs.AssertSameStatCalls(t, filesystem.StatCalls,
- []string{"/tmp", "/tmp/a", "/tmp/a/1", "/tmp/a/1/2", "/tmp/b", "/tmp/c", "/tmp/c/1", "/tmp/c/1/2"})
- fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp", "/tmp/c", "/tmp/c/1", "/tmp/c/1/2"})
- finder2.Shutdown()
- }
- func TestDirectoriesSwapped(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/1/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/1/2/findme.txt", filesystem)
- fs.Create(t, "/tmp/b/findme.txt", filesystem)
- // run the first finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- finder.Shutdown()
- // check the response of the first finder
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/findme.txt",
- "/tmp/a/findme.txt",
- "/tmp/a/1/findme.txt",
- "/tmp/a/1/2/findme.txt",
- "/tmp/b/findme.txt"})
- // modify the filesystem
- filesystem.Clock.Tick()
- fs.Move(t, "/tmp/a", "/tmp/temp", filesystem)
- fs.Move(t, "/tmp/b", "/tmp/a", filesystem)
- fs.Move(t, "/tmp/temp", "/tmp/b", filesystem)
- filesystem.ClearMetrics()
- // run the second finder
- finder2 := finderWithSameParams(t, finder)
- foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
- // check results
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/findme.txt",
- "/tmp/a/findme.txt",
- "/tmp/b/findme.txt",
- "/tmp/b/1/findme.txt",
- "/tmp/b/1/2/findme.txt"})
- // Technically, we don't care whether /tmp/a/1/2 gets Statted or gets skipped
- // if the Finder detects the nonexistence of /tmp/a/1
- // However, when resuming from cache, we don't want the Finder to necessarily wait
- // to stat a directory until after statting its parent.
- // So here we just include /tmp/a/1/2 in the list.
- // The Finder is currently implemented to always restat every dir and
- // to not short-circuit due to nonexistence of parents (but it will remove
- // missing dirs from the cache for next time)
- fs.AssertSameStatCalls(t, filesystem.StatCalls,
- []string{"/tmp", "/tmp/a", "/tmp/a/1", "/tmp/a/1/2", "/tmp/b", "/tmp/b/1", "/tmp/b/1/2"})
- fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp", "/tmp/a", "/tmp/b", "/tmp/b/1", "/tmp/b/1/2"})
- finder2.Shutdown()
- }
- // runFsReplacementTest tests a change modifying properties of the filesystem itself:
- // runFsReplacementTest tests changing the user, the hostname, or the device number
- // runFsReplacementTest is a helper method called by other tests
- func runFsReplacementTest(t *testing.T, fs1 *fs.MockFs, fs2 *fs.MockFs) {
- // setup fs1
- fs.Create(t, "/tmp/findme.txt", fs1)
- fs.Create(t, "/tmp/a/findme.txt", fs1)
- fs.Create(t, "/tmp/a/a/findme.txt", fs1)
- // setup fs2 to have the same directories but different files
- fs.Create(t, "/tmp/findme.txt", fs2)
- fs.Create(t, "/tmp/a/findme.txt", fs2)
- fs.Create(t, "/tmp/a/a/ignoreme.txt", fs2)
- fs.Create(t, "/tmp/a/b/findme.txt", fs2)
- // run the first finder
- finder := newFinder(
- t,
- fs1,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- finder.Shutdown()
- // check the response of the first finder
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/findme.txt", "/tmp/a/findme.txt", "/tmp/a/a/findme.txt"})
- // copy the cache data from the first filesystem to the second
- cacheContent := fs.Read(t, finder.DbPath, fs1)
- fs.Write(t, finder.DbPath, cacheContent, fs2)
- // run the second finder, with the same config and same cache contents but a different filesystem
- finder2 := newFinder(
- t,
- fs2,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- foundPaths = finder2.FindNamedAt("/tmp", "findme.txt")
- // check results
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/findme.txt", "/tmp/a/findme.txt", "/tmp/a/b/findme.txt"})
- fs.AssertSameStatCalls(t, fs2.StatCalls,
- []string{"/tmp", "/tmp/a", "/tmp/a/a", "/tmp/a/b"})
- fs.AssertSameReadDirCalls(t, fs2.ReadDirCalls,
- []string{"/tmp", "/tmp/a", "/tmp/a/a", "/tmp/a/b"})
- finder2.Shutdown()
- }
- func TestChangeOfDevice(t *testing.T) {
- fs1 := newFs()
- // not as fine-grained mounting controls as a real filesystem, but should be adequate
- fs1.SetDeviceNumber(0)
- fs2 := newFs()
- fs2.SetDeviceNumber(1)
- runFsReplacementTest(t, fs1, fs2)
- }
- func TestChangeOfUserOrHost(t *testing.T) {
- fs1 := newFs()
- fs1.SetViewId("me@here")
- fs2 := newFs()
- fs2.SetViewId("you@there")
- runFsReplacementTest(t, fs1, fs2)
- }
- func TestConsistentCacheOrdering(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- for i := 0; i < 5; i++ {
- fs.Create(t, fmt.Sprintf("/tmp/%v/findme.txt", i), filesystem)
- }
- // run the first finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- finder.FindNamedAt("/tmp", "findme.txt")
- finder.Shutdown()
- // read db file
- string1 := fs.Read(t, finder.DbPath, filesystem)
- err := filesystem.Remove(finder.DbPath)
- if err != nil {
- t.Fatal(err)
- }
- // run another finder
- finder2 := finderWithSameParams(t, finder)
- finder2.FindNamedAt("/tmp", "findme.txt")
- finder2.Shutdown()
- string2 := fs.Read(t, finder.DbPath, filesystem)
- if string1 != string2 {
- t.Errorf("Running Finder twice generated two dbs not having identical contents.\n"+
- "Content of first file:\n"+
- "\n"+
- "%v"+
- "\n"+
- "\n"+
- "Content of second file:\n"+
- "\n"+
- "%v\n"+
- "\n",
- string1,
- string2,
- )
- }
- }
- func TestNumSyscallsOfSecondFind(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/misc.txt", filesystem)
- // set up the finder and run it once
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/findme.txt", "/tmp/a/findme.txt"})
- filesystem.ClearMetrics()
- // run the finder again and confirm it doesn't check the filesystem
- refoundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- fs.AssertSameResponse(t, refoundPaths, foundPaths)
- fs.AssertSameStatCalls(t, filesystem.StatCalls, []string{})
- fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{})
- finder.Shutdown()
- }
- func TestChangingParamsOfSecondFind(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/findme.txt", filesystem)
- fs.Create(t, "/tmp/a/metoo.txt", filesystem)
- // set up the finder and run it once
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt", "metoo.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/findme.txt", "/tmp/a/findme.txt"})
- filesystem.ClearMetrics()
- // run the finder again and confirm it gets the right answer without asking the filesystem
- refoundPaths := finder.FindNamedAt("/tmp", "metoo.txt")
- fs.AssertSameResponse(t, refoundPaths, []string{"/tmp/a/metoo.txt"})
- fs.AssertSameStatCalls(t, filesystem.StatCalls, []string{})
- fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{})
- finder.Shutdown()
- }
- func TestSymlinkPointingToFile(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/a/hi.txt", filesystem)
- fs.Create(t, "/tmp/a/ignoreme.txt", filesystem)
- fs.Link(t, "/tmp/hi.txt", "a/hi.txt", filesystem)
- fs.Link(t, "/tmp/b/hi.txt", "../a/hi.txt", filesystem)
- fs.Link(t, "/tmp/c/hi.txt", "/tmp/hi.txt", filesystem)
- fs.Link(t, "/tmp/d/hi.txt", "../a/bye.txt", filesystem)
- fs.Link(t, "/tmp/d/bye.txt", "../a/hi.txt", filesystem)
- fs.Link(t, "/tmp/e/bye.txt", "../a/bye.txt", filesystem)
- fs.Link(t, "/tmp/f/hi.txt", "somethingThatDoesntExist", filesystem)
- // set up the finder and run it once
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"hi.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "hi.txt")
- // should search based on the name of the link rather than the destination or validity of the link
- correctResponse := []string{
- "/tmp/a/hi.txt",
- "/tmp/hi.txt",
- "/tmp/b/hi.txt",
- "/tmp/c/hi.txt",
- "/tmp/d/hi.txt",
- "/tmp/f/hi.txt",
- }
- fs.AssertSameResponse(t, foundPaths, correctResponse)
- }
- func TestSymlinkPointingToDirectory(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/dir/hi.txt", filesystem)
- fs.Create(t, "/tmp/dir/ignoreme.txt", filesystem)
- fs.Link(t, "/tmp/links/dir", "../dir", filesystem)
- fs.Link(t, "/tmp/links/link", "../dir", filesystem)
- fs.Link(t, "/tmp/links/hi.txt", "../dir", filesystem)
- fs.Link(t, "/tmp/links/broken", "nothingHere", filesystem)
- fs.Link(t, "/tmp/links/recursive", "recursive", filesystem)
- // set up the finder and run it once
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"hi.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "hi.txt")
- // should completely ignore symlinks that point to directories
- correctResponse := []string{
- "/tmp/dir/hi.txt",
- }
- fs.AssertSameResponse(t, foundPaths, correctResponse)
- }
- // TestAddPruneFile confirms that adding a prune-file (into a directory for which we
- // already had a cache) causes the directory to be ignored
- func TestAddPruneFile(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/out/hi.txt", filesystem)
- fs.Create(t, "/tmp/out/a/hi.txt", filesystem)
- fs.Create(t, "/tmp/hi.txt", filesystem)
- // do find
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- PruneFiles: []string{".ignore-out-dir"},
- IncludeFiles: []string{"hi.txt"},
- },
- )
- foundPaths := finder.FindNamedAt("/tmp", "hi.txt")
- // check result
- fs.AssertSameResponse(t, foundPaths,
- []string{"/tmp/hi.txt",
- "/tmp/out/hi.txt",
- "/tmp/out/a/hi.txt"},
- )
- finder.Shutdown()
- // modify filesystem
- filesystem.Clock.Tick()
- fs.Create(t, "/tmp/out/.ignore-out-dir", filesystem)
- // run another find and check its result
- finder2 := finderWithSameParams(t, finder)
- foundPaths = finder2.FindNamedAt("/tmp", "hi.txt")
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/hi.txt"})
- finder2.Shutdown()
- }
- func TestUpdatingDbIffChanged(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/a/hi.txt", filesystem)
- fs.Create(t, "/tmp/b/bye.txt", filesystem)
- // run the first finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"hi.txt"},
- },
- )
- filesystem.Clock.Tick()
- foundPaths := finder.FindAll()
- finder.Shutdown()
- // check results
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/hi.txt"})
- // modify the filesystem
- filesystem.Clock.Tick()
- fs.Create(t, "/tmp/b/hi.txt", filesystem)
- filesystem.Clock.Tick()
- filesystem.ClearMetrics()
- // run the second finder
- finder2 := finderWithSameParams(t, finder)
- foundPaths = finder2.FindAll()
- finder2.Shutdown()
- // check results
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/hi.txt", "/tmp/b/hi.txt"})
- fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{"/tmp/b"})
- expectedDbWriteTime := filesystem.Clock.Time()
- actualDbWriteTime := fs.ModTime(t, finder2.DbPath, filesystem)
- if actualDbWriteTime != expectedDbWriteTime {
- t.Fatalf("Expected to write db at %v, actually wrote db at %v\n",
- expectedDbWriteTime, actualDbWriteTime)
- }
- // reset metrics
- filesystem.ClearMetrics()
- // run the third finder
- finder3 := finderWithSameParams(t, finder2)
- foundPaths = finder3.FindAll()
- // check results
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/hi.txt", "/tmp/b/hi.txt"})
- fs.AssertSameReadDirCalls(t, filesystem.ReadDirCalls, []string{})
- finder3.Shutdown()
- actualDbWriteTime = fs.ModTime(t, finder3.DbPath, filesystem)
- if actualDbWriteTime != expectedDbWriteTime {
- t.Fatalf("Re-wrote db even when contents did not change")
- }
- }
- func TestDirectoryNotPermitted(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/hi.txt", filesystem)
- fs.Create(t, "/tmp/a/hi.txt", filesystem)
- fs.Create(t, "/tmp/a/a/hi.txt", filesystem)
- fs.Create(t, "/tmp/b/hi.txt", filesystem)
- // run the first finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"hi.txt"},
- },
- )
- filesystem.Clock.Tick()
- foundPaths := finder.FindAll()
- finder.Shutdown()
- allPaths := []string{"/tmp/hi.txt", "/tmp/a/hi.txt", "/tmp/a/a/hi.txt", "/tmp/b/hi.txt"}
- // check results
- fs.AssertSameResponse(t, foundPaths, allPaths)
- // modify the filesystem
- filesystem.Clock.Tick()
- fs.SetReadable(t, "/tmp/a", false, filesystem)
- filesystem.Clock.Tick()
- // run the second finder
- finder2 := finderWithSameParams(t, finder)
- foundPaths = finder2.FindAll()
- finder2.Shutdown()
- // check results
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/hi.txt", "/tmp/b/hi.txt"})
- // modify the filesystem back
- fs.SetReadable(t, "/tmp/a", true, filesystem)
- // run the third finder
- finder3 := finderWithSameParams(t, finder2)
- foundPaths = finder3.FindAll()
- finder3.Shutdown()
- // check results
- fs.AssertSameResponse(t, foundPaths, allPaths)
- }
- func TestFileNotPermitted(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/hi.txt", filesystem)
- fs.SetReadable(t, "/tmp/hi.txt", false, filesystem)
- // run the first finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"hi.txt"},
- },
- )
- filesystem.Clock.Tick()
- foundPaths := finder.FindAll()
- finder.Shutdown()
- // check results
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/hi.txt"})
- }
- func TestCacheEntryPathUnexpectedError(t *testing.T) {
- // setup filesystem
- filesystem := newFs()
- fs.Create(t, "/tmp/a/hi.txt", filesystem)
- // run the first finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"hi.txt"},
- },
- )
- filesystem.Clock.Tick()
- foundPaths := finder.FindAll()
- finder.Shutdown()
- // check results
- fs.AssertSameResponse(t, foundPaths, []string{"/tmp/a/hi.txt"})
- // make the directory not readable
- fs.SetReadErr(t, "/tmp/a", os.ErrInvalid, filesystem)
- // run the second finder
- _, err := finderAndErrorWithSameParams(t, finder)
- if err == nil {
- t.Fatal("Failed to detect unexpected filesystem error")
- }
- }
|