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