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  }