kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/serving/identifiers/identifiers_test.go (about) 1 /* 2 * Copyright 2017 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 identifiers 18 19 import ( 20 "context" 21 "testing" 22 23 "kythe.io/kythe/go/storage/table" 24 "kythe.io/kythe/go/test/testutil" 25 26 "google.golang.org/protobuf/proto" 27 28 ipb "kythe.io/kythe/proto/identifier_go_proto" 29 srvpb "kythe.io/kythe/proto/serving_go_proto" 30 ) 31 32 var matchTable = Table{testProtoTable{ 33 "foo::bar": []proto.Message{ 34 &srvpb.IdentifierMatch{ 35 Node: []*srvpb.IdentifierMatch_Node{ 36 node("kythe://corpus?lang=c++", "", "record", "class"), 37 }, 38 BaseName: "bar", 39 QualifiedName: "foo::bar", 40 }, 41 &srvpb.IdentifierMatch{ 42 Node: []*srvpb.IdentifierMatch_Node{ 43 node("kythe://corpus?lang=c++#decl", "kythe://corpus?lang=c++", "record", "class"), 44 }, 45 BaseName: "bar", 46 QualifiedName: "foo::bar", 47 }, 48 &srvpb.IdentifierMatch{ 49 Node: []*srvpb.IdentifierMatch_Node{ 50 node("kythe://corpus?lang=rust", "", "record", "struct"), 51 }, 52 BaseName: "bar", 53 QualifiedName: "foo::bar", 54 }, 55 }, 56 57 "foo.bar": []proto.Message{ 58 &srvpb.IdentifierMatch{ 59 Node: []*srvpb.IdentifierMatch_Node{ 60 node("kythe://corpus?lang=java", "kythe://corpus?lang=c++", "record", "interface"), 61 }, 62 BaseName: "bar", 63 QualifiedName: "foo.bar", 64 }, 65 }, 66 67 "com.java.package.Interface": []proto.Message{ 68 &srvpb.IdentifierMatch{ 69 Node: []*srvpb.IdentifierMatch_Node{ 70 node("kythe://habeas?lang=java", "", "record", "interface"), 71 }, 72 BaseName: "Interface", 73 QualifiedName: "com.java.package.Interface", 74 }, 75 }, 76 }} 77 78 var tests = []testCase{ 79 { 80 "Qualified name across languages", 81 findRequest("foo::bar", nil, nil, false), 82 []*ipb.FindReply_Match{ 83 match("kythe://corpus?lang=c++", "record", "class", "bar", "foo::bar"), 84 match("kythe://corpus?lang=c++#decl", "record", "class", "bar", "foo::bar"), 85 match("kythe://corpus?lang=rust", "record", "struct", "bar", "foo::bar"), 86 }, 87 }, 88 { 89 "Canonical node for Qualified name across languages", 90 findRequest("foo::bar", nil, nil, true), 91 []*ipb.FindReply_Match{ 92 match("kythe://corpus?lang=c++", "record", "class", "bar", "foo::bar"), 93 match("kythe://corpus?lang=rust", "record", "struct", "bar", "foo::bar"), 94 }, 95 }, 96 { 97 "Java qualified name", 98 findRequest("foo.bar", nil, nil, false), 99 []*ipb.FindReply_Match{ 100 match("kythe://corpus?lang=java", "record", "interface", "bar", "foo.bar"), 101 }, 102 }, 103 { 104 "Java qualified name with canonical node with a different qualified name", 105 findRequest("foo.bar", nil, nil, true), 106 []*ipb.FindReply_Match{ 107 match("kythe://corpus?lang=java", "record", "interface", "bar", "foo.bar"), 108 }, 109 }, 110 { 111 "Rust only", 112 findRequest("foo::bar", nil, []string{"rust"}, false), 113 []*ipb.FindReply_Match{ 114 match("kythe://corpus?lang=rust", "record", "struct", "bar", "foo::bar"), 115 }, 116 }, 117 { 118 "Corpus filter matches", 119 findRequest("com.java.package.Interface", []string{"habeas"}, nil, false), 120 []*ipb.FindReply_Match{ 121 match("kythe://habeas?lang=java", "record", "interface", "Interface", "com.java.package.Interface"), 122 }, 123 }, 124 { 125 "Corpus filter does not match", 126 findRequest("com.java.package.Interface", []string{"corpus"}, nil, false), 127 nil, 128 }, 129 } 130 131 func TestFind(t *testing.T) { 132 for _, test := range tests { 133 reply, err := matchTable.Find(context.TODO(), test.Request) 134 if err != nil { 135 t.Errorf("unexpected error for request %v: %v", test.Request, err) 136 } 137 138 if err := testutil.DeepEqual(test.Matches, reply.Matches); err != nil { 139 t.Errorf("Failed %s\n%v", test.Name, err) 140 } 141 } 142 } 143 144 func findRequest(qname string, corpora, langs []string, canonicalOnly bool) *ipb.FindRequest { 145 return &ipb.FindRequest{ 146 Identifier: qname, 147 PickCanonicalNodes: canonicalOnly, 148 Corpus: corpora, 149 Languages: langs, 150 } 151 } 152 153 func node(ticket, canonicalNodeTicket, kind, subkind string) *srvpb.IdentifierMatch_Node { 154 return &srvpb.IdentifierMatch_Node{ 155 Ticket: ticket, 156 CanonicalNodeTicket: canonicalNodeTicket, 157 NodeKind: kind, 158 NodeSubkind: subkind, 159 } 160 } 161 162 func match(ticket, kind, subkind, bname, qname string) *ipb.FindReply_Match { 163 return &ipb.FindReply_Match{ 164 Ticket: ticket, 165 NodeKind: kind, 166 NodeSubkind: subkind, 167 BaseName: bname, 168 QualifiedName: qname, 169 } 170 } 171 172 type testCase struct { 173 Name string 174 Request *ipb.FindRequest 175 Matches []*ipb.FindReply_Match 176 } 177 178 type testProtoTable map[string][]proto.Message 179 180 func (t testProtoTable) Put(_ context.Context, key []byte, val proto.Message) error { 181 t[string(key)] = []proto.Message{val} 182 return nil 183 } 184 185 func (t testProtoTable) Lookup(_ context.Context, key []byte, msg proto.Message) error { 186 m, ok := t[string(key)] 187 if !ok || len(m) == 0 { 188 return table.ErrNoSuchKey 189 } 190 proto.Merge(msg, m[0]) 191 return nil 192 } 193 194 func (t testProtoTable) LookupValues(_ context.Context, key []byte, m proto.Message, f func(proto.Message) error) error { 195 for _, val := range t[string(key)] { 196 msg := m.ProtoReflect().New().Interface() 197 proto.Merge(msg, val) 198 if err := f(msg); err == table.ErrStopLookup { 199 return nil 200 } else if err != nil { 201 return err 202 } 203 } 204 return nil 205 } 206 207 func (t testProtoTable) Buffered() table.BufferedProto { panic("UNIMPLEMENTED") } 208 209 func (t testProtoTable) Close(context.Context) error { return nil }