kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/services/link/link_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 link 18 19 import ( 20 "context" 21 "errors" 22 "testing" 23 24 "google.golang.org/grpc/codes" 25 "google.golang.org/grpc/status" 26 "google.golang.org/protobuf/proto" 27 28 cpb "kythe.io/kythe/proto/common_go_proto" 29 ipb "kythe.io/kythe/proto/identifier_go_proto" 30 linkpb "kythe.io/kythe/proto/link_go_proto" 31 xpb "kythe.io/kythe/proto/xref_go_proto" 32 ) 33 34 type fakeClient struct { 35 found *ipb.FindReply 36 xrefs *xpb.CrossReferencesReply 37 } 38 39 func (f fakeClient) CrossReferences(_ context.Context, req *xpb.CrossReferencesRequest) (*xpb.CrossReferencesReply, error) { 40 if f.xrefs == nil { 41 return nil, errNoRefs 42 } 43 return f.xrefs, nil 44 } 45 46 func (f fakeClient) Find(_ context.Context, req *ipb.FindRequest) (*ipb.FindReply, error) { 47 if f.found == nil { 48 return nil, errNoID 49 } 50 return f.found, nil 51 } 52 53 var ( 54 errNoRefs = errors.New("no xrefs") 55 errNoID = errors.New("no identifiers") 56 ) 57 58 func TestErrors(t *testing.T) { 59 // None of these tests should make it to calling the service. 60 res := &Resolver{Client: fakeClient{}} 61 tests := []struct { 62 req *linkpb.LinkRequest 63 want codes.Code 64 }{ 65 // Various missing parameters should report INVALID_ARGUMENT. 66 {new(linkpb.LinkRequest), codes.InvalidArgument}, 67 {&linkpb.LinkRequest{ 68 Identifier: "foo", 69 Include: []*linkpb.LinkRequest_Location{{ 70 Path: "(", // bogus regexp 71 }}, 72 }, codes.InvalidArgument}, 73 {&linkpb.LinkRequest{ 74 Identifier: "foo", 75 Exclude: []*linkpb.LinkRequest_Location{{ 76 Root: "?", // bogus regexp 77 }}, 78 }, codes.InvalidArgument}, 79 } 80 ctx := context.Background() 81 for _, test := range tests { 82 _, err := res.Resolve(ctx, test.req) 83 got := status.Code(err) 84 if got != test.want { 85 t.Errorf("Resolve %+v: got code %v, want %v [%v]", test.req, got, test.want, err) 86 } 87 } 88 } 89 90 func TestResolve(t *testing.T) { 91 tests := []struct { 92 req *linkpb.LinkRequest 93 client fakeClient 94 check func(*linkpb.LinkReply, error) 95 }{ 96 { 97 // If there are no ID matches, the request should fail. 98 req: &linkpb.LinkRequest{Identifier: "foo"}, 99 client: fakeClient{}, 100 check: func(rsp *linkpb.LinkReply, err error) { 101 if err != errNoID { 102 t.Errorf("Resolve(foo): got %v, want %v", err, errNoID) 103 } 104 }, 105 }, 106 { 107 // If there are no cross-references, the request should fail. 108 req: &linkpb.LinkRequest{Identifier: "bar"}, 109 client: fakeClient{ 110 found: &ipb.FindReply{ 111 Matches: []*ipb.FindReply_Match{{Ticket: "T"}}, 112 }, 113 }, 114 check: func(rsp *linkpb.LinkReply, err error) { 115 if err != errNoRefs { 116 t.Errorf("Resolve(bar): got %v, want %v", err, errNoRefs) 117 } 118 }, 119 }, 120 { 121 // If there are cross-references, we should get a result. 122 req: &linkpb.LinkRequest{Identifier: "baz"}, 123 client: fakeClient{ 124 found: &ipb.FindReply{ 125 Matches: []*ipb.FindReply_Match{ 126 {Ticket: "kythe://test?lang=qq#X"}, 127 {Ticket: "kythe://test?lang=rr#Y"}, 128 }, 129 }, 130 xrefs: &xpb.CrossReferencesReply{ 131 CrossReferences: map[string]*xpb.CrossReferencesReply_CrossReferenceSet{ 132 "kythe://test?lang=qq#X": { 133 Ticket: "kythe://test?lang=qq#X", 134 Definition: []*xpb.CrossReferencesReply_RelatedAnchor{{ 135 Anchor: &xpb.Anchor{ 136 Ticket: "kythe://test?lang=qq?path=foo#blah", 137 Kind: "/kythe/edge/defines/binding", 138 Parent: "kythe://test?path=foo", 139 Span: &cpb.Span{ 140 Start: &cpb.Point{LineNumber: 10}, 141 End: &cpb.Point{LineNumber: 11}, 142 }, 143 }, 144 }}, 145 }, 146 }, 147 }, 148 }, 149 check: func(rsp *linkpb.LinkReply, err error) { 150 if err != nil { 151 t.Errorf("Resolve(baz): unexpected error: %v", err) 152 return 153 } 154 want := &linkpb.LinkReply{ 155 Links: []*linkpb.Link{{ 156 FileTicket: "kythe://test?path=foo", 157 Span: &cpb.Span{ 158 Start: &cpb.Point{LineNumber: 10}, 159 End: &cpb.Point{LineNumber: 11}, 160 }, 161 }}, 162 } 163 if !proto.Equal(rsp, want) { 164 t.Errorf("Resolve(baz):\ngot %+v\nwant %+v", rsp, want) 165 } 166 }, 167 }, 168 { 169 // If there are no suitable definitions, we should get no result. 170 req: &linkpb.LinkRequest{Identifier: "frob"}, 171 client: fakeClient{ 172 found: &ipb.FindReply{ 173 Matches: []*ipb.FindReply_Match{{Ticket: "kythe://test?lang=qq#X"}}, 174 }, 175 xrefs: &xpb.CrossReferencesReply{ 176 CrossReferences: map[string]*xpb.CrossReferencesReply_CrossReferenceSet{ 177 "kythe://test?lang=qq#X": { 178 Ticket: "kythe://test?lang=qq#X", 179 Reference: []*xpb.CrossReferencesReply_RelatedAnchor{{ 180 Anchor: new(xpb.Anchor), 181 }}, 182 }, 183 }, 184 }, 185 }, 186 check: func(rsp *linkpb.LinkReply, err error) { 187 if err == nil { 188 t.Errorf("Resolve(frob): expected error, but got %+v", rsp) 189 } 190 }, 191 }, 192 } 193 ctx := context.Background() 194 for _, test := range tests { 195 res := &Resolver{Client: test.client} 196 test.check(res.Resolve(ctx, test.req)) 197 } 198 }