@@ -407,6 +407,124 @@ func TestMessageToQueryParameters(t *testing.T) {
407
407
}
408
408
}
409
409
410
+ // TestMessagetoQueryParametersRecursive, is a check that cyclical references between messages
411
+ // are handled gracefully. The goal is to insure that attempts to add messages with cyclical
412
+ // references to query-parameters returns an error message.
413
+ func TestMessageToQueryParametersRecursive (t * testing.T ) {
414
+ type test struct {
415
+ MsgDescs []* protodescriptor.DescriptorProto
416
+ Message string
417
+ }
418
+
419
+ tests := []test {
420
+ // First test:
421
+ // Here we test that a message that references it self through a field will return an error.
422
+ // Example proto:
423
+ // message DirectRecursiveMessage {
424
+ // DirectRecursiveMessage nested = 1;
425
+ // }
426
+ {
427
+ MsgDescs : []* protodescriptor.DescriptorProto {
428
+ & protodescriptor.DescriptorProto {
429
+ Name : proto .String ("DirectRecursiveMessage" ),
430
+ Field : []* protodescriptor.FieldDescriptorProto {
431
+ {
432
+ Name : proto .String ("nested" ),
433
+ Label : protodescriptor .FieldDescriptorProto_LABEL_OPTIONAL .Enum (),
434
+ Type : protodescriptor .FieldDescriptorProto_TYPE_MESSAGE .Enum (),
435
+ TypeName : proto .String (".example.DirectRecursiveMessage" ),
436
+ Number : proto .Int32 (1 ),
437
+ },
438
+ },
439
+ },
440
+ },
441
+ Message : "DirectRecursiveMessage" ,
442
+ },
443
+ // Second test:
444
+ // Here we test that a cycle through multiple messages is detected and that an error is returned.
445
+ // Sample:
446
+ // message Root { NodeMessage nested = 1; }
447
+ // message NodeMessage { CycleMessage nested = 1; }
448
+ // message CycleMessage { Root nested = 1; }
449
+ {
450
+ MsgDescs : []* protodescriptor.DescriptorProto {
451
+ & protodescriptor.DescriptorProto {
452
+ Name : proto .String ("RootMessage" ),
453
+ Field : []* protodescriptor.FieldDescriptorProto {
454
+ {
455
+ Name : proto .String ("nested" ),
456
+ Label : protodescriptor .FieldDescriptorProto_LABEL_OPTIONAL .Enum (),
457
+ Type : protodescriptor .FieldDescriptorProto_TYPE_MESSAGE .Enum (),
458
+ TypeName : proto .String (".example.NodeMessage" ),
459
+ Number : proto .Int32 (1 ),
460
+ },
461
+ },
462
+ },
463
+ & protodescriptor.DescriptorProto {
464
+ Name : proto .String ("NodeMessage" ),
465
+ Field : []* protodescriptor.FieldDescriptorProto {
466
+ {
467
+ Name : proto .String ("nested" ),
468
+ Label : protodescriptor .FieldDescriptorProto_LABEL_OPTIONAL .Enum (),
469
+ Type : protodescriptor .FieldDescriptorProto_TYPE_MESSAGE .Enum (),
470
+ TypeName : proto .String (".example.CycleMessage" ),
471
+ Number : proto .Int32 (1 ),
472
+ },
473
+ },
474
+ },
475
+ & protodescriptor.DescriptorProto {
476
+ Name : proto .String ("CycleMessage" ),
477
+ Field : []* protodescriptor.FieldDescriptorProto {
478
+ {
479
+ Name : proto .String ("nested" ),
480
+ Label : protodescriptor .FieldDescriptorProto_LABEL_OPTIONAL .Enum (),
481
+ Type : protodescriptor .FieldDescriptorProto_TYPE_MESSAGE .Enum (),
482
+ TypeName : proto .String (".example.RootMessage" ),
483
+ Number : proto .Int32 (1 ),
484
+ },
485
+ },
486
+ },
487
+ },
488
+ Message : "RootMessage" ,
489
+ },
490
+ }
491
+
492
+ for _ , test := range tests {
493
+ reg := descriptor .NewRegistry ()
494
+ msgs := []* descriptor.Message {}
495
+ for _ , msgdesc := range test .MsgDescs {
496
+ msgs = append (msgs , & descriptor.Message {DescriptorProto : msgdesc })
497
+ }
498
+ file := descriptor.File {
499
+ FileDescriptorProto : & protodescriptor.FileDescriptorProto {
500
+ SourceCodeInfo : & protodescriptor.SourceCodeInfo {},
501
+ Name : proto .String ("example.proto" ),
502
+ Package : proto .String ("example" ),
503
+ Dependency : []string {},
504
+ MessageType : test .MsgDescs ,
505
+ Service : []* protodescriptor.ServiceDescriptorProto {},
506
+ },
507
+ GoPkg : descriptor.GoPackage {
508
+ Path : "example.com/path/to/example/example.pb" ,
509
+ Name : "example_pb" ,
510
+ },
511
+ Messages : msgs ,
512
+ }
513
+ reg .Load (& plugin.CodeGeneratorRequest {
514
+ ProtoFile : []* protodescriptor.FileDescriptorProto {file .FileDescriptorProto },
515
+ })
516
+
517
+ message , err := reg .LookupMsg ("" , ".example." + test .Message )
518
+ if err != nil {
519
+ t .Fatalf ("failed to lookup message: %s" , err )
520
+ }
521
+ _ , err = messageToQueryParameters (message , reg , []descriptor.Parameter {})
522
+ if err == nil {
523
+ t .Fatalf ("It should not be allowed to have recursive query parameters" )
524
+ }
525
+ }
526
+ }
527
+
410
528
func TestMessageToQueryParametersWithJsonName (t * testing.T ) {
411
529
type test struct {
412
530
MsgDescs []* protodescriptor.DescriptorProto
0 commit comments