1*1c12ee1eSDan Willemsen// Copyright 2018 The Go Authors. All rights reserved. 2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style 3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file. 4*1c12ee1eSDan Willemsen 5*1c12ee1eSDan Willemsenpackage filedesc_test 6*1c12ee1eSDan Willemsen 7*1c12ee1eSDan Willemsenimport ( 8*1c12ee1eSDan Willemsen "fmt" 9*1c12ee1eSDan Willemsen "reflect" 10*1c12ee1eSDan Willemsen "regexp" 11*1c12ee1eSDan Willemsen "strconv" 12*1c12ee1eSDan Willemsen "strings" 13*1c12ee1eSDan Willemsen "testing" 14*1c12ee1eSDan Willemsen 15*1c12ee1eSDan Willemsen "github.com/google/go-cmp/cmp" 16*1c12ee1eSDan Willemsen 17*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/detrand" 18*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/filedesc" 19*1c12ee1eSDan Willemsen "google.golang.org/protobuf/proto" 20*1c12ee1eSDan Willemsen "google.golang.org/protobuf/reflect/protodesc" 21*1c12ee1eSDan Willemsen "google.golang.org/protobuf/reflect/protoreflect" 22*1c12ee1eSDan Willemsen 23*1c12ee1eSDan Willemsen "google.golang.org/protobuf/types/descriptorpb" 24*1c12ee1eSDan Willemsen) 25*1c12ee1eSDan Willemsen 26*1c12ee1eSDan Willemsenfunc init() { 27*1c12ee1eSDan Willemsen // Disable detrand to enable direct comparisons on outputs. 28*1c12ee1eSDan Willemsen detrand.Disable() 29*1c12ee1eSDan Willemsen} 30*1c12ee1eSDan Willemsen 31*1c12ee1eSDan Willemsen// TODO: Test protodesc.NewFile with imported files. 32*1c12ee1eSDan Willemsen 33*1c12ee1eSDan Willemsenfunc TestFile(t *testing.T) { 34*1c12ee1eSDan Willemsen f1 := &descriptorpb.FileDescriptorProto{ 35*1c12ee1eSDan Willemsen Syntax: proto.String("proto2"), 36*1c12ee1eSDan Willemsen Name: proto.String("path/to/file.proto"), 37*1c12ee1eSDan Willemsen Package: proto.String("test"), 38*1c12ee1eSDan Willemsen Options: &descriptorpb.FileOptions{Deprecated: proto.Bool(true)}, 39*1c12ee1eSDan Willemsen MessageType: []*descriptorpb.DescriptorProto{{ 40*1c12ee1eSDan Willemsen Name: proto.String("A"), 41*1c12ee1eSDan Willemsen Options: &descriptorpb.MessageOptions{ 42*1c12ee1eSDan Willemsen Deprecated: proto.Bool(true), 43*1c12ee1eSDan Willemsen }, 44*1c12ee1eSDan Willemsen }, { 45*1c12ee1eSDan Willemsen Name: proto.String("B"), 46*1c12ee1eSDan Willemsen Field: []*descriptorpb.FieldDescriptorProto{{ 47*1c12ee1eSDan Willemsen Name: proto.String("field_one"), 48*1c12ee1eSDan Willemsen Number: proto.Int32(1), 49*1c12ee1eSDan Willemsen Label: descriptorpb.FieldDescriptorProto_Label(protoreflect.Optional).Enum(), 50*1c12ee1eSDan Willemsen Type: descriptorpb.FieldDescriptorProto_Type(protoreflect.StringKind).Enum(), 51*1c12ee1eSDan Willemsen DefaultValue: proto.String("hello, \"world!\"\n"), 52*1c12ee1eSDan Willemsen OneofIndex: proto.Int32(0), 53*1c12ee1eSDan Willemsen }, { 54*1c12ee1eSDan Willemsen Name: proto.String("field_two"), 55*1c12ee1eSDan Willemsen JsonName: proto.String("Field2"), 56*1c12ee1eSDan Willemsen Number: proto.Int32(2), 57*1c12ee1eSDan Willemsen Label: descriptorpb.FieldDescriptorProto_Label(protoreflect.Optional).Enum(), 58*1c12ee1eSDan Willemsen Type: descriptorpb.FieldDescriptorProto_Type(protoreflect.EnumKind).Enum(), 59*1c12ee1eSDan Willemsen DefaultValue: proto.String("BAR"), 60*1c12ee1eSDan Willemsen TypeName: proto.String(".test.E1"), 61*1c12ee1eSDan Willemsen OneofIndex: proto.Int32(1), 62*1c12ee1eSDan Willemsen }, { 63*1c12ee1eSDan Willemsen Name: proto.String("field_three"), 64*1c12ee1eSDan Willemsen Number: proto.Int32(3), 65*1c12ee1eSDan Willemsen Label: descriptorpb.FieldDescriptorProto_Label(protoreflect.Optional).Enum(), 66*1c12ee1eSDan Willemsen Type: descriptorpb.FieldDescriptorProto_Type(protoreflect.MessageKind).Enum(), 67*1c12ee1eSDan Willemsen TypeName: proto.String(".test.C"), 68*1c12ee1eSDan Willemsen OneofIndex: proto.Int32(1), 69*1c12ee1eSDan Willemsen }, { 70*1c12ee1eSDan Willemsen Name: proto.String("field_four"), 71*1c12ee1eSDan Willemsen JsonName: proto.String("Field4"), 72*1c12ee1eSDan Willemsen Number: proto.Int32(4), 73*1c12ee1eSDan Willemsen Label: descriptorpb.FieldDescriptorProto_Label(protoreflect.Repeated).Enum(), 74*1c12ee1eSDan Willemsen Type: descriptorpb.FieldDescriptorProto_Type(protoreflect.MessageKind).Enum(), 75*1c12ee1eSDan Willemsen TypeName: proto.String(".test.B.FieldFourEntry"), 76*1c12ee1eSDan Willemsen }, { 77*1c12ee1eSDan Willemsen Name: proto.String("field_five"), 78*1c12ee1eSDan Willemsen Number: proto.Int32(5), 79*1c12ee1eSDan Willemsen Label: descriptorpb.FieldDescriptorProto_Label(protoreflect.Repeated).Enum(), 80*1c12ee1eSDan Willemsen Type: descriptorpb.FieldDescriptorProto_Type(protoreflect.Int32Kind).Enum(), 81*1c12ee1eSDan Willemsen Options: &descriptorpb.FieldOptions{Packed: proto.Bool(true)}, 82*1c12ee1eSDan Willemsen }, { 83*1c12ee1eSDan Willemsen Name: proto.String("field_six"), 84*1c12ee1eSDan Willemsen Number: proto.Int32(6), 85*1c12ee1eSDan Willemsen Label: descriptorpb.FieldDescriptorProto_Label(protoreflect.Required).Enum(), 86*1c12ee1eSDan Willemsen Type: descriptorpb.FieldDescriptorProto_Type(protoreflect.BytesKind).Enum(), 87*1c12ee1eSDan Willemsen }}, 88*1c12ee1eSDan Willemsen OneofDecl: []*descriptorpb.OneofDescriptorProto{ 89*1c12ee1eSDan Willemsen { 90*1c12ee1eSDan Willemsen Name: proto.String("O1"), 91*1c12ee1eSDan Willemsen Options: &descriptorpb.OneofOptions{ 92*1c12ee1eSDan Willemsen UninterpretedOption: []*descriptorpb.UninterpretedOption{ 93*1c12ee1eSDan Willemsen {StringValue: []byte("option")}, 94*1c12ee1eSDan Willemsen }, 95*1c12ee1eSDan Willemsen }, 96*1c12ee1eSDan Willemsen }, 97*1c12ee1eSDan Willemsen {Name: proto.String("O2")}, 98*1c12ee1eSDan Willemsen }, 99*1c12ee1eSDan Willemsen ReservedName: []string{"fizz", "buzz"}, 100*1c12ee1eSDan Willemsen ReservedRange: []*descriptorpb.DescriptorProto_ReservedRange{ 101*1c12ee1eSDan Willemsen {Start: proto.Int32(100), End: proto.Int32(200)}, 102*1c12ee1eSDan Willemsen {Start: proto.Int32(300), End: proto.Int32(301)}, 103*1c12ee1eSDan Willemsen }, 104*1c12ee1eSDan Willemsen ExtensionRange: []*descriptorpb.DescriptorProto_ExtensionRange{ 105*1c12ee1eSDan Willemsen {Start: proto.Int32(1000), End: proto.Int32(2000)}, 106*1c12ee1eSDan Willemsen {Start: proto.Int32(3000), End: proto.Int32(3001), Options: new(descriptorpb.ExtensionRangeOptions)}, 107*1c12ee1eSDan Willemsen }, 108*1c12ee1eSDan Willemsen NestedType: []*descriptorpb.DescriptorProto{{ 109*1c12ee1eSDan Willemsen Name: proto.String("FieldFourEntry"), 110*1c12ee1eSDan Willemsen Field: []*descriptorpb.FieldDescriptorProto{{ 111*1c12ee1eSDan Willemsen Name: proto.String("key"), 112*1c12ee1eSDan Willemsen Number: proto.Int32(1), 113*1c12ee1eSDan Willemsen Label: descriptorpb.FieldDescriptorProto_Label(protoreflect.Optional).Enum(), 114*1c12ee1eSDan Willemsen Type: descriptorpb.FieldDescriptorProto_Type(protoreflect.StringKind).Enum(), 115*1c12ee1eSDan Willemsen }, { 116*1c12ee1eSDan Willemsen Name: proto.String("value"), 117*1c12ee1eSDan Willemsen Number: proto.Int32(2), 118*1c12ee1eSDan Willemsen Label: descriptorpb.FieldDescriptorProto_Label(protoreflect.Optional).Enum(), 119*1c12ee1eSDan Willemsen Type: descriptorpb.FieldDescriptorProto_Type(protoreflect.MessageKind).Enum(), 120*1c12ee1eSDan Willemsen TypeName: proto.String(".test.B"), 121*1c12ee1eSDan Willemsen }}, 122*1c12ee1eSDan Willemsen Options: &descriptorpb.MessageOptions{ 123*1c12ee1eSDan Willemsen MapEntry: proto.Bool(true), 124*1c12ee1eSDan Willemsen }, 125*1c12ee1eSDan Willemsen }}, 126*1c12ee1eSDan Willemsen }, { 127*1c12ee1eSDan Willemsen Name: proto.String("C"), 128*1c12ee1eSDan Willemsen NestedType: []*descriptorpb.DescriptorProto{{ 129*1c12ee1eSDan Willemsen Name: proto.String("A"), 130*1c12ee1eSDan Willemsen Field: []*descriptorpb.FieldDescriptorProto{{ 131*1c12ee1eSDan Willemsen Name: proto.String("F"), 132*1c12ee1eSDan Willemsen Number: proto.Int32(1), 133*1c12ee1eSDan Willemsen Label: descriptorpb.FieldDescriptorProto_Label(protoreflect.Required).Enum(), 134*1c12ee1eSDan Willemsen Type: descriptorpb.FieldDescriptorProto_Type(protoreflect.BytesKind).Enum(), 135*1c12ee1eSDan Willemsen DefaultValue: proto.String(`dead\276\357`), 136*1c12ee1eSDan Willemsen }}, 137*1c12ee1eSDan Willemsen }}, 138*1c12ee1eSDan Willemsen EnumType: []*descriptorpb.EnumDescriptorProto{{ 139*1c12ee1eSDan Willemsen Name: proto.String("E1"), 140*1c12ee1eSDan Willemsen Value: []*descriptorpb.EnumValueDescriptorProto{ 141*1c12ee1eSDan Willemsen {Name: proto.String("FOO"), Number: proto.Int32(0)}, 142*1c12ee1eSDan Willemsen {Name: proto.String("BAR"), Number: proto.Int32(1)}, 143*1c12ee1eSDan Willemsen }, 144*1c12ee1eSDan Willemsen }}, 145*1c12ee1eSDan Willemsen Extension: []*descriptorpb.FieldDescriptorProto{{ 146*1c12ee1eSDan Willemsen Name: proto.String("X"), 147*1c12ee1eSDan Willemsen Number: proto.Int32(1000), 148*1c12ee1eSDan Willemsen Label: descriptorpb.FieldDescriptorProto_Label(protoreflect.Repeated).Enum(), 149*1c12ee1eSDan Willemsen Type: descriptorpb.FieldDescriptorProto_Type(protoreflect.MessageKind).Enum(), 150*1c12ee1eSDan Willemsen TypeName: proto.String(".test.C"), 151*1c12ee1eSDan Willemsen Extendee: proto.String(".test.B"), 152*1c12ee1eSDan Willemsen }}, 153*1c12ee1eSDan Willemsen }}, 154*1c12ee1eSDan Willemsen EnumType: []*descriptorpb.EnumDescriptorProto{{ 155*1c12ee1eSDan Willemsen Name: proto.String("E1"), 156*1c12ee1eSDan Willemsen Options: &descriptorpb.EnumOptions{Deprecated: proto.Bool(true)}, 157*1c12ee1eSDan Willemsen Value: []*descriptorpb.EnumValueDescriptorProto{ 158*1c12ee1eSDan Willemsen { 159*1c12ee1eSDan Willemsen Name: proto.String("FOO"), 160*1c12ee1eSDan Willemsen Number: proto.Int32(0), 161*1c12ee1eSDan Willemsen Options: &descriptorpb.EnumValueOptions{Deprecated: proto.Bool(true)}, 162*1c12ee1eSDan Willemsen }, 163*1c12ee1eSDan Willemsen {Name: proto.String("BAR"), Number: proto.Int32(1)}, 164*1c12ee1eSDan Willemsen }, 165*1c12ee1eSDan Willemsen ReservedName: []string{"FIZZ", "BUZZ"}, 166*1c12ee1eSDan Willemsen ReservedRange: []*descriptorpb.EnumDescriptorProto_EnumReservedRange{ 167*1c12ee1eSDan Willemsen {Start: proto.Int32(10), End: proto.Int32(19)}, 168*1c12ee1eSDan Willemsen {Start: proto.Int32(30), End: proto.Int32(30)}, 169*1c12ee1eSDan Willemsen }, 170*1c12ee1eSDan Willemsen }}, 171*1c12ee1eSDan Willemsen Extension: []*descriptorpb.FieldDescriptorProto{{ 172*1c12ee1eSDan Willemsen Name: proto.String("X"), 173*1c12ee1eSDan Willemsen Number: proto.Int32(1000), 174*1c12ee1eSDan Willemsen Label: descriptorpb.FieldDescriptorProto_Label(protoreflect.Repeated).Enum(), 175*1c12ee1eSDan Willemsen Type: descriptorpb.FieldDescriptorProto_Type(protoreflect.EnumKind).Enum(), 176*1c12ee1eSDan Willemsen Options: &descriptorpb.FieldOptions{Packed: proto.Bool(true)}, 177*1c12ee1eSDan Willemsen TypeName: proto.String(".test.E1"), 178*1c12ee1eSDan Willemsen Extendee: proto.String(".test.B"), 179*1c12ee1eSDan Willemsen }}, 180*1c12ee1eSDan Willemsen Service: []*descriptorpb.ServiceDescriptorProto{{ 181*1c12ee1eSDan Willemsen Name: proto.String("S"), 182*1c12ee1eSDan Willemsen Options: &descriptorpb.ServiceOptions{Deprecated: proto.Bool(true)}, 183*1c12ee1eSDan Willemsen Method: []*descriptorpb.MethodDescriptorProto{{ 184*1c12ee1eSDan Willemsen Name: proto.String("M"), 185*1c12ee1eSDan Willemsen InputType: proto.String(".test.A"), 186*1c12ee1eSDan Willemsen OutputType: proto.String(".test.C.A"), 187*1c12ee1eSDan Willemsen ClientStreaming: proto.Bool(true), 188*1c12ee1eSDan Willemsen ServerStreaming: proto.Bool(true), 189*1c12ee1eSDan Willemsen Options: &descriptorpb.MethodOptions{Deprecated: proto.Bool(true)}, 190*1c12ee1eSDan Willemsen }}, 191*1c12ee1eSDan Willemsen }}, 192*1c12ee1eSDan Willemsen } 193*1c12ee1eSDan Willemsen fd1, err := protodesc.NewFile(f1, nil) 194*1c12ee1eSDan Willemsen if err != nil { 195*1c12ee1eSDan Willemsen t.Fatalf("protodesc.NewFile() error: %v", err) 196*1c12ee1eSDan Willemsen } 197*1c12ee1eSDan Willemsen 198*1c12ee1eSDan Willemsen b, err := proto.Marshal(f1) 199*1c12ee1eSDan Willemsen if err != nil { 200*1c12ee1eSDan Willemsen t.Fatalf("proto.Marshal() error: %v", err) 201*1c12ee1eSDan Willemsen } 202*1c12ee1eSDan Willemsen fd2 := filedesc.Builder{RawDescriptor: b}.Build().File 203*1c12ee1eSDan Willemsen 204*1c12ee1eSDan Willemsen tests := []struct { 205*1c12ee1eSDan Willemsen name string 206*1c12ee1eSDan Willemsen desc protoreflect.FileDescriptor 207*1c12ee1eSDan Willemsen }{ 208*1c12ee1eSDan Willemsen {"protodesc.NewFile", fd1}, 209*1c12ee1eSDan Willemsen {"filedesc.Builder.Build", fd2}, 210*1c12ee1eSDan Willemsen } 211*1c12ee1eSDan Willemsen for _, tt := range tests { 212*1c12ee1eSDan Willemsen tt := tt 213*1c12ee1eSDan Willemsen t.Run(tt.name, func(t *testing.T) { 214*1c12ee1eSDan Willemsen // Run sub-tests in parallel to induce potential races. 215*1c12ee1eSDan Willemsen for i := 0; i < 2; i++ { 216*1c12ee1eSDan Willemsen t.Run("Accessors", func(t *testing.T) { t.Parallel(); testFileAccessors(t, tt.desc) }) 217*1c12ee1eSDan Willemsen t.Run("Format", func(t *testing.T) { t.Parallel(); testFileFormat(t, tt.desc) }) 218*1c12ee1eSDan Willemsen } 219*1c12ee1eSDan Willemsen }) 220*1c12ee1eSDan Willemsen } 221*1c12ee1eSDan Willemsen} 222*1c12ee1eSDan Willemsen 223*1c12ee1eSDan Willemsenfunc testFileAccessors(t *testing.T, fd protoreflect.FileDescriptor) { 224*1c12ee1eSDan Willemsen // Represent the descriptor as a map where each key is an accessor method 225*1c12ee1eSDan Willemsen // and the value is either the wanted tail value or another accessor map. 226*1c12ee1eSDan Willemsen type M = map[string]interface{} 227*1c12ee1eSDan Willemsen want := M{ 228*1c12ee1eSDan Willemsen "Parent": nil, 229*1c12ee1eSDan Willemsen "Index": 0, 230*1c12ee1eSDan Willemsen "Syntax": protoreflect.Proto2, 231*1c12ee1eSDan Willemsen "Name": protoreflect.Name("test"), 232*1c12ee1eSDan Willemsen "FullName": protoreflect.FullName("test"), 233*1c12ee1eSDan Willemsen "Path": "path/to/file.proto", 234*1c12ee1eSDan Willemsen "Package": protoreflect.FullName("test"), 235*1c12ee1eSDan Willemsen "IsPlaceholder": false, 236*1c12ee1eSDan Willemsen "Options": &descriptorpb.FileOptions{Deprecated: proto.Bool(true)}, 237*1c12ee1eSDan Willemsen "Messages": M{ 238*1c12ee1eSDan Willemsen "Len": 3, 239*1c12ee1eSDan Willemsen "Get:0": M{ 240*1c12ee1eSDan Willemsen "Parent": M{"FullName": protoreflect.FullName("test")}, 241*1c12ee1eSDan Willemsen "Index": 0, 242*1c12ee1eSDan Willemsen "Syntax": protoreflect.Proto2, 243*1c12ee1eSDan Willemsen "Name": protoreflect.Name("A"), 244*1c12ee1eSDan Willemsen "FullName": protoreflect.FullName("test.A"), 245*1c12ee1eSDan Willemsen "IsPlaceholder": false, 246*1c12ee1eSDan Willemsen "IsMapEntry": false, 247*1c12ee1eSDan Willemsen "Options": &descriptorpb.MessageOptions{ 248*1c12ee1eSDan Willemsen Deprecated: proto.Bool(true), 249*1c12ee1eSDan Willemsen }, 250*1c12ee1eSDan Willemsen "Oneofs": M{"Len": 0}, 251*1c12ee1eSDan Willemsen "RequiredNumbers": M{"Len": 0}, 252*1c12ee1eSDan Willemsen "ExtensionRanges": M{"Len": 0}, 253*1c12ee1eSDan Willemsen "Messages": M{"Len": 0}, 254*1c12ee1eSDan Willemsen "Enums": M{"Len": 0}, 255*1c12ee1eSDan Willemsen "Extensions": M{"Len": 0}, 256*1c12ee1eSDan Willemsen }, 257*1c12ee1eSDan Willemsen "ByName:B": M{ 258*1c12ee1eSDan Willemsen "Name": protoreflect.Name("B"), 259*1c12ee1eSDan Willemsen "Index": 1, 260*1c12ee1eSDan Willemsen "Fields": M{ 261*1c12ee1eSDan Willemsen "Len": 6, 262*1c12ee1eSDan Willemsen "ByJSONName:field_one": nil, 263*1c12ee1eSDan Willemsen "ByJSONName:fieldOne": M{ 264*1c12ee1eSDan Willemsen "Name": protoreflect.Name("field_one"), 265*1c12ee1eSDan Willemsen "Index": 0, 266*1c12ee1eSDan Willemsen "JSONName": "fieldOne", 267*1c12ee1eSDan Willemsen "Default": "hello, \"world!\"\n", 268*1c12ee1eSDan Willemsen "ContainingOneof": M{"Name": protoreflect.Name("O1"), "IsPlaceholder": false}, 269*1c12ee1eSDan Willemsen "ContainingMessage": M{"FullName": protoreflect.FullName("test.B")}, 270*1c12ee1eSDan Willemsen }, 271*1c12ee1eSDan Willemsen "ByJSONName:fieldTwo": nil, 272*1c12ee1eSDan Willemsen "ByJSONName:Field2": M{ 273*1c12ee1eSDan Willemsen "Name": protoreflect.Name("field_two"), 274*1c12ee1eSDan Willemsen "Index": 1, 275*1c12ee1eSDan Willemsen "HasJSONName": true, 276*1c12ee1eSDan Willemsen "JSONName": "Field2", 277*1c12ee1eSDan Willemsen "Default": protoreflect.EnumNumber(1), 278*1c12ee1eSDan Willemsen "ContainingOneof": M{"Name": protoreflect.Name("O2"), "IsPlaceholder": false}, 279*1c12ee1eSDan Willemsen }, 280*1c12ee1eSDan Willemsen "ByName:fieldThree": nil, 281*1c12ee1eSDan Willemsen "ByName:field_three": M{ 282*1c12ee1eSDan Willemsen "IsExtension": false, 283*1c12ee1eSDan Willemsen "IsMap": false, 284*1c12ee1eSDan Willemsen "MapKey": nil, 285*1c12ee1eSDan Willemsen "MapValue": nil, 286*1c12ee1eSDan Willemsen "Message": M{"FullName": protoreflect.FullName("test.C"), "IsPlaceholder": false}, 287*1c12ee1eSDan Willemsen "ContainingOneof": M{"Name": protoreflect.Name("O2"), "IsPlaceholder": false}, 288*1c12ee1eSDan Willemsen "ContainingMessage": M{"FullName": protoreflect.FullName("test.B")}, 289*1c12ee1eSDan Willemsen }, 290*1c12ee1eSDan Willemsen "ByNumber:12": nil, 291*1c12ee1eSDan Willemsen "ByNumber:4": M{ 292*1c12ee1eSDan Willemsen "Cardinality": protoreflect.Repeated, 293*1c12ee1eSDan Willemsen "IsExtension": false, 294*1c12ee1eSDan Willemsen "IsList": false, 295*1c12ee1eSDan Willemsen "IsMap": true, 296*1c12ee1eSDan Willemsen "MapKey": M{"Kind": protoreflect.StringKind}, 297*1c12ee1eSDan Willemsen "MapValue": M{"Kind": protoreflect.MessageKind, "Message": M{"FullName": protoreflect.FullName("test.B")}}, 298*1c12ee1eSDan Willemsen "Default": nil, 299*1c12ee1eSDan Willemsen "Message": M{"FullName": protoreflect.FullName("test.B.FieldFourEntry"), "IsPlaceholder": false}, 300*1c12ee1eSDan Willemsen }, 301*1c12ee1eSDan Willemsen "ByNumber:5": M{ 302*1c12ee1eSDan Willemsen "Cardinality": protoreflect.Repeated, 303*1c12ee1eSDan Willemsen "Kind": protoreflect.Int32Kind, 304*1c12ee1eSDan Willemsen "IsPacked": true, 305*1c12ee1eSDan Willemsen "IsList": true, 306*1c12ee1eSDan Willemsen "IsMap": false, 307*1c12ee1eSDan Willemsen "Default": nil, 308*1c12ee1eSDan Willemsen }, 309*1c12ee1eSDan Willemsen "ByNumber:6": M{ 310*1c12ee1eSDan Willemsen "Cardinality": protoreflect.Required, 311*1c12ee1eSDan Willemsen "Default": []byte(nil), 312*1c12ee1eSDan Willemsen "ContainingOneof": nil, 313*1c12ee1eSDan Willemsen }, 314*1c12ee1eSDan Willemsen }, 315*1c12ee1eSDan Willemsen "Oneofs": M{ 316*1c12ee1eSDan Willemsen "Len": 2, 317*1c12ee1eSDan Willemsen "ByName:O0": nil, 318*1c12ee1eSDan Willemsen "ByName:O1": M{ 319*1c12ee1eSDan Willemsen "FullName": protoreflect.FullName("test.B.O1"), 320*1c12ee1eSDan Willemsen "Index": 0, 321*1c12ee1eSDan Willemsen "Options": &descriptorpb.OneofOptions{ 322*1c12ee1eSDan Willemsen UninterpretedOption: []*descriptorpb.UninterpretedOption{ 323*1c12ee1eSDan Willemsen {StringValue: []byte("option")}, 324*1c12ee1eSDan Willemsen }, 325*1c12ee1eSDan Willemsen }, 326*1c12ee1eSDan Willemsen "Fields": M{ 327*1c12ee1eSDan Willemsen "Len": 1, 328*1c12ee1eSDan Willemsen "Get:0": M{"FullName": protoreflect.FullName("test.B.field_one")}, 329*1c12ee1eSDan Willemsen }, 330*1c12ee1eSDan Willemsen }, 331*1c12ee1eSDan Willemsen "Get:1": M{ 332*1c12ee1eSDan Willemsen "FullName": protoreflect.FullName("test.B.O2"), 333*1c12ee1eSDan Willemsen "Index": 1, 334*1c12ee1eSDan Willemsen "Fields": M{ 335*1c12ee1eSDan Willemsen "Len": 2, 336*1c12ee1eSDan Willemsen "ByName:field_two": M{"Name": protoreflect.Name("field_two")}, 337*1c12ee1eSDan Willemsen "Get:1": M{"Name": protoreflect.Name("field_three")}, 338*1c12ee1eSDan Willemsen }, 339*1c12ee1eSDan Willemsen }, 340*1c12ee1eSDan Willemsen }, 341*1c12ee1eSDan Willemsen "ReservedNames": M{ 342*1c12ee1eSDan Willemsen "Len": 2, 343*1c12ee1eSDan Willemsen "Get:0": protoreflect.Name("fizz"), 344*1c12ee1eSDan Willemsen "Has:buzz": true, 345*1c12ee1eSDan Willemsen "Has:noexist": false, 346*1c12ee1eSDan Willemsen }, 347*1c12ee1eSDan Willemsen "ReservedRanges": M{ 348*1c12ee1eSDan Willemsen "Len": 2, 349*1c12ee1eSDan Willemsen "Get:0": [2]protoreflect.FieldNumber{100, 200}, 350*1c12ee1eSDan Willemsen "Has:99": false, 351*1c12ee1eSDan Willemsen "Has:100": true, 352*1c12ee1eSDan Willemsen "Has:150": true, 353*1c12ee1eSDan Willemsen "Has:199": true, 354*1c12ee1eSDan Willemsen "Has:200": false, 355*1c12ee1eSDan Willemsen "Has:300": true, 356*1c12ee1eSDan Willemsen "Has:301": false, 357*1c12ee1eSDan Willemsen }, 358*1c12ee1eSDan Willemsen "RequiredNumbers": M{ 359*1c12ee1eSDan Willemsen "Len": 1, 360*1c12ee1eSDan Willemsen "Get:0": protoreflect.FieldNumber(6), 361*1c12ee1eSDan Willemsen "Has:1": false, 362*1c12ee1eSDan Willemsen "Has:6": true, 363*1c12ee1eSDan Willemsen }, 364*1c12ee1eSDan Willemsen "ExtensionRanges": M{ 365*1c12ee1eSDan Willemsen "Len": 2, 366*1c12ee1eSDan Willemsen "Get:0": [2]protoreflect.FieldNumber{1000, 2000}, 367*1c12ee1eSDan Willemsen "Has:999": false, 368*1c12ee1eSDan Willemsen "Has:1000": true, 369*1c12ee1eSDan Willemsen "Has:1500": true, 370*1c12ee1eSDan Willemsen "Has:1999": true, 371*1c12ee1eSDan Willemsen "Has:2000": false, 372*1c12ee1eSDan Willemsen "Has:3000": true, 373*1c12ee1eSDan Willemsen "Has:3001": false, 374*1c12ee1eSDan Willemsen }, 375*1c12ee1eSDan Willemsen "ExtensionRangeOptions:0": (*descriptorpb.ExtensionRangeOptions)(nil), 376*1c12ee1eSDan Willemsen "ExtensionRangeOptions:1": new(descriptorpb.ExtensionRangeOptions), 377*1c12ee1eSDan Willemsen "Messages": M{ 378*1c12ee1eSDan Willemsen "Get:0": M{ 379*1c12ee1eSDan Willemsen "Fields": M{ 380*1c12ee1eSDan Willemsen "Len": 2, 381*1c12ee1eSDan Willemsen "ByNumber:1": M{ 382*1c12ee1eSDan Willemsen "Parent": M{"FullName": protoreflect.FullName("test.B.FieldFourEntry")}, 383*1c12ee1eSDan Willemsen "Index": 0, 384*1c12ee1eSDan Willemsen "Name": protoreflect.Name("key"), 385*1c12ee1eSDan Willemsen "FullName": protoreflect.FullName("test.B.FieldFourEntry.key"), 386*1c12ee1eSDan Willemsen "Number": protoreflect.FieldNumber(1), 387*1c12ee1eSDan Willemsen "Cardinality": protoreflect.Optional, 388*1c12ee1eSDan Willemsen "Kind": protoreflect.StringKind, 389*1c12ee1eSDan Willemsen "Options": (*descriptorpb.FieldOptions)(nil), 390*1c12ee1eSDan Willemsen "HasJSONName": false, 391*1c12ee1eSDan Willemsen "JSONName": "key", 392*1c12ee1eSDan Willemsen "IsPacked": false, 393*1c12ee1eSDan Willemsen "IsList": false, 394*1c12ee1eSDan Willemsen "IsMap": false, 395*1c12ee1eSDan Willemsen "IsExtension": false, 396*1c12ee1eSDan Willemsen "IsWeak": false, 397*1c12ee1eSDan Willemsen "Default": "", 398*1c12ee1eSDan Willemsen "ContainingOneof": nil, 399*1c12ee1eSDan Willemsen "ContainingMessage": M{"FullName": protoreflect.FullName("test.B.FieldFourEntry")}, 400*1c12ee1eSDan Willemsen "Message": nil, 401*1c12ee1eSDan Willemsen "Enum": nil, 402*1c12ee1eSDan Willemsen }, 403*1c12ee1eSDan Willemsen "ByNumber:2": M{ 404*1c12ee1eSDan Willemsen "Parent": M{"FullName": protoreflect.FullName("test.B.FieldFourEntry")}, 405*1c12ee1eSDan Willemsen "Index": 1, 406*1c12ee1eSDan Willemsen "Name": protoreflect.Name("value"), 407*1c12ee1eSDan Willemsen "FullName": protoreflect.FullName("test.B.FieldFourEntry.value"), 408*1c12ee1eSDan Willemsen "Number": protoreflect.FieldNumber(2), 409*1c12ee1eSDan Willemsen "Cardinality": protoreflect.Optional, 410*1c12ee1eSDan Willemsen "Kind": protoreflect.MessageKind, 411*1c12ee1eSDan Willemsen "JSONName": "value", 412*1c12ee1eSDan Willemsen "IsPacked": false, 413*1c12ee1eSDan Willemsen "IsList": false, 414*1c12ee1eSDan Willemsen "IsMap": false, 415*1c12ee1eSDan Willemsen "IsExtension": false, 416*1c12ee1eSDan Willemsen "IsWeak": false, 417*1c12ee1eSDan Willemsen "Default": nil, 418*1c12ee1eSDan Willemsen "ContainingOneof": nil, 419*1c12ee1eSDan Willemsen "ContainingMessage": M{"FullName": protoreflect.FullName("test.B.FieldFourEntry")}, 420*1c12ee1eSDan Willemsen "Message": M{"FullName": protoreflect.FullName("test.B"), "IsPlaceholder": false}, 421*1c12ee1eSDan Willemsen "Enum": nil, 422*1c12ee1eSDan Willemsen }, 423*1c12ee1eSDan Willemsen "ByNumber:3": nil, 424*1c12ee1eSDan Willemsen }, 425*1c12ee1eSDan Willemsen }, 426*1c12ee1eSDan Willemsen }, 427*1c12ee1eSDan Willemsen }, 428*1c12ee1eSDan Willemsen "Get:2": M{ 429*1c12ee1eSDan Willemsen "Name": protoreflect.Name("C"), 430*1c12ee1eSDan Willemsen "Index": 2, 431*1c12ee1eSDan Willemsen "Messages": M{ 432*1c12ee1eSDan Willemsen "Len": 1, 433*1c12ee1eSDan Willemsen "Get:0": M{"FullName": protoreflect.FullName("test.C.A")}, 434*1c12ee1eSDan Willemsen }, 435*1c12ee1eSDan Willemsen "Enums": M{ 436*1c12ee1eSDan Willemsen "Len": 1, 437*1c12ee1eSDan Willemsen "Get:0": M{"FullName": protoreflect.FullName("test.C.E1")}, 438*1c12ee1eSDan Willemsen }, 439*1c12ee1eSDan Willemsen "Extensions": M{ 440*1c12ee1eSDan Willemsen "Len": 1, 441*1c12ee1eSDan Willemsen "Get:0": M{"FullName": protoreflect.FullName("test.C.X")}, 442*1c12ee1eSDan Willemsen }, 443*1c12ee1eSDan Willemsen }, 444*1c12ee1eSDan Willemsen }, 445*1c12ee1eSDan Willemsen "Enums": M{ 446*1c12ee1eSDan Willemsen "Len": 1, 447*1c12ee1eSDan Willemsen "Get:0": M{ 448*1c12ee1eSDan Willemsen "Name": protoreflect.Name("E1"), 449*1c12ee1eSDan Willemsen "Options": &descriptorpb.EnumOptions{Deprecated: proto.Bool(true)}, 450*1c12ee1eSDan Willemsen "Values": M{ 451*1c12ee1eSDan Willemsen "Len": 2, 452*1c12ee1eSDan Willemsen "ByName:Foo": nil, 453*1c12ee1eSDan Willemsen "ByName:FOO": M{ 454*1c12ee1eSDan Willemsen "FullName": protoreflect.FullName("test.FOO"), 455*1c12ee1eSDan Willemsen "Options": &descriptorpb.EnumValueOptions{Deprecated: proto.Bool(true)}, 456*1c12ee1eSDan Willemsen }, 457*1c12ee1eSDan Willemsen "ByNumber:2": nil, 458*1c12ee1eSDan Willemsen "ByNumber:1": M{"FullName": protoreflect.FullName("test.BAR")}, 459*1c12ee1eSDan Willemsen }, 460*1c12ee1eSDan Willemsen "ReservedNames": M{ 461*1c12ee1eSDan Willemsen "Len": 2, 462*1c12ee1eSDan Willemsen "Get:0": protoreflect.Name("FIZZ"), 463*1c12ee1eSDan Willemsen "Has:BUZZ": true, 464*1c12ee1eSDan Willemsen "Has:NOEXIST": false, 465*1c12ee1eSDan Willemsen }, 466*1c12ee1eSDan Willemsen "ReservedRanges": M{ 467*1c12ee1eSDan Willemsen "Len": 2, 468*1c12ee1eSDan Willemsen "Get:0": [2]protoreflect.EnumNumber{10, 19}, 469*1c12ee1eSDan Willemsen "Has:9": false, 470*1c12ee1eSDan Willemsen "Has:10": true, 471*1c12ee1eSDan Willemsen "Has:15": true, 472*1c12ee1eSDan Willemsen "Has:19": true, 473*1c12ee1eSDan Willemsen "Has:20": false, 474*1c12ee1eSDan Willemsen "Has:30": true, 475*1c12ee1eSDan Willemsen "Has:31": false, 476*1c12ee1eSDan Willemsen }, 477*1c12ee1eSDan Willemsen }, 478*1c12ee1eSDan Willemsen }, 479*1c12ee1eSDan Willemsen "Extensions": M{ 480*1c12ee1eSDan Willemsen "Len": 1, 481*1c12ee1eSDan Willemsen "ByName:X": M{ 482*1c12ee1eSDan Willemsen "Name": protoreflect.Name("X"), 483*1c12ee1eSDan Willemsen "Number": protoreflect.FieldNumber(1000), 484*1c12ee1eSDan Willemsen "Cardinality": protoreflect.Repeated, 485*1c12ee1eSDan Willemsen "Kind": protoreflect.EnumKind, 486*1c12ee1eSDan Willemsen "IsExtension": true, 487*1c12ee1eSDan Willemsen "IsPacked": true, 488*1c12ee1eSDan Willemsen "IsList": true, 489*1c12ee1eSDan Willemsen "IsMap": false, 490*1c12ee1eSDan Willemsen "MapKey": nil, 491*1c12ee1eSDan Willemsen "MapValue": nil, 492*1c12ee1eSDan Willemsen "ContainingOneof": nil, 493*1c12ee1eSDan Willemsen "ContainingMessage": M{"FullName": protoreflect.FullName("test.B"), "IsPlaceholder": false}, 494*1c12ee1eSDan Willemsen "Enum": M{"FullName": protoreflect.FullName("test.E1"), "IsPlaceholder": false}, 495*1c12ee1eSDan Willemsen "Options": &descriptorpb.FieldOptions{Packed: proto.Bool(true)}, 496*1c12ee1eSDan Willemsen }, 497*1c12ee1eSDan Willemsen }, 498*1c12ee1eSDan Willemsen "Services": M{ 499*1c12ee1eSDan Willemsen "Len": 1, 500*1c12ee1eSDan Willemsen "ByName:s": nil, 501*1c12ee1eSDan Willemsen "ByName:S": M{ 502*1c12ee1eSDan Willemsen "Parent": M{"FullName": protoreflect.FullName("test")}, 503*1c12ee1eSDan Willemsen "Name": protoreflect.Name("S"), 504*1c12ee1eSDan Willemsen "FullName": protoreflect.FullName("test.S"), 505*1c12ee1eSDan Willemsen "Options": &descriptorpb.ServiceOptions{Deprecated: proto.Bool(true)}, 506*1c12ee1eSDan Willemsen "Methods": M{ 507*1c12ee1eSDan Willemsen "Len": 1, 508*1c12ee1eSDan Willemsen "Get:0": M{ 509*1c12ee1eSDan Willemsen "Parent": M{"FullName": protoreflect.FullName("test.S")}, 510*1c12ee1eSDan Willemsen "Name": protoreflect.Name("M"), 511*1c12ee1eSDan Willemsen "FullName": protoreflect.FullName("test.S.M"), 512*1c12ee1eSDan Willemsen "Input": M{"FullName": protoreflect.FullName("test.A"), "IsPlaceholder": false}, 513*1c12ee1eSDan Willemsen "Output": M{"FullName": protoreflect.FullName("test.C.A"), "IsPlaceholder": false}, 514*1c12ee1eSDan Willemsen "IsStreamingClient": true, 515*1c12ee1eSDan Willemsen "IsStreamingServer": true, 516*1c12ee1eSDan Willemsen "Options": &descriptorpb.MethodOptions{Deprecated: proto.Bool(true)}, 517*1c12ee1eSDan Willemsen }, 518*1c12ee1eSDan Willemsen }, 519*1c12ee1eSDan Willemsen }, 520*1c12ee1eSDan Willemsen }, 521*1c12ee1eSDan Willemsen } 522*1c12ee1eSDan Willemsen checkAccessors(t, "", reflect.ValueOf(fd), want) 523*1c12ee1eSDan Willemsen} 524*1c12ee1eSDan Willemsenfunc checkAccessors(t *testing.T, p string, rv reflect.Value, want map[string]interface{}) { 525*1c12ee1eSDan Willemsen p0 := p 526*1c12ee1eSDan Willemsen defer func() { 527*1c12ee1eSDan Willemsen if ex := recover(); ex != nil { 528*1c12ee1eSDan Willemsen t.Errorf("panic at %v: %v", p, ex) 529*1c12ee1eSDan Willemsen } 530*1c12ee1eSDan Willemsen }() 531*1c12ee1eSDan Willemsen 532*1c12ee1eSDan Willemsen if rv.Interface() == nil { 533*1c12ee1eSDan Willemsen t.Errorf("%v is nil, want non-nil", p) 534*1c12ee1eSDan Willemsen return 535*1c12ee1eSDan Willemsen } 536*1c12ee1eSDan Willemsen for s, v := range want { 537*1c12ee1eSDan Willemsen // Call the accessor method. 538*1c12ee1eSDan Willemsen p = p0 + "." + s 539*1c12ee1eSDan Willemsen var rets []reflect.Value 540*1c12ee1eSDan Willemsen if i := strings.IndexByte(s, ':'); i >= 0 { 541*1c12ee1eSDan Willemsen // Accessor method takes in a single argument, which is encoded 542*1c12ee1eSDan Willemsen // after the accessor name, separated by a ':' delimiter. 543*1c12ee1eSDan Willemsen fnc := rv.MethodByName(s[:i]) 544*1c12ee1eSDan Willemsen arg := reflect.New(fnc.Type().In(0)).Elem() 545*1c12ee1eSDan Willemsen s = s[i+len(":"):] 546*1c12ee1eSDan Willemsen switch arg.Kind() { 547*1c12ee1eSDan Willemsen case reflect.String: 548*1c12ee1eSDan Willemsen arg.SetString(s) 549*1c12ee1eSDan Willemsen case reflect.Int32, reflect.Int: 550*1c12ee1eSDan Willemsen n, _ := strconv.ParseInt(s, 0, 64) 551*1c12ee1eSDan Willemsen arg.SetInt(n) 552*1c12ee1eSDan Willemsen } 553*1c12ee1eSDan Willemsen rets = fnc.Call([]reflect.Value{arg}) 554*1c12ee1eSDan Willemsen } else { 555*1c12ee1eSDan Willemsen rets = rv.MethodByName(s).Call(nil) 556*1c12ee1eSDan Willemsen } 557*1c12ee1eSDan Willemsen 558*1c12ee1eSDan Willemsen // Check that (val, ok) pattern is internally consistent. 559*1c12ee1eSDan Willemsen if len(rets) == 2 { 560*1c12ee1eSDan Willemsen if rets[0].IsNil() && rets[1].Bool() { 561*1c12ee1eSDan Willemsen t.Errorf("%v = (nil, true), want (nil, false)", p) 562*1c12ee1eSDan Willemsen } 563*1c12ee1eSDan Willemsen if !rets[0].IsNil() && !rets[1].Bool() { 564*1c12ee1eSDan Willemsen t.Errorf("%v = (non-nil, false), want (non-nil, true)", p) 565*1c12ee1eSDan Willemsen } 566*1c12ee1eSDan Willemsen } 567*1c12ee1eSDan Willemsen 568*1c12ee1eSDan Willemsen // Check that the accessor output matches. 569*1c12ee1eSDan Willemsen if want, ok := v.(map[string]interface{}); ok { 570*1c12ee1eSDan Willemsen checkAccessors(t, p, rets[0], want) 571*1c12ee1eSDan Willemsen continue 572*1c12ee1eSDan Willemsen } 573*1c12ee1eSDan Willemsen 574*1c12ee1eSDan Willemsen got := rets[0].Interface() 575*1c12ee1eSDan Willemsen if pv, ok := got.(protoreflect.Value); ok { 576*1c12ee1eSDan Willemsen got = pv.Interface() 577*1c12ee1eSDan Willemsen } 578*1c12ee1eSDan Willemsen 579*1c12ee1eSDan Willemsen // Compare with proto.Equal if possible. 580*1c12ee1eSDan Willemsen gotMsg, gotMsgOK := got.(proto.Message) 581*1c12ee1eSDan Willemsen wantMsg, wantMsgOK := v.(proto.Message) 582*1c12ee1eSDan Willemsen if gotMsgOK && wantMsgOK { 583*1c12ee1eSDan Willemsen gotNil := reflect.ValueOf(gotMsg).IsNil() 584*1c12ee1eSDan Willemsen wantNil := reflect.ValueOf(wantMsg).IsNil() 585*1c12ee1eSDan Willemsen switch { 586*1c12ee1eSDan Willemsen case !gotNil && wantNil: 587*1c12ee1eSDan Willemsen t.Errorf("%v = non-nil, want nil", p) 588*1c12ee1eSDan Willemsen case gotNil && !wantNil: 589*1c12ee1eSDan Willemsen t.Errorf("%v = nil, want non-nil", p) 590*1c12ee1eSDan Willemsen case !proto.Equal(gotMsg, wantMsg): 591*1c12ee1eSDan Willemsen t.Errorf("%v = %v, want %v", p, gotMsg, wantMsg) 592*1c12ee1eSDan Willemsen } 593*1c12ee1eSDan Willemsen continue 594*1c12ee1eSDan Willemsen } 595*1c12ee1eSDan Willemsen 596*1c12ee1eSDan Willemsen if want := v; !reflect.DeepEqual(got, want) { 597*1c12ee1eSDan Willemsen t.Errorf("%v = %T(%v), want %T(%v)", p, got, got, want, want) 598*1c12ee1eSDan Willemsen } 599*1c12ee1eSDan Willemsen } 600*1c12ee1eSDan Willemsen} 601*1c12ee1eSDan Willemsen 602*1c12ee1eSDan Willemsenfunc testFileFormat(t *testing.T, fd protoreflect.FileDescriptor) { 603*1c12ee1eSDan Willemsen const wantFileDescriptor = `FileDescriptor{ 604*1c12ee1eSDan Willemsen Syntax: proto2 605*1c12ee1eSDan Willemsen Path: "path/to/file.proto" 606*1c12ee1eSDan Willemsen Package: test 607*1c12ee1eSDan Willemsen Messages: [{ 608*1c12ee1eSDan Willemsen Name: A 609*1c12ee1eSDan Willemsen }, { 610*1c12ee1eSDan Willemsen Name: B 611*1c12ee1eSDan Willemsen Fields: [{ 612*1c12ee1eSDan Willemsen Name: field_one 613*1c12ee1eSDan Willemsen Number: 1 614*1c12ee1eSDan Willemsen Cardinality: optional 615*1c12ee1eSDan Willemsen Kind: string 616*1c12ee1eSDan Willemsen JSONName: "fieldOne" 617*1c12ee1eSDan Willemsen HasPresence: true 618*1c12ee1eSDan Willemsen HasDefault: true 619*1c12ee1eSDan Willemsen Default: "hello, \"world!\"\n" 620*1c12ee1eSDan Willemsen Oneof: O1 621*1c12ee1eSDan Willemsen }, { 622*1c12ee1eSDan Willemsen Name: field_two 623*1c12ee1eSDan Willemsen Number: 2 624*1c12ee1eSDan Willemsen Cardinality: optional 625*1c12ee1eSDan Willemsen Kind: enum 626*1c12ee1eSDan Willemsen HasJSONName: true 627*1c12ee1eSDan Willemsen JSONName: "Field2" 628*1c12ee1eSDan Willemsen HasPresence: true 629*1c12ee1eSDan Willemsen HasDefault: true 630*1c12ee1eSDan Willemsen Default: 1 631*1c12ee1eSDan Willemsen Oneof: O2 632*1c12ee1eSDan Willemsen Enum: test.E1 633*1c12ee1eSDan Willemsen }, { 634*1c12ee1eSDan Willemsen Name: field_three 635*1c12ee1eSDan Willemsen Number: 3 636*1c12ee1eSDan Willemsen Cardinality: optional 637*1c12ee1eSDan Willemsen Kind: message 638*1c12ee1eSDan Willemsen JSONName: "fieldThree" 639*1c12ee1eSDan Willemsen HasPresence: true 640*1c12ee1eSDan Willemsen Oneof: O2 641*1c12ee1eSDan Willemsen Message: test.C 642*1c12ee1eSDan Willemsen }, { 643*1c12ee1eSDan Willemsen Name: field_four 644*1c12ee1eSDan Willemsen Number: 4 645*1c12ee1eSDan Willemsen Cardinality: repeated 646*1c12ee1eSDan Willemsen Kind: message 647*1c12ee1eSDan Willemsen HasJSONName: true 648*1c12ee1eSDan Willemsen JSONName: "Field4" 649*1c12ee1eSDan Willemsen IsMap: true 650*1c12ee1eSDan Willemsen MapKey: string 651*1c12ee1eSDan Willemsen MapValue: test.B 652*1c12ee1eSDan Willemsen }, { 653*1c12ee1eSDan Willemsen Name: field_five 654*1c12ee1eSDan Willemsen Number: 5 655*1c12ee1eSDan Willemsen Cardinality: repeated 656*1c12ee1eSDan Willemsen Kind: int32 657*1c12ee1eSDan Willemsen JSONName: "fieldFive" 658*1c12ee1eSDan Willemsen IsPacked: true 659*1c12ee1eSDan Willemsen IsList: true 660*1c12ee1eSDan Willemsen }, { 661*1c12ee1eSDan Willemsen Name: field_six 662*1c12ee1eSDan Willemsen Number: 6 663*1c12ee1eSDan Willemsen Cardinality: required 664*1c12ee1eSDan Willemsen Kind: bytes 665*1c12ee1eSDan Willemsen JSONName: "fieldSix" 666*1c12ee1eSDan Willemsen HasPresence: true 667*1c12ee1eSDan Willemsen }] 668*1c12ee1eSDan Willemsen Oneofs: [{ 669*1c12ee1eSDan Willemsen Name: O1 670*1c12ee1eSDan Willemsen Fields: [field_one] 671*1c12ee1eSDan Willemsen }, { 672*1c12ee1eSDan Willemsen Name: O2 673*1c12ee1eSDan Willemsen Fields: [field_two, field_three] 674*1c12ee1eSDan Willemsen }] 675*1c12ee1eSDan Willemsen ReservedNames: [fizz, buzz] 676*1c12ee1eSDan Willemsen ReservedRanges: [100:200, 300] 677*1c12ee1eSDan Willemsen RequiredNumbers: [6] 678*1c12ee1eSDan Willemsen ExtensionRanges: [1000:2000, 3000] 679*1c12ee1eSDan Willemsen Messages: [{ 680*1c12ee1eSDan Willemsen Name: FieldFourEntry 681*1c12ee1eSDan Willemsen IsMapEntry: true 682*1c12ee1eSDan Willemsen Fields: [{ 683*1c12ee1eSDan Willemsen Name: key 684*1c12ee1eSDan Willemsen Number: 1 685*1c12ee1eSDan Willemsen Cardinality: optional 686*1c12ee1eSDan Willemsen Kind: string 687*1c12ee1eSDan Willemsen JSONName: "key" 688*1c12ee1eSDan Willemsen HasPresence: true 689*1c12ee1eSDan Willemsen }, { 690*1c12ee1eSDan Willemsen Name: value 691*1c12ee1eSDan Willemsen Number: 2 692*1c12ee1eSDan Willemsen Cardinality: optional 693*1c12ee1eSDan Willemsen Kind: message 694*1c12ee1eSDan Willemsen JSONName: "value" 695*1c12ee1eSDan Willemsen HasPresence: true 696*1c12ee1eSDan Willemsen Message: test.B 697*1c12ee1eSDan Willemsen }] 698*1c12ee1eSDan Willemsen }] 699*1c12ee1eSDan Willemsen }, { 700*1c12ee1eSDan Willemsen Name: C 701*1c12ee1eSDan Willemsen Messages: [{ 702*1c12ee1eSDan Willemsen Name: A 703*1c12ee1eSDan Willemsen Fields: [{ 704*1c12ee1eSDan Willemsen Name: F 705*1c12ee1eSDan Willemsen Number: 1 706*1c12ee1eSDan Willemsen Cardinality: required 707*1c12ee1eSDan Willemsen Kind: bytes 708*1c12ee1eSDan Willemsen JSONName: "F" 709*1c12ee1eSDan Willemsen HasPresence: true 710*1c12ee1eSDan Willemsen HasDefault: true 711*1c12ee1eSDan Willemsen Default: "dead\xbe\xef" 712*1c12ee1eSDan Willemsen }] 713*1c12ee1eSDan Willemsen RequiredNumbers: [1] 714*1c12ee1eSDan Willemsen }] 715*1c12ee1eSDan Willemsen Enums: [{ 716*1c12ee1eSDan Willemsen Name: E1 717*1c12ee1eSDan Willemsen Values: [ 718*1c12ee1eSDan Willemsen {Name: FOO} 719*1c12ee1eSDan Willemsen {Name: BAR, Number: 1} 720*1c12ee1eSDan Willemsen ] 721*1c12ee1eSDan Willemsen }] 722*1c12ee1eSDan Willemsen Extensions: [{ 723*1c12ee1eSDan Willemsen Name: X 724*1c12ee1eSDan Willemsen Number: 1000 725*1c12ee1eSDan Willemsen Cardinality: repeated 726*1c12ee1eSDan Willemsen Kind: message 727*1c12ee1eSDan Willemsen JSONName: "[test.C.X]" 728*1c12ee1eSDan Willemsen IsExtension: true 729*1c12ee1eSDan Willemsen IsList: true 730*1c12ee1eSDan Willemsen Extendee: test.B 731*1c12ee1eSDan Willemsen Message: test.C 732*1c12ee1eSDan Willemsen }] 733*1c12ee1eSDan Willemsen }] 734*1c12ee1eSDan Willemsen Enums: [{ 735*1c12ee1eSDan Willemsen Name: E1 736*1c12ee1eSDan Willemsen Values: [ 737*1c12ee1eSDan Willemsen {Name: FOO} 738*1c12ee1eSDan Willemsen {Name: BAR, Number: 1} 739*1c12ee1eSDan Willemsen ] 740*1c12ee1eSDan Willemsen ReservedNames: [FIZZ, BUZZ] 741*1c12ee1eSDan Willemsen ReservedRanges: [10:20, 30] 742*1c12ee1eSDan Willemsen }] 743*1c12ee1eSDan Willemsen Extensions: [{ 744*1c12ee1eSDan Willemsen Name: X 745*1c12ee1eSDan Willemsen Number: 1000 746*1c12ee1eSDan Willemsen Cardinality: repeated 747*1c12ee1eSDan Willemsen Kind: enum 748*1c12ee1eSDan Willemsen JSONName: "[test.X]" 749*1c12ee1eSDan Willemsen IsExtension: true 750*1c12ee1eSDan Willemsen IsPacked: true 751*1c12ee1eSDan Willemsen IsList: true 752*1c12ee1eSDan Willemsen Extendee: test.B 753*1c12ee1eSDan Willemsen Enum: test.E1 754*1c12ee1eSDan Willemsen }] 755*1c12ee1eSDan Willemsen Services: [{ 756*1c12ee1eSDan Willemsen Name: S 757*1c12ee1eSDan Willemsen Methods: [{ 758*1c12ee1eSDan Willemsen Name: M 759*1c12ee1eSDan Willemsen Input: test.A 760*1c12ee1eSDan Willemsen Output: test.C.A 761*1c12ee1eSDan Willemsen IsStreamingClient: true 762*1c12ee1eSDan Willemsen IsStreamingServer: true 763*1c12ee1eSDan Willemsen }] 764*1c12ee1eSDan Willemsen }] 765*1c12ee1eSDan Willemsen}` 766*1c12ee1eSDan Willemsen 767*1c12ee1eSDan Willemsen const wantEnums = `Enums{{ 768*1c12ee1eSDan Willemsen Name: E1 769*1c12ee1eSDan Willemsen Values: [ 770*1c12ee1eSDan Willemsen {Name: FOO} 771*1c12ee1eSDan Willemsen {Name: BAR, Number: 1} 772*1c12ee1eSDan Willemsen ] 773*1c12ee1eSDan Willemsen ReservedNames: [FIZZ, BUZZ] 774*1c12ee1eSDan Willemsen ReservedRanges: [10:20, 30] 775*1c12ee1eSDan Willemsen}}` 776*1c12ee1eSDan Willemsen 777*1c12ee1eSDan Willemsen const wantExtensions = `Extensions{{ 778*1c12ee1eSDan Willemsen Name: X 779*1c12ee1eSDan Willemsen Number: 1000 780*1c12ee1eSDan Willemsen Cardinality: repeated 781*1c12ee1eSDan Willemsen Kind: enum 782*1c12ee1eSDan Willemsen JSONName: "[test.X]" 783*1c12ee1eSDan Willemsen IsExtension: true 784*1c12ee1eSDan Willemsen IsPacked: true 785*1c12ee1eSDan Willemsen IsList: true 786*1c12ee1eSDan Willemsen Extendee: test.B 787*1c12ee1eSDan Willemsen Enum: test.E1 788*1c12ee1eSDan Willemsen}}` 789*1c12ee1eSDan Willemsen 790*1c12ee1eSDan Willemsen const wantImports = `FileImports{}` 791*1c12ee1eSDan Willemsen 792*1c12ee1eSDan Willemsen const wantReservedNames = "Names{fizz, buzz}" 793*1c12ee1eSDan Willemsen 794*1c12ee1eSDan Willemsen const wantReservedRanges = "FieldRanges{100:200, 300}" 795*1c12ee1eSDan Willemsen 796*1c12ee1eSDan Willemsen const wantServices = `Services{{ 797*1c12ee1eSDan Willemsen Name: S 798*1c12ee1eSDan Willemsen Methods: [{ 799*1c12ee1eSDan Willemsen Name: M 800*1c12ee1eSDan Willemsen Input: test.A 801*1c12ee1eSDan Willemsen Output: test.C.A 802*1c12ee1eSDan Willemsen IsStreamingClient: true 803*1c12ee1eSDan Willemsen IsStreamingServer: true 804*1c12ee1eSDan Willemsen }] 805*1c12ee1eSDan Willemsen}}` 806*1c12ee1eSDan Willemsen 807*1c12ee1eSDan Willemsen tests := []struct { 808*1c12ee1eSDan Willemsen path string 809*1c12ee1eSDan Willemsen fmt string 810*1c12ee1eSDan Willemsen want string 811*1c12ee1eSDan Willemsen val interface{} 812*1c12ee1eSDan Willemsen }{ 813*1c12ee1eSDan Willemsen {"fd", "%v", compactMultiFormat(wantFileDescriptor), fd}, 814*1c12ee1eSDan Willemsen {"fd", "%+v", wantFileDescriptor, fd}, 815*1c12ee1eSDan Willemsen {"fd.Enums()", "%v", compactMultiFormat(wantEnums), fd.Enums()}, 816*1c12ee1eSDan Willemsen {"fd.Enums()", "%+v", wantEnums, fd.Enums()}, 817*1c12ee1eSDan Willemsen {"fd.Extensions()", "%v", compactMultiFormat(wantExtensions), fd.Extensions()}, 818*1c12ee1eSDan Willemsen {"fd.Extensions()", "%+v", wantExtensions, fd.Extensions()}, 819*1c12ee1eSDan Willemsen {"fd.Imports()", "%v", compactMultiFormat(wantImports), fd.Imports()}, 820*1c12ee1eSDan Willemsen {"fd.Imports()", "%+v", wantImports, fd.Imports()}, 821*1c12ee1eSDan Willemsen {"fd.Messages(B).ReservedNames()", "%v", compactMultiFormat(wantReservedNames), fd.Messages().ByName("B").ReservedNames()}, 822*1c12ee1eSDan Willemsen {"fd.Messages(B).ReservedNames()", "%+v", wantReservedNames, fd.Messages().ByName("B").ReservedNames()}, 823*1c12ee1eSDan Willemsen {"fd.Messages(B).ReservedRanges()", "%v", compactMultiFormat(wantReservedRanges), fd.Messages().ByName("B").ReservedRanges()}, 824*1c12ee1eSDan Willemsen {"fd.Messages(B).ReservedRanges()", "%+v", wantReservedRanges, fd.Messages().ByName("B").ReservedRanges()}, 825*1c12ee1eSDan Willemsen {"fd.Services()", "%v", compactMultiFormat(wantServices), fd.Services()}, 826*1c12ee1eSDan Willemsen {"fd.Services()", "%+v", wantServices, fd.Services()}, 827*1c12ee1eSDan Willemsen } 828*1c12ee1eSDan Willemsen for _, tt := range tests { 829*1c12ee1eSDan Willemsen got := fmt.Sprintf(tt.fmt, tt.val) 830*1c12ee1eSDan Willemsen if diff := cmp.Diff(got, tt.want); diff != "" { 831*1c12ee1eSDan Willemsen t.Errorf("fmt.Sprintf(%q, %s) mismatch (-got +want):\n%s", tt.fmt, tt.path, diff) 832*1c12ee1eSDan Willemsen } 833*1c12ee1eSDan Willemsen } 834*1c12ee1eSDan Willemsen} 835*1c12ee1eSDan Willemsen 836*1c12ee1eSDan Willemsen// compactMultiFormat returns the single line form of a multi line output. 837*1c12ee1eSDan Willemsenfunc compactMultiFormat(s string) string { 838*1c12ee1eSDan Willemsen var b []byte 839*1c12ee1eSDan Willemsen for _, s := range strings.Split(s, "\n") { 840*1c12ee1eSDan Willemsen s = strings.TrimSpace(s) 841*1c12ee1eSDan Willemsen s = regexp.MustCompile(": +").ReplaceAllString(s, ": ") 842*1c12ee1eSDan Willemsen prevWord := len(b) > 0 && b[len(b)-1] != '[' && b[len(b)-1] != '{' 843*1c12ee1eSDan Willemsen nextWord := len(s) > 0 && s[0] != ']' && s[0] != '}' 844*1c12ee1eSDan Willemsen if prevWord && nextWord { 845*1c12ee1eSDan Willemsen b = append(b, ", "...) 846*1c12ee1eSDan Willemsen } 847*1c12ee1eSDan Willemsen b = append(b, s...) 848*1c12ee1eSDan Willemsen } 849*1c12ee1eSDan Willemsen return string(b) 850*1c12ee1eSDan Willemsen} 851