kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/platform/kcd/kzipdb/kzipdb_test.go (about) 1 /* 2 * Copyright 2018 The Kythe Authors. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package kzipdb 18 19 import ( 20 "bytes" 21 "context" 22 "sort" 23 "strings" 24 "sync" 25 "testing" 26 27 "kythe.io/kythe/go/platform/kcd" 28 "kythe.io/kythe/go/platform/kcd/kythe" 29 "kythe.io/kythe/go/platform/kzip" 30 31 "github.com/google/go-cmp/cmp" 32 33 apb "kythe.io/kythe/proto/analysis_go_proto" 34 spb "kythe.io/kythe/proto/storage_go_proto" 35 ) 36 37 var testInput struct { 38 sync.Once 39 40 data []byte 41 units []string 42 files []string 43 } 44 45 func newUnit(key, lang, corpus string) *apb.CompilationUnit { 46 return &apb.CompilationUnit{ 47 VName: &spb.VName{ 48 Corpus: corpus, 49 Language: lang, 50 }, 51 OutputKey: key, 52 } 53 } 54 55 func newIndex(revs ...string) *apb.IndexedCompilation_Index { 56 return &apb.IndexedCompilation_Index{Revisions: revs} 57 } 58 59 func setup(t *testing.T) { 60 t.Helper() 61 testInput.Do(func() { 62 63 buf := bytes.NewBuffer(nil) 64 w, err := kzip.NewWriter(buf) 65 if err != nil { 66 t.Fatalf("NewWriter: %v", err) 67 } 68 for _, ic := range []*apb.IndexedCompilation{ 69 {Unit: newUnit("A", "go", "kythe"), Index: newIndex("123")}, 70 {Unit: newUnit("B", "c++", "kythe"), Index: newIndex("456", "789")}, 71 {Unit: newUnit("C", "go", "chromium"), Index: newIndex("123")}, 72 {Unit: newUnit("D", "protobuf", "kythe"), Index: newIndex("789")}, 73 {Unit: newUnit("E", "java", "boiler.plate"), Index: newIndex("666")}, 74 {Unit: newUnit("F", "java", "kythe")}, 75 } { 76 digest, err := w.AddUnit(ic.Unit, ic.Index) 77 if err != nil { 78 t.Fatalf("AddUnit %v: %v", ic.Unit, err) 79 } 80 testInput.units = append(testInput.units, digest) 81 } 82 for _, src := range []string{ 83 "apple", "pear", "plum", "cherry", 84 } { 85 digest, err := w.AddFile(strings.NewReader(src)) 86 if err != nil { 87 t.Fatalf("AddFile %q: %v", src, err) 88 } 89 testInput.files = append(testInput.files, digest) 90 } 91 if err := w.Close(); err != nil { 92 t.Fatalf("Close: %v", err) 93 } 94 95 testInput.data = buf.Bytes() 96 }) 97 } 98 99 func TestReader(t *testing.T) { 100 setup(t) 101 r, err := kzip.NewReader(bytes.NewReader(testInput.data), int64(len(testInput.data))) 102 if err != nil { 103 t.Fatalf("NewReader failed: %v", err) 104 } 105 db := DB{Reader: r} 106 ctx := context.Background() 107 108 t.Run("NoMatchingRevs", func(t *testing.T) { 109 db.Revisions(ctx, &kcd.RevisionsFilter{Corpus: "bogus"}, func(rev kcd.Revision) error { 110 t.Errorf("Unexpected revision found: %v", rev) 111 return nil 112 }) 113 }) 114 t.Run("MatchSomeRevs", func(t *testing.T) { 115 want := []kcd.Revision{ 116 {Revision: "123", Corpus: "kythe"}, 117 {Revision: "456", Corpus: "kythe"}, 118 {Revision: "789", Corpus: "kythe"}, 119 } 120 var got []kcd.Revision 121 db.Revisions(ctx, &kcd.RevisionsFilter{Corpus: "kythe"}, func(rev kcd.Revision) error { 122 got = append(got, rev) 123 return nil 124 }) 125 sort.Slice(got, func(i, j int) bool { 126 if c := strings.Compare(got[i].Revision, got[j].Revision); c == 0 { 127 return got[i].Corpus < got[j].Corpus 128 } else { 129 return c < 0 130 } 131 }) 132 if diff := cmp.Diff(got, want); diff != "" { 133 t.Errorf("Revisions did not match: diff is\n%s", diff) 134 } 135 }) 136 t.Run("FindGo", func(t *testing.T) { 137 var numFound int 138 db.Find(ctx, &kcd.FindFilter{Languages: []string{"go"}}, func(digest string) error { 139 unit, err := r.Lookup(digest) 140 if err != nil { 141 t.Errorf("Lookup %q failed: %v", digest, err) 142 } else if lang := unit.Proto.GetVName().GetLanguage(); lang != "go" { 143 t.Errorf("Language for %q: got %q, wanted go", digest, lang) 144 } else { 145 numFound++ 146 } 147 return nil 148 }) 149 if numFound != 2 { 150 t.Errorf("Find: got %d compilations, want 2", numFound) 151 } 152 }) 153 t.Run("ReadUnits", func(t *testing.T) { 154 i := 0 155 db.Units(ctx, testInput.units, func(digest, key string, data []byte) error { 156 if want := testInput.units[i]; digest != want { 157 t.Errorf("Unit %d digest: got %q, want %q", i, digest, want) 158 } 159 if key != kythe.Format { 160 t.Errorf("Unit %d format: got %q, want %q", i, key, kythe.Format) 161 } 162 i++ 163 return nil 164 }) 165 }) 166 t.Run("FailUnits", func(t *testing.T) { 167 db.Units(ctx, testInput.files, func(digest, key string, data []byte) error { 168 t.Errorf("Unexpected unit digest %q key %q data %q", digest, key, string(data)) 169 return nil 170 }) 171 }) 172 t.Run("ReadFiles", func(t *testing.T) { 173 i := 0 174 db.Files(ctx, testInput.files, func(digest string, data []byte) error { 175 if want := testInput.files[i]; digest != want { 176 t.Errorf("File %d digest: got %q, want %q", i, digest, want) 177 } 178 i++ 179 return nil 180 }) 181 i = 0 182 db.FilesExist(ctx, testInput.files, func(digest string) error { 183 if want := testInput.files[i]; digest != want { 184 t.Errorf("File %d digest: got %q, want %q", i, digest, want) 185 } 186 i++ 187 return nil 188 }) 189 }) 190 t.Run("FailFiles", func(t *testing.T) { 191 db.Files(ctx, testInput.units, func(digest string, data []byte) error { 192 t.Errorf("Unexpected file digest %q data %q", digest, string(data)) 193 return nil 194 }) 195 db.FilesExist(ctx, testInput.units, func(digest string) error { 196 t.Errorf("Unexpected file digest %q", digest) 197 return nil 198 }) 199 }) 200 }