blob: 1ef9c43bd5b0445dc6593256d8c49817797831fc [file] [log] [blame]
Joe Tsaid8881392019-06-06 13:01:53 -07001// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
John Wright9a824c92019-05-03 14:05:20 -06005package protodesc
6
7import (
8 "strings"
9 "testing"
10
Damien Neile89e6242019-05-13 23:55:40 -070011 "google.golang.org/protobuf/internal/scalar"
12 "google.golang.org/protobuf/reflect/protoregistry"
John Wright9a824c92019-05-03 14:05:20 -060013
Joe Tsaia95b29f2019-05-16 12:47:20 -070014 "google.golang.org/protobuf/types/descriptorpb"
John Wright9a824c92019-05-03 14:05:20 -060015)
16
17// Tests validation logic for malformed descriptors.
18func TestNewFile_ValidationErrors(t *testing.T) {
19 testCases := []struct {
20 name string
21 deps []*descriptorpb.FileDescriptorProto
22 fd *descriptorpb.FileDescriptorProto
23 wantErr string
24 }{{
25 name: "field number reserved",
26 fd: &descriptorpb.FileDescriptorProto{
27 Name: scalar.String("field-number-reserved.proto"),
28 Syntax: scalar.String("proto2"),
29 Package: scalar.String("foo"),
30 MessageType: []*descriptorpb.DescriptorProto{{
31 Name: scalar.String("BadMessage"),
32 ReservedRange: []*descriptorpb.DescriptorProto_ReservedRange{{
33 Start: scalar.Int32(3),
34 End: scalar.Int32(4),
35 }},
36 Field: []*descriptorpb.FieldDescriptorProto{{
37 Name: scalar.String("good_field"),
38 Number: scalar.Int32(1),
39 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
40 Type: descriptorpb.FieldDescriptorProto_TYPE_INT32.Enum(),
41 }, {
42 Name: scalar.String("bad_field"),
43 Number: scalar.Int32(3),
44 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
45 Type: descriptorpb.FieldDescriptorProto_TYPE_INT32.Enum(),
46 }},
47 }},
48 },
49 wantErr: "reserved number 3",
50 }, {
51 name: "field name reserved",
52 fd: &descriptorpb.FileDescriptorProto{
53 Name: scalar.String("field-name-reserved.proto"),
54 Syntax: scalar.String("proto2"),
55 Package: scalar.String("foo"),
56 MessageType: []*descriptorpb.DescriptorProto{{
57 Name: scalar.String("BadMessage"),
58 ReservedName: []string{"bad_field", "baz"},
59 Field: []*descriptorpb.FieldDescriptorProto{{
60 Name: scalar.String("good_field"),
61 Number: scalar.Int32(1),
62 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
63 Type: descriptorpb.FieldDescriptorProto_TYPE_INT32.Enum(),
64 }, {
65 Name: scalar.String("bad_field"),
66 Number: scalar.Int32(3),
67 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
68 Type: descriptorpb.FieldDescriptorProto_TYPE_INT32.Enum(),
69 }},
70 }},
71 },
72 wantErr: `reserved name "bad_field"`,
73 }, {
74 name: "normal field with extendee",
75 deps: []*descriptorpb.FileDescriptorProto{{
76 Name: scalar.String("extensible.proto"),
77 Syntax: scalar.String("proto2"),
78 Package: scalar.String("foo"),
79 MessageType: []*descriptorpb.DescriptorProto{{
80 Name: scalar.String("ExtensibleMessage"),
81 ExtensionRange: []*descriptorpb.DescriptorProto_ExtensionRange{{
82 Start: scalar.Int32(1000),
83 End: scalar.Int32(2000),
84 }},
85 }},
86 }},
87 fd: &descriptorpb.FileDescriptorProto{
88 Name: scalar.String("field-with-extendee.proto"),
89 Syntax: scalar.String("proto2"),
90 Package: scalar.String("foo"),
91 Dependency: []string{"extensible.proto"},
92 MessageType: []*descriptorpb.DescriptorProto{{
93 Name: scalar.String("BadMessage"),
94 Field: []*descriptorpb.FieldDescriptorProto{{
95 Name: scalar.String("good_field"),
96 Number: scalar.Int32(1),
97 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
98 Type: descriptorpb.FieldDescriptorProto_TYPE_INT32.Enum(),
99 }, {
100 Name: scalar.String("bad_field"),
101 Number: scalar.Int32(3),
102 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
103 Type: descriptorpb.FieldDescriptorProto_TYPE_INT32.Enum(),
104 Extendee: scalar.String(".foo.ExtensibleMessage"),
105 }},
106 }},
107 },
108 wantErr: "may not have extendee",
109 }, {
110 name: "type_name on int32 field",
111 fd: &descriptorpb.FileDescriptorProto{
112 Name: scalar.String("int32-with-type-name.proto"),
113 Syntax: scalar.String("proto2"),
114 Package: scalar.String("foo"),
115 EnumType: []*descriptorpb.EnumDescriptorProto{{
116 Name: scalar.String("AnEnum"),
117 Value: []*descriptorpb.EnumValueDescriptorProto{{
118 Name: scalar.String("UNKNOWN"),
119 Number: scalar.Int32(0),
120 }},
121 }},
122 MessageType: []*descriptorpb.DescriptorProto{{
123 Name: scalar.String("BadMessage"),
124 Field: []*descriptorpb.FieldDescriptorProto{{
125 Name: scalar.String("good_field"),
126 Number: scalar.Int32(1),
127 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
128 Type: descriptorpb.FieldDescriptorProto_TYPE_INT32.Enum(),
129 }, {
130 Name: scalar.String("bad_field"),
131 Number: scalar.Int32(3),
132 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
133 Type: descriptorpb.FieldDescriptorProto_TYPE_INT32.Enum(),
134 TypeName: scalar.String("AnEnum"),
135 }},
136 }},
137 },
138 wantErr: "type_name",
139 }, {
140 name: "type_name on string extension",
141 deps: []*descriptorpb.FileDescriptorProto{{
142 Name: scalar.String("extensible.proto"),
143 Syntax: scalar.String("proto2"),
144 Package: scalar.String("foo"),
145 MessageType: []*descriptorpb.DescriptorProto{{
146 Name: scalar.String("ExtensibleMessage"),
147 ExtensionRange: []*descriptorpb.DescriptorProto_ExtensionRange{{
148 Start: scalar.Int32(1000),
149 End: scalar.Int32(2000),
150 }},
151 }},
152 }},
153 fd: &descriptorpb.FileDescriptorProto{
154 Name: scalar.String("string-ext-with-type-name.proto"),
155 Syntax: scalar.String("proto2"),
156 Package: scalar.String("bar"),
157 Dependency: []string{"extensible.proto"},
158 EnumType: []*descriptorpb.EnumDescriptorProto{{
159 Name: scalar.String("AnEnum"),
160 Value: []*descriptorpb.EnumValueDescriptorProto{{
161 Name: scalar.String("UNKNOWN"),
162 Number: scalar.Int32(0),
163 }},
164 }},
165 Extension: []*descriptorpb.FieldDescriptorProto{{
166 Name: scalar.String("my_ext"),
167 Number: scalar.Int32(1000),
168 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
169 Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(),
170 Extendee: scalar.String(".foo.ExtensibleMessage"),
171 TypeName: scalar.String("AnEnum"),
172 }},
173 },
174 wantErr: "type_name",
175 }, {
176 name: "oneof_index on extension",
177 deps: []*descriptorpb.FileDescriptorProto{{
178 Name: scalar.String("extensible.proto"),
179 Syntax: scalar.String("proto2"),
180 Package: scalar.String("foo"),
181 MessageType: []*descriptorpb.DescriptorProto{{
182 Name: scalar.String("ExtensibleMessage"),
183 ExtensionRange: []*descriptorpb.DescriptorProto_ExtensionRange{{
184 Start: scalar.Int32(1000),
185 End: scalar.Int32(2000),
186 }},
187 }},
188 }},
189 fd: &descriptorpb.FileDescriptorProto{
190 Name: scalar.String("ext-with-oneof-index.proto"),
191 Syntax: scalar.String("proto2"),
192 Package: scalar.String("bar"),
193 Dependency: []string{"extensible.proto"},
194 Extension: []*descriptorpb.FieldDescriptorProto{{
195 Name: scalar.String("my_ext"),
196 Number: scalar.Int32(1000),
197 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
198 Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(),
199 Extendee: scalar.String(".foo.ExtensibleMessage"),
200 OneofIndex: scalar.Int32(0),
201 }},
202 },
203 wantErr: "oneof_index",
204 }, {
205 name: "enum with reserved number",
206 fd: &descriptorpb.FileDescriptorProto{
207 Name: scalar.String("enum-with-reserved-number.proto"),
208 Syntax: scalar.String("proto2"),
209 Package: scalar.String("foo"),
210 EnumType: []*descriptorpb.EnumDescriptorProto{{
211 Name: scalar.String("AnEnum"),
212 ReservedRange: []*descriptorpb.EnumDescriptorProto_EnumReservedRange{{
213 Start: scalar.Int32(5),
214 End: scalar.Int32(6),
215 }, {
216 Start: scalar.Int32(10),
217 End: scalar.Int32(12),
218 }},
219 Value: []*descriptorpb.EnumValueDescriptorProto{{
220 Name: scalar.String("UNKNOWN"),
221 Number: scalar.Int32(0),
222 }, {
223 Name: scalar.String("FOO"),
224 Number: scalar.Int32(1),
225 }, {
226 Name: scalar.String("BAR"),
227 Number: scalar.Int32(2),
228 }, {
229 Name: scalar.String("BAD"),
230 Number: scalar.Int32(11),
231 }},
232 }},
233 },
234 wantErr: "reserved number 11",
235 }, {
236 name: "enum with reserved number",
237 fd: &descriptorpb.FileDescriptorProto{
238 Name: scalar.String("enum-with-reserved-name.proto"),
239 Syntax: scalar.String("proto2"),
240 Package: scalar.String("foo"),
241 MessageType: []*descriptorpb.DescriptorProto{{
242 Name: scalar.String("ParentMessage"),
243 EnumType: []*descriptorpb.EnumDescriptorProto{{
244 Name: scalar.String("AnEnum"),
245 ReservedName: []string{"ABC", "XYZ"},
246 Value: []*descriptorpb.EnumValueDescriptorProto{{
247 Name: scalar.String("UNKNOWN"),
248 Number: scalar.Int32(0),
249 }, {
250 Name: scalar.String("FOO"),
251 Number: scalar.Int32(1),
252 }, {
253 Name: scalar.String("BAR"),
254 Number: scalar.Int32(2),
255 }, {
256 Name: scalar.String("XYZ"),
257 Number: scalar.Int32(3),
258 }},
259 }},
260 }},
261 },
262 wantErr: `reserved name "XYZ"`,
263 }, {
264 name: "message dependency without import",
265 deps: []*descriptorpb.FileDescriptorProto{{
266 Name: scalar.String("foo.proto"),
267 Syntax: scalar.String("proto2"),
268 Package: scalar.String("foo"),
269 MessageType: []*descriptorpb.DescriptorProto{{
270 Name: scalar.String("Foo"),
271 }},
272 }},
273 fd: &descriptorpb.FileDescriptorProto{
274 Name: scalar.String("message-dependency-without-import.proto"),
275 Syntax: scalar.String("proto2"),
276 Package: scalar.String("bar"),
277 MessageType: []*descriptorpb.DescriptorProto{{
278 Name: scalar.String("Bar"),
279 Field: []*descriptorpb.FieldDescriptorProto{{
280 Name: scalar.String("id"),
281 Number: scalar.Int32(1),
282 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
283 Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(),
284 }, {
285 Name: scalar.String("foo"),
286 Number: scalar.Int32(2),
287 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
288 Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
289 TypeName: scalar.String(".foo.Foo"),
290 }},
291 }},
292 },
293 wantErr: "foo.Foo without import of foo.proto",
294 }, {
295 name: "enum dependency without import",
296 deps: []*descriptorpb.FileDescriptorProto{{
297 Name: scalar.String("foo.proto"),
298 Syntax: scalar.String("proto2"),
299 Package: scalar.String("foo"),
300 EnumType: []*descriptorpb.EnumDescriptorProto{{
301 Name: scalar.String("Foo"),
302 Value: []*descriptorpb.EnumValueDescriptorProto{{
303 Name: scalar.String("UNKNOWN"),
304 Number: scalar.Int32(0),
305 }},
306 }},
307 }},
308 fd: &descriptorpb.FileDescriptorProto{
309 Name: scalar.String("enum-dependency-without-import.proto"),
310 Syntax: scalar.String("proto2"),
311 Package: scalar.String("bar"),
312 MessageType: []*descriptorpb.DescriptorProto{{
313 Name: scalar.String("Bar"),
314 Field: []*descriptorpb.FieldDescriptorProto{{
315 Name: scalar.String("id"),
316 Number: scalar.Int32(1),
317 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
318 Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(),
319 }, {
320 Name: scalar.String("foo"),
321 Number: scalar.Int32(2),
322 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
323 Type: descriptorpb.FieldDescriptorProto_TYPE_ENUM.Enum(),
324 TypeName: scalar.String(".foo.Foo"),
325 }},
326 }},
327 },
328 wantErr: "foo.Foo without import of foo.proto",
329 }, {
330 name: "message dependency on without import on file imported by a public import",
331 deps: []*descriptorpb.FileDescriptorProto{{
332 Name: scalar.String("foo.proto"),
333 Syntax: scalar.String("proto2"),
334 Package: scalar.String("foo"),
335 MessageType: []*descriptorpb.DescriptorProto{{
336 Name: scalar.String("Foo"),
337 }},
338 }, {
339 Name: scalar.String("baz.proto"),
340 Syntax: scalar.String("proto2"),
341 Package: scalar.String("foo"),
342 Dependency: []string{"foo.proto"},
343 }, {
344 Name: scalar.String("old-baz.proto"),
345 Syntax: scalar.String("proto2"),
346 Package: scalar.String("foo"),
347 Dependency: []string{"baz.proto"},
348 PublicDependency: []int32{0},
349 }},
350 fd: &descriptorpb.FileDescriptorProto{
351 Name: scalar.String("message-dependency-without-import.proto"),
352 Syntax: scalar.String("proto2"),
353 Package: scalar.String("bar"),
354 Dependency: []string{"old-baz.proto"},
355 MessageType: []*descriptorpb.DescriptorProto{{
356 Name: scalar.String("Bar"),
357 Field: []*descriptorpb.FieldDescriptorProto{{
358 Name: scalar.String("id"),
359 Number: scalar.Int32(1),
360 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
361 Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(),
362 }, {
363 Name: scalar.String("foo"),
364 Number: scalar.Int32(2),
365 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
366 Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
367 TypeName: scalar.String(".foo.Foo"),
368 }},
369 }},
370 },
371 wantErr: "foo.Foo without import of foo.proto",
372 }}
373
374 for _, tc := range testCases {
375 t.Run(tc.name, func(t *testing.T) {
376 r := new(protoregistry.Files)
377 for _, dep := range tc.deps {
378 f, err := NewFile(dep, r)
379 if err != nil {
380 t.Fatalf("Error creating dependency: %v", err)
381 }
382 if err := r.Register(f); err != nil {
383 t.Fatalf("Error adding dependency: %v", err)
384 }
385 }
386 if _, err := NewFile(tc.fd, r); err == nil || !strings.Contains(err.Error(), tc.wantErr) {
387 t.Errorf("NewFile: got err = %v; want error containing %q", err, tc.wantErr)
388 }
389 })
390 }
391}
392
393// Sanity checks for well-formed descriptors. Most behavior with well-formed descriptors is covered
394// by other tests that rely on generated descriptors.
395func TestNewFile_ValidationOK(t *testing.T) {
396 testCases := []struct {
397 name string
398 deps []*descriptorpb.FileDescriptorProto
399 fd *descriptorpb.FileDescriptorProto
400 }{{
401 name: "self contained file",
402 fd: &descriptorpb.FileDescriptorProto{
403 Name: scalar.String("self-contained.proto"),
404 Syntax: scalar.String("proto2"),
405 Package: scalar.String("foo"),
406 EnumType: []*descriptorpb.EnumDescriptorProto{{
407 Name: scalar.String("TopLevelEnum"),
408 Value: []*descriptorpb.EnumValueDescriptorProto{{
409 Name: scalar.String("UNKNOWN"),
410 Number: scalar.Int32(0),
411 }},
412 }},
413 MessageType: []*descriptorpb.DescriptorProto{{
414 Name: scalar.String("TopLevelMessage"),
415 EnumType: []*descriptorpb.EnumDescriptorProto{{
416 Name: scalar.String("NestedEnum"),
417 Value: []*descriptorpb.EnumValueDescriptorProto{{
418 Name: scalar.String("UNKNOWN"),
419 Number: scalar.Int32(0),
420 }},
421 }},
422 NestedType: []*descriptorpb.DescriptorProto{{
423 Name: scalar.String("NestedMessage"),
424 }},
425 Field: []*descriptorpb.FieldDescriptorProto{{
426 Name: scalar.String("id"),
427 Number: scalar.Int32(1),
428 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
429 Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(),
430 }, {
431 Name: scalar.String("top_level_enum"),
432 Number: scalar.Int32(2),
433 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
434 Type: descriptorpb.FieldDescriptorProto_TYPE_ENUM.Enum(),
435 TypeName: scalar.String(".foo.TopLevelEnum"),
436 }, {
437 Name: scalar.String("nested_enum"),
438 Number: scalar.Int32(3),
439 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
440 Type: descriptorpb.FieldDescriptorProto_TYPE_ENUM.Enum(),
441 TypeName: scalar.String(".foo.TopLevelMessage.NestedEnum"),
442 }, {
443 Name: scalar.String("nested_message"),
444 Number: scalar.Int32(4),
445 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
Joe Tsaid8881392019-06-06 13:01:53 -0700446 Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
John Wright9a824c92019-05-03 14:05:20 -0600447 TypeName: scalar.String(".foo.TopLevelMessage.NestedMessage"),
448 }},
449 }},
450 },
451 }, {
452 name: "external types with explicit import",
453 deps: []*descriptorpb.FileDescriptorProto{{
454 Name: scalar.String("foo.proto"),
455 Syntax: scalar.String("proto2"),
456 Package: scalar.String("foo"),
457 MessageType: []*descriptorpb.DescriptorProto{{
458 Name: scalar.String("FooMessage"),
459 }},
460 EnumType: []*descriptorpb.EnumDescriptorProto{{
461 Name: scalar.String("BarEnum"),
462 Value: []*descriptorpb.EnumValueDescriptorProto{{
463 Name: scalar.String("UNKNOWN"),
464 Number: scalar.Int32(0),
465 }},
466 }},
467 }},
468 fd: &descriptorpb.FileDescriptorProto{
469 Name: scalar.String("external-types-with-explicit-import.proto"),
470 Syntax: scalar.String("proto2"),
471 Package: scalar.String("bar"),
472 Dependency: []string{"foo.proto"},
473 MessageType: []*descriptorpb.DescriptorProto{{
474 Name: scalar.String("Bar"),
475 Field: []*descriptorpb.FieldDescriptorProto{{
476 Name: scalar.String("id"),
477 Number: scalar.Int32(1),
478 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
479 Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(),
480 }, {
481 Name: scalar.String("foo"),
482 Number: scalar.Int32(2),
483 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
484 Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
485 TypeName: scalar.String(".foo.FooMessage"),
486 }, {
487 Name: scalar.String("bar"),
488 Number: scalar.Int32(3),
489 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
490 Type: descriptorpb.FieldDescriptorProto_TYPE_ENUM.Enum(),
491 TypeName: scalar.String(".foo.BarEnum"),
492 }},
493 }},
494 },
495 }, {
496 name: "external types with transitive public imports",
497 deps: []*descriptorpb.FileDescriptorProto{{
498 Name: scalar.String("quux.proto"),
499 Syntax: scalar.String("proto2"),
500 Package: scalar.String("foo"),
501 MessageType: []*descriptorpb.DescriptorProto{{
502 Name: scalar.String("QuuxMessage"),
503 }},
504 }, {
505 Name: scalar.String("foo.proto"),
506 Syntax: scalar.String("proto2"),
507 Package: scalar.String("foo"),
508 Dependency: []string{"quux.proto"},
509 PublicDependency: []int32{0},
510 MessageType: []*descriptorpb.DescriptorProto{{
511 Name: scalar.String("FooMessage"),
512 }},
513 EnumType: []*descriptorpb.EnumDescriptorProto{{
514 Name: scalar.String("BarEnum"),
515 Value: []*descriptorpb.EnumValueDescriptorProto{{
516 Name: scalar.String("UNKNOWN"),
517 Number: scalar.Int32(0),
518 }},
519 }},
520 }, {
521 Name: scalar.String("old-name.proto"),
522 Syntax: scalar.String("proto2"),
523 Package: scalar.String("foo"),
524 Dependency: []string{"foo.proto"},
525 PublicDependency: []int32{0},
526 }},
527 fd: &descriptorpb.FileDescriptorProto{
528 Name: scalar.String("external-types-with-public-import.proto"),
529 Syntax: scalar.String("proto2"),
530 Package: scalar.String("bar"),
531 Dependency: []string{"old-name.proto"},
532 MessageType: []*descriptorpb.DescriptorProto{{
533 Name: scalar.String("Bar"),
534 Field: []*descriptorpb.FieldDescriptorProto{{
535 Name: scalar.String("id"),
536 Number: scalar.Int32(1),
537 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
538 Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(),
539 }, {
540 Name: scalar.String("foo"),
541 Number: scalar.Int32(2),
542 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
543 Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
544 TypeName: scalar.String(".foo.FooMessage"),
545 }, {
546 Name: scalar.String("bar"),
547 Number: scalar.Int32(3),
548 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
549 Type: descriptorpb.FieldDescriptorProto_TYPE_ENUM.Enum(),
550 TypeName: scalar.String(".foo.BarEnum"),
551 }, {
552 Name: scalar.String("quux"),
553 Number: scalar.Int32(4),
554 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
555 Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
556 TypeName: scalar.String(".foo.QuuxMessage"),
557 }},
558 }},
559 },
John Wrightbac4cd42019-05-07 19:10:41 -0600560 }, {
561 name: "external type from weak import",
562 deps: []*descriptorpb.FileDescriptorProto{{
563 Name: scalar.String("weak.proto"),
564 Syntax: scalar.String("proto2"),
565 Package: scalar.String("foo"),
566 MessageType: []*descriptorpb.DescriptorProto{{
567 Name: scalar.String("WeakMessage"),
568 }},
569 }},
570 fd: &descriptorpb.FileDescriptorProto{
571 Name: scalar.String("external-type-from-weak-import.proto"),
572 Syntax: scalar.String("proto2"),
573 Package: scalar.String("bar"),
574 Dependency: []string{"weak.proto"},
575 WeakDependency: []int32{0},
576 MessageType: []*descriptorpb.DescriptorProto{{
577 Name: scalar.String("Bar"),
578 Field: []*descriptorpb.FieldDescriptorProto{{
579 Name: scalar.String("id"),
580 Number: scalar.Int32(1),
581 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
582 Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum(),
583 }, {
584 Name: scalar.String("weak_message"),
585 Number: scalar.Int32(2),
586 Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
587 Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
588 TypeName: scalar.String(".foo.WeakMessage"),
589 Options: &descriptorpb.FieldOptions{
590 Weak: scalar.Bool(true),
591 },
592 }},
593 }},
594 },
John Wright9a824c92019-05-03 14:05:20 -0600595 }}
596
597 for _, tc := range testCases {
598 t.Run(tc.name, func(t *testing.T) {
599 r := new(protoregistry.Files)
600 for _, dep := range tc.deps {
601 f, err := NewFile(dep, r)
602 if err != nil {
Joe Tsaid8881392019-06-06 13:01:53 -0700603 t.Fatalf("error creating dependency: %v", err)
John Wright9a824c92019-05-03 14:05:20 -0600604 }
605 if err := r.Register(f); err != nil {
Joe Tsaid8881392019-06-06 13:01:53 -0700606 t.Fatalf("error adding dependency: %v", err)
John Wright9a824c92019-05-03 14:05:20 -0600607 }
608 }
609 if _, err := NewFile(tc.fd, r); err != nil {
Joe Tsaid8881392019-06-06 13:01:53 -0700610 t.Errorf("unexpected NewFile error: %v", err)
John Wright9a824c92019-05-03 14:05:20 -0600611 }
612 })
613 }
614}