| // Copyright 2016 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 build |
| |
| import ( |
| "fmt" |
| "io/ioutil" |
| "log" |
| "os" |
| "path/filepath" |
| "strings" |
| "testing" |
| "time" |
| |
| "golang.org/x/net/context" |
| |
| "github.com/google/zoekt" |
| "github.com/google/zoekt/query" |
| ) |
| |
| func TestBasic(t *testing.T) { |
| dir, err := ioutil.TempDir("", "") |
| if err != nil { |
| t.Fatalf("TempDir: %v", err) |
| } |
| |
| opts := Options{ |
| IndexDir: dir, |
| ShardMax: 1024, |
| RepositoryDescription: zoekt.Repository{ |
| Name: "repo", |
| }, |
| RepoDir: "/repo", |
| Parallelism: 2, |
| SizeMax: 1 << 20, |
| } |
| |
| b, err := NewBuilder(opts) |
| if err != nil { |
| t.Fatalf("NewBuilder: %v", err) |
| } |
| |
| for i := 0; i < 4; i++ { |
| s := fmt.Sprintf("%d", i) |
| b.AddFile("F"+s, []byte(strings.Repeat(s, 1000))) |
| } |
| |
| b.Finish() |
| |
| fs, _ := filepath.Glob(dir + "/*") |
| if len(fs) <= 1 { |
| t.Fatalf("want multiple shards, got %v", fs) |
| } |
| |
| ss, err := zoekt.NewShardedSearcher(dir) |
| if err != nil { |
| t.Fatalf("NewShardedSearcher(%s): %v", dir, err) |
| } |
| |
| q, err := query.Parse("111") |
| if err != nil { |
| t.Fatalf("Parse(111): %v", err) |
| } |
| |
| var sOpts zoekt.SearchOptions |
| ctx := context.Background() |
| result, err := ss.Search(ctx, q, &sOpts) |
| if err != nil { |
| t.Fatalf("Parse(111): %v", err) |
| } |
| |
| if len(result.Files) != 1 || result.Files[0].FileName != "F1" { |
| t.Errorf("got %v, want 1 file.", result.Files) |
| } |
| defer ss.Close() |
| } |
| |
| func TestUpdate(t *testing.T) { |
| dir, err := ioutil.TempDir("", "") |
| if err != nil { |
| t.Fatalf("TempDir: %v", err) |
| } |
| |
| opts := Options{ |
| IndexDir: dir, |
| ShardMax: 1024, |
| RepositoryDescription: zoekt.Repository{ |
| Name: "repo", |
| FileURLTemplate: "url", |
| }, |
| Parallelism: 2, |
| SizeMax: 1 << 20, |
| |
| RepoDir: "/a", |
| } |
| |
| if b, err := NewBuilder(opts); err != nil { |
| t.Fatalf("NewBuilder: %v", err) |
| } else { |
| b.AddFile("F", []byte("hoi")) |
| b.Finish() |
| } |
| ss, err := zoekt.NewShardedSearcher(dir) |
| if err != nil { |
| t.Fatalf("NewShardedSearcher(%s): %v", dir, err) |
| } |
| |
| ctx := context.Background() |
| repos, err := ss.List(ctx, &query.Repo{Pattern: "repo"}) |
| if err != nil { |
| t.Fatalf("List: %v", err) |
| } |
| |
| if len(repos.Repos) != 1 { |
| t.Errorf("List(repo): got %v, want 1 repo", repos.Repos) |
| } |
| |
| fs, err := filepath.Glob(filepath.Join(dir, "*")) |
| if err != nil { |
| t.Fatalf("glob: %v", err) |
| } |
| |
| opts.RepositoryDescription = zoekt.Repository{ |
| Name: "repo2", |
| FileURLTemplate: "url2", |
| } |
| |
| opts.RepoDir = "/b" |
| if b, err := NewBuilder(opts); err != nil { |
| t.Fatalf("NewBuilder: %v", err) |
| } else { |
| b.AddFile("F", []byte("hoi")) |
| b.Finish() |
| } |
| |
| // This is ugly, and potentially flaky, but there is no |
| // observable synchronization for the Sharded searcher, so |
| // this is the best we can do. |
| time.Sleep(100 * time.Millisecond) |
| |
| ctx = context.Background() |
| if repos, err = ss.List(ctx, &query.Repo{Pattern: "repo"}); err != nil { |
| t.Fatalf("List: %v", err) |
| } else if len(repos.Repos) != 2 { |
| t.Errorf("List(repo): got %v, want 2 repos", repos.Repos) |
| } |
| |
| for _, fn := range fs { |
| log.Printf("removing %s", fn) |
| if err := os.Remove(fn); err != nil { |
| t.Fatalf("Remove(%s): %v", fn, err) |
| } |
| break |
| } |
| |
| time.Sleep(100 * time.Millisecond) |
| |
| ctx = context.Background() |
| if repos, err = ss.List(ctx, &query.Repo{Pattern: "repo"}); err != nil { |
| t.Fatalf("List: %v", err) |
| } else if len(repos.Repos) != 1 { |
| t.Errorf("List(repo): got %v, want 1 repo", repos.Repos) |
| } |
| } |
| |
| func TestDeleteOldShards(t *testing.T) { |
| dir, err := ioutil.TempDir("", "") |
| if err != nil { |
| t.Fatalf("TempDir: %v", err) |
| } |
| |
| opts := Options{ |
| IndexDir: dir, |
| ShardMax: 1024, |
| RepositoryDescription: zoekt.Repository{ |
| Name: "repo", |
| FileURLTemplate: "url", |
| }, |
| RepoDir: "/a", |
| SizeMax: 1 << 20, |
| } |
| opts.SetDefaults() |
| |
| b, err := NewBuilder(opts) |
| if err != nil { |
| t.Fatalf("NewBuilder: %v", err) |
| } |
| for i := 0; i < 4; i++ { |
| s := fmt.Sprintf("%d\n", i) |
| b.AddFile("F"+s, []byte(strings.Repeat(s, 1024/2))) |
| } |
| b.Finish() |
| |
| glob := filepath.Join(dir, "*") |
| fs, err := filepath.Glob(glob) |
| if err != nil { |
| t.Fatalf("Glob(%s): %v", glob, err) |
| } else if len(fs) != 4 { |
| t.Fatalf("Glob(%s): got %v, want 4 shards", glob, fs) |
| } |
| |
| // Do again, without sharding. |
| opts.ShardMax = 1 << 20 |
| b, err = NewBuilder(opts) |
| if err != nil { |
| t.Fatalf("NewBuilder: %v", err) |
| } |
| for i := 0; i < 4; i++ { |
| s := fmt.Sprintf("%d\n", i) |
| b.AddFile("F"+s, []byte(strings.Repeat(s, 1024/2))) |
| } |
| b.Finish() |
| |
| fs, err = filepath.Glob(glob) |
| if err != nil { |
| t.Fatalf("Glob(%s): %v", glob, err) |
| } else if len(fs) != 1 { |
| t.Fatalf("Glob(%s): got %v, want 1 shard", glob, fs) |
| } |
| |
| // Again, but don't index anything; should leave old shards intact. |
| b, err = NewBuilder(opts) |
| if err != nil { |
| t.Fatalf("NewBuilder: %v", err) |
| } |
| b.Finish() |
| |
| fs, err = filepath.Glob(glob) |
| if err != nil { |
| t.Fatalf("Glob(%s): %v", glob, err) |
| } else if len(fs) != 1 { |
| t.Fatalf("Glob(%s): got %v, want 1 shard", glob, fs) |
| } |
| } |