kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/platform/kcd/kcd_test.go (about) 1 /* 2 * Copyright 2016 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 kcd 18 19 import ( 20 "regexp" 21 "testing" 22 "time" 23 ) 24 25 func TestHexDigest(t *testing.T) { 26 // SHA256 test vectors from http://www.nsrl.nist.gov/testdata/ 27 // We're using these just to make sure we actually get SHA256. 28 tests := map[string]string{ 29 "": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", 30 "abc": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", 31 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq": "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", 32 } 33 for input, want := range tests { 34 if got := HexDigest([]byte(input)); got != want { 35 t.Errorf("HexDigest(%q): got %q, want %q", input, got, want) 36 } 37 } 38 } 39 40 func regexps(exprs ...string) (res []*regexp.Regexp) { 41 for _, expr := range exprs { 42 res = append(res, regexp.MustCompile(expr)) 43 } 44 return 45 } 46 47 func TestIsEmpty(t *testing.T) { 48 tests := []struct { 49 input *FindFilter 50 want bool 51 }{ 52 {nil, true}, 53 {new(FindFilter), true}, 54 {&FindFilter{Revisions: []string{}}, true}, 55 {&FindFilter{Languages: []string{""}}, false}, 56 {&FindFilter{Sources: regexps("foo")}, false}, 57 {&FindFilter{Outputs: regexps("foo")}, false}, 58 {&FindFilter{BuildCorpus: []string{"google3", "foo", "bar"}}, false}, 59 } 60 for _, test := range tests { 61 if got := test.input.IsEmpty(); got != test.want { 62 t.Errorf("%v.IsEmpty(): got %v, want %v", test.input, got, test.want) 63 } 64 } 65 } 66 67 func TestMatcher(t *testing.T) { 68 // The matcher function is an internal detail, but it provides the kernel 69 // of functionality for several other pieces of the package so testing this 70 // is a convenient way to cover the most important bits. 71 tests := []struct { 72 exprs []string 73 inputs []string 74 quote func(string) string 75 want bool 76 }{ 77 // Fallback on empty exprs should work, with or without inputs. 78 {want: true}, 79 {inputs: []string{"xyz"}, want: true}, 80 {exprs: []string{}, want: true}, 81 {exprs: []string{}, inputs: []string{"pdq"}, want: true}, 82 83 { // No values at all; no match. 84 exprs: []string{"a", "b", "c"}}, 85 86 { // Some values, but no match. 87 exprs: []string{"needle"}, 88 inputs: []string{"hay", "stack"}}, 89 90 { // Some values and a match. 91 exprs: []string{"needle"}, 92 inputs: []string{"a", "needle", "is", "here"}, 93 want: true}, 94 95 { // Make sure quoting works. 96 exprs: []string{"foo"}, 97 inputs: []string{"xfoox"}, 98 quote: func(s string) string { return "x" + s + "x" }, 99 want: true}, 100 101 { // Make sure quoting works, negative case. 102 exprs: []string{"foo"}, 103 inputs: []string{"foo"}, 104 quote: func(s string) string { return "bollocks" }}, 105 106 { // Another negative case for quoting. 107 exprs: []string{"f.*g"}, 108 inputs: []string{"foooog"}, 109 quote: regexp.QuoteMeta}, 110 111 { // Matching with regexp operators. 112 exprs: []string{"w[aeiou]{2,}"}, 113 inputs: []string{"waaaaooooouuuu"}, 114 want: true}, 115 } 116 117 for _, test := range tests { 118 m, err := matcher(test.exprs, test.quote) 119 if err != nil { 120 t.Errorf("Matcher for %+v: unexpected error: %v [broken test]", test, err) 121 continue 122 } 123 if got := m(test.inputs...); got != test.want { 124 t.Errorf("Match failed: got %v, want %v", got, test.want) 125 t.Logf("Exprs: %+q\nInput: %+q", test.exprs, test.inputs) 126 } 127 } 128 } 129 130 func TestCombineRegexps(t *testing.T) { 131 res := []*regexp.Regexp{ 132 regexp.MustCompile(`^(foo|bar)$`), 133 regexp.MustCompile(`.*xxx.*`), 134 } 135 match, err := combineRegexps(res) 136 if err != nil { 137 t.Fatalf("combineRegexps %+v: unexpected error: %v", res, err) 138 } 139 for _, yes := range []string{"foo", "bar", "xxx", "axxxb", "fooxxxbar"} { 140 if !match(yes) { 141 t.Errorf("match(%q): got false, want true", yes) 142 } 143 } 144 for _, no := range []string{"food", "barf", "xyxx", "xxfooxx"} { 145 if match(no) { 146 t.Errorf("match(%q): got true, want false", no) 147 } 148 } 149 } 150 151 func TestRevMatch(t *testing.T) { 152 tests := []struct { 153 // Pieces of the filter 154 filterRev, filterCorpus string 155 until time.Time 156 157 // Input to test against the filter 158 inputRev, inputCorpus string 159 timestamp time.Time 160 161 // Should it match? 162 want bool 163 }{ 164 // An empty filter matches everything. 165 {want: true}, 166 {inputRev: "xyzzy", want: true}, 167 {inputRev: "plugh", inputCorpus: "deedle", want: true}, 168 {inputCorpus: "kitteh!", want: true}, 169 {inputRev: "zardoz", timestamp: time.Unix(1940, 204), want: true}, 170 171 // Exact match on the revision string. 172 {filterRev: "xyz pdq", inputRev: "xyz pdq", want: true}, 173 {filterRev: "保護者", inputRev: "watcher", want: false}, 174 175 // Regexp match on the revision string. 176 {filterRev: `1.*`, inputRev: "12345", inputCorpus: "alpha", want: true}, 177 {filterRev: `\d+`, inputRev: "12345", inputCorpus: "bravo", want: true}, 178 {filterRev: `(?i)[aeiou]lf`, inputRev: "Elf", want: true}, 179 180 // Exact match on the corpus string. 181 {filterCorpus: "alpha", inputRev: "12345", inputCorpus: "alpha", want: true}, 182 {filterCorpus: "alpha", inputRev: "12345", inputCorpus: "bravo", want: false}, 183 {filterRev: `\d+`, filterCorpus: "alpha", inputRev: "12345", inputCorpus: "alpha", want: true}, 184 {filterRev: `1{5}`, filterCorpus: "alpha", inputRev: "12345", want: false}, 185 186 // Corpus doesn't accept regexp matches. 187 {filterCorpus: `p(ie|ea)ces?`, inputRev: "q", inputCorpus: "pieces", want: false}, 188 189 // Timestamp constraints. 190 {until: time.Unix(25, 0), inputRev: "boozle", timestamp: time.Unix(25, 1), want: false}, 191 {until: time.Unix(25, 0), inputRev: "beezle", timestamp: time.Unix(24, 0), want: true}, 192 } 193 194 for _, test := range tests { 195 filter := &RevisionsFilter{ 196 Revision: test.filterRev, 197 Corpus: test.filterCorpus, 198 Until: test.until, 199 } 200 matches, err := filter.Compile() 201 if err != nil { 202 t.Errorf("Compile %+v failed: %v", filter, err) 203 continue 204 } 205 rev := Revision{test.inputRev, test.inputCorpus, test.timestamp} 206 if got := matches(rev); got != test.want { 207 t.Errorf("Match failed: got %v, want %v\nFilter: %+v\nQuery: %+v", got, test.want, 208 filter, rev) 209 } 210 } 211 } 212 213 func TestIsValidDigest(t *testing.T) { 214 tests := []struct { 215 input string 216 want bool 217 }{ 218 // String too short. 219 {"", false}, 220 {"e3b0c4429", false}, 221 {"E3B0C4429", false}, 222 {"x y z", false}, 223 {"<dir>", false}, 224 225 // Invalid characters in the digest. 226 {"e3b-c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", false}, 227 {"e3b0c?4298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85+", false}, 228 {"all your base are belong to us you have no chance to survive ha!", false}, 229 230 // Correct format, correct case. 231 {"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", true}, 232 {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", true}, 233 {"0000000000000000000000000000000000000000000000000000000000000000", true}, 234 235 // Correct format, but case matters. 236 {"E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", false}, 237 } 238 for _, test := range tests { 239 got := IsValidDigest(test.input) 240 if got != test.want { 241 t.Errorf("IsValidDigest(%q): got %v, want %v", test.input, got, test.want) 242 } 243 } 244 }