github.com/stackb/rules_proto@v0.0.0-20240221195024-5428336c51f1/pkg/protoc/resolver_test.go (about) 1 package protoc 2 3 import ( 4 "bytes" 5 "strings" 6 "testing" 7 8 "github.com/bazelbuild/bazel-gazelle/label" 9 "github.com/bazelbuild/bazel-gazelle/resolve" 10 "github.com/google/go-cmp/cmp" 11 "github.com/google/go-cmp/cmp/cmpopts" 12 ) 13 14 func TestLoadResolver(t *testing.T) { 15 for name, tc := range map[string]struct { 16 in string 17 known map[string]importLabels 18 }{ 19 "empty string": { 20 in: "", 21 known: map[string]importLabels{}, 22 }, 23 "comment": { 24 in: "# ignored", 25 known: map[string]importLabels{}, 26 }, 27 "proto resolve": { 28 in: "proto,proto,google/protobuf/any.proto,@com_google_protobuf//:any_proto", 29 known: map[string]importLabels{ 30 "proto proto": map[string][]label.Label{ 31 "google/protobuf/any.proto": {label.New("com_google_protobuf", "", "any_proto")}, 32 }, 33 }, 34 }, 35 } { 36 t.Run(name, func(t *testing.T) { 37 resolver := &resolver{ 38 options: &ImportResolverOptions{ 39 Debug: false, 40 Printf: t.Logf, 41 }, 42 known: make(map[string]importLabels), 43 } 44 if err := resolver.Load(strings.NewReader(tc.in)); err != nil { 45 t.Fatal(err) 46 } 47 if diff := cmp.Diff(tc.known, resolver.known); diff != "" { 48 t.Error("unexpected diff:", diff) 49 } 50 }) 51 } 52 } 53 54 func TestSaveResolver(t *testing.T) { 55 for name, tc := range map[string]struct { 56 known map[string]importLabels 57 repoName string 58 out string 59 }{ 60 "empty string": { 61 known: map[string]importLabels{}, 62 out: "", 63 }, 64 "does not write external labels": { 65 // the resolver generally loads resolves from other csv files, so we 66 // don't want to "transitively" emit them. Saved output should onlt 67 // reflect the current workspace. 68 known: map[string]importLabels{ 69 "proto proto": map[string][]label.Label{ 70 "google/protobuf/any.proto": {label.New("com_google_protobuf", "", "any_proto")}, 71 }, 72 }, 73 out: "", 74 }, 75 "rewrites labels with repoName": { 76 repoName: "com_google_protobuf", 77 known: map[string]importLabels{ 78 "proto proto": map[string][]label.Label{ 79 "google/protobuf/any.proto": {label.New("", "", "any_proto")}, 80 }, 81 }, 82 out: "proto,proto,google/protobuf/any.proto,@com_google_protobuf//:any_proto\n", 83 }, 84 } { 85 t.Run(name, func(t *testing.T) { 86 resolver := &resolver{ 87 options: &ImportResolverOptions{ 88 Debug: false, 89 Printf: t.Logf, 90 }, 91 known: tc.known, 92 } 93 var out bytes.Buffer 94 resolver.Save(&out, tc.repoName) 95 if diff := cmp.Diff(tc.out, out.String()); diff != "" { 96 t.Error("unexpected diff:", diff) 97 } 98 }) 99 } 100 } 101 102 func TestProvide(t *testing.T) { 103 for name, tc := range map[string]struct { 104 lang, impLang, imp string 105 from label.Label 106 known map[string]importLabels 107 }{ 108 "empty case": { 109 known: map[string]importLabels{ 110 " ": map[string][]label.Label{ 111 "": {label.NoLabel}, 112 }, 113 }, 114 }, 115 "typical usage": { 116 lang: "proto", 117 impLang: "proto", 118 imp: "google/protobuf/any.proto", 119 from: label.New("com_google_protobuf", "", "any_proto"), 120 known: map[string]importLabels{ 121 "proto proto": map[string][]label.Label{ 122 "google/protobuf/any.proto": {label.New("com_google_protobuf", "", "any_proto")}, 123 }, 124 }, 125 }, 126 } { 127 t.Run(name, func(t *testing.T) { 128 resolver := &resolver{ 129 options: &ImportResolverOptions{ 130 Debug: false, 131 Printf: t.Logf, 132 }, 133 known: make(map[string]importLabels), 134 } 135 resolver.Provide(tc.lang, tc.impLang, tc.imp, tc.from) 136 if diff := cmp.Diff(tc.known, resolver.known); diff != "" { 137 t.Error("unexpected diff:", diff) 138 } 139 }) 140 } 141 } 142 143 func TestResolve(t *testing.T) { 144 for name, tc := range map[string]struct { 145 lang, impLang, imp string 146 want []resolve.FindResult 147 known map[string]importLabels 148 }{ 149 "empty case - matches a single empty result": { 150 known: map[string]importLabels{ 151 " ": map[string][]label.Label{ 152 "": {label.NoLabel}, 153 }, 154 }, 155 want: []resolve.FindResult{{}}, 156 }, 157 "typical usage": { 158 lang: "proto", 159 impLang: "proto", 160 imp: "google/protobuf/any.proto", 161 want: []resolve.FindResult{ 162 { 163 Label: label.New("com_google_protobuf", "", "any_proto"), 164 }, 165 }, 166 known: map[string]importLabels{ 167 "proto proto": map[string][]label.Label{ 168 "google/protobuf/any.proto": {label.New("com_google_protobuf", "", "any_proto")}, 169 }, 170 }, 171 }, 172 } { 173 t.Run(name, func(t *testing.T) { 174 resolver := &resolver{ 175 options: &ImportResolverOptions{ 176 Debug: false, 177 Printf: t.Logf, 178 }, 179 known: tc.known, 180 } 181 got := resolver.Resolve(tc.lang, tc.impLang, tc.imp) 182 if diff := cmp.Diff(tc.want, got); diff != "" { 183 t.Errorf("Resolve() mismatch (-want +got):\n%s", diff) 184 } 185 }) 186 } 187 } 188 189 func TestProvided(t *testing.T) { 190 for name, tc := range map[string]struct { 191 lang, impLang string 192 want map[label.Label][]string 193 known map[string]importLabels 194 }{ 195 "empty case - nothing known": {}, 196 "typical usage": { 197 lang: "proto", 198 impLang: "proto", 199 known: map[string]importLabels{ 200 "proto proto": map[string][]label.Label{ 201 "google/protobuf/any.proto": {label.New("com_google_protobuf", "", "any_proto")}, 202 "google/protobuf/any_helper.proto": {label.New("com_google_protobuf", "", "any_proto")}, 203 "google/protobuf/duration.proto": {label.New("com_google_protobuf", "", "duration_proto")}, 204 }, 205 }, 206 want: map[label.Label][]string{ 207 label.New("com_google_protobuf", "", "any_proto"): { 208 "google/protobuf/any.proto", 209 "google/protobuf/any_helper.proto", 210 }, 211 label.New("com_google_protobuf", "", "duration_proto"): { 212 "google/protobuf/duration.proto", 213 }, 214 }, 215 }, 216 } { 217 t.Run(name, func(t *testing.T) { 218 resolver := &resolver{ 219 options: &ImportResolverOptions{ 220 Debug: false, 221 Printf: t.Logf, 222 }, 223 known: tc.known, 224 } 225 got := resolver.Provided(tc.lang, tc.impLang) 226 if diff := cmp.Diff(tc.want, got, cmpopts.SortMaps(compareImportLabels)); diff != "" { 227 t.Errorf("Resolve() mismatch (-want +got):\n%s", diff) 228 } 229 }) 230 } 231 } 232 233 func compareImportLabels(x, y importLabels) bool { 234 if len(x) != len(y) { 235 return len(x) < len(y) 236 } 237 a := importLabelEntries(x) 238 b := importLabelEntries(y) 239 240 for i := 0; i < len(a); i++ { 241 r := a[i] 242 s := b[i] 243 if r.key != s.key { 244 return r.key < s.key 245 } 246 for j := 0; j < len(r.values); j++ { 247 if r.values[j] != s.values[j] { 248 return r.values[j] < s.values[j] 249 } 250 } 251 } 252 253 return true 254 } 255 256 func importLabelEntries(x importLabels) []importLabelEntry { 257 var a []importLabelEntry 258 for k, v := range x { 259 deps := make([]string, len(v)) 260 for i, d := range v { 261 deps[i] = d.String() 262 } 263 a = append(a, importLabelEntry{k, deps}) 264 } 265 return a 266 } 267 268 type importLabelEntry struct { 269 key string 270 values []string 271 }