github.com/bakjos/protoreflect@v1.9.2/desc/descriptor_test.go (about)

     1  package desc
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"math"
     7  	"os"
     8  	"reflect"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/golang/protobuf/proto"
    13  	dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
    14  	_ "github.com/golang/protobuf/protoc-gen-go/plugin"
    15  	_ "github.com/golang/protobuf/ptypes/empty"
    16  	_ "google.golang.org/genproto/protobuf/api"
    17  	_ "google.golang.org/genproto/protobuf/field_mask"
    18  	_ "google.golang.org/genproto/protobuf/ptype"
    19  	_ "google.golang.org/genproto/protobuf/source_context"
    20  
    21  	"github.com/bakjos/protoreflect/internal"
    22  	"github.com/bakjos/protoreflect/internal/testprotos"
    23  	"github.com/bakjos/protoreflect/internal/testutil"
    24  )
    25  
    26  func TestFileDescriptorObjectGraph(t *testing.T) {
    27  	// This checks the structure of the descriptor for desc_test1.proto to make sure
    28  	// the "rich descriptor" accurately models everything therein.
    29  	fd, err := loadProtoset("../internal/testprotos/desc_test1.protoset")
    30  	testutil.Ok(t, err)
    31  	checkDescriptor(t, "file", 0, fd, nil, fd, descCase{
    32  		name: "desc_test1.proto",
    33  		references: map[string]childCases{
    34  			"messages": {(*FileDescriptor).GetMessageTypes, []descCase{
    35  				{
    36  					name: "testprotos.TestMessage",
    37  					references: map[string]childCases{
    38  						"fields": {(*MessageDescriptor).GetFields, []descCase{
    39  							{
    40  								name: "testprotos.TestMessage.nm",
    41  								references: map[string]childCases{
    42  									"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage")},
    43  									"enum type":    {(*FieldDescriptor).GetEnumType, nil},
    44  									"one of":       {(*FieldDescriptor).GetOneOf, nil},
    45  								},
    46  							},
    47  							{
    48  								name: "testprotos.TestMessage.anm",
    49  								references: map[string]childCases{
    50  									"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage")},
    51  									"enum type":    {(*FieldDescriptor).GetEnumType, nil},
    52  									"one of":       {(*FieldDescriptor).GetOneOf, nil},
    53  								},
    54  							},
    55  							{
    56  								name: "testprotos.TestMessage.yanm",
    57  								references: map[string]childCases{
    58  									"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage")},
    59  									"enum type":    {(*FieldDescriptor).GetEnumType, nil},
    60  									"one of":       {(*FieldDescriptor).GetOneOf, nil},
    61  								},
    62  							},
    63  							{
    64  								name: "testprotos.TestMessage.ne",
    65  								references: map[string]childCases{
    66  									"message type": {(*FieldDescriptor).GetMessageType, nil},
    67  									"enum type":    {(*FieldDescriptor).GetEnumType, refs("testprotos.TestMessage.NestedEnum")},
    68  									"one of":       {(*FieldDescriptor).GetOneOf, nil},
    69  								},
    70  							},
    71  						}},
    72  						// this rabbit hole goes pretty deep...
    73  						"nested messages": {(*MessageDescriptor).GetNestedMessageTypes, []descCase{
    74  							{
    75  								name: "testprotos.TestMessage.NestedMessage",
    76  								references: map[string]childCases{
    77  									"fields": {(*MessageDescriptor).GetFields, []descCase{
    78  										{
    79  											name: "testprotos.TestMessage.NestedMessage.anm",
    80  											references: map[string]childCases{
    81  												"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage")},
    82  												"enum type":    {(*FieldDescriptor).GetEnumType, nil},
    83  												"one of":       {(*FieldDescriptor).GetOneOf, nil},
    84  											},
    85  										},
    86  										{
    87  											name: "testprotos.TestMessage.NestedMessage.yanm",
    88  											references: map[string]childCases{
    89  												"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage")},
    90  												"enum type":    {(*FieldDescriptor).GetEnumType, nil},
    91  												"one of":       {(*FieldDescriptor).GetOneOf, nil},
    92  											},
    93  										},
    94  									}},
    95  									"nested messages": {(*MessageDescriptor).GetNestedMessageTypes, []descCase{
    96  										{
    97  											name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage",
    98  											references: map[string]childCases{
    99  												"fields": {(*MessageDescriptor).GetFields, []descCase{
   100  													{
   101  														name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.yanm",
   102  														references: map[string]childCases{
   103  															"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage")},
   104  															"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   105  															"one of":       {(*FieldDescriptor).GetOneOf, nil},
   106  														},
   107  													},
   108  												}},
   109  												"nested messages": {(*MessageDescriptor).GetNestedMessageTypes, []descCase{
   110  													{
   111  														name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage",
   112  														references: map[string]childCases{
   113  															"nested fields": {(*MessageDescriptor).GetFields, []descCase{
   114  																{
   115  																	name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.foo",
   116  																	references: map[string]childCases{
   117  																		"message type": {(*FieldDescriptor).GetMessageType, nil},
   118  																		"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   119  																		"one of":       {(*FieldDescriptor).GetOneOf, nil},
   120  																	},
   121  																},
   122  																{
   123  																	name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.bar",
   124  																	references: map[string]childCases{
   125  																		"message type": {(*FieldDescriptor).GetMessageType, nil},
   126  																		"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   127  																		"one of":       {(*FieldDescriptor).GetOneOf, nil},
   128  																	},
   129  																},
   130  																{
   131  																	name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.baz",
   132  																	references: map[string]childCases{
   133  																		"message type": {(*FieldDescriptor).GetMessageType, nil},
   134  																		"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   135  																		"one of":       {(*FieldDescriptor).GetOneOf, nil},
   136  																	},
   137  																},
   138  																{
   139  																	name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.dne",
   140  																	references: map[string]childCases{
   141  																		"message type": {(*FieldDescriptor).GetMessageType, nil},
   142  																		"enum type":    {(*FieldDescriptor).GetEnumType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.DeeplyNestedEnum")},
   143  																		"one of":       {(*FieldDescriptor).GetOneOf, nil},
   144  																	},
   145  																},
   146  																{
   147  																	name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.anm",
   148  																	references: map[string]childCases{
   149  																		"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage")},
   150  																		"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   151  																		"one of":       {(*FieldDescriptor).GetOneOf, nil},
   152  																	},
   153  																},
   154  																{
   155  																	name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.nm",
   156  																	references: map[string]childCases{
   157  																		"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage")},
   158  																		"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   159  																		"one of":       {(*FieldDescriptor).GetOneOf, nil},
   160  																	},
   161  																},
   162  																{
   163  																	name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.tm",
   164  																	references: map[string]childCases{
   165  																		"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage")},
   166  																		"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   167  																		"one of":       {(*FieldDescriptor).GetOneOf, nil},
   168  																	},
   169  																},
   170  															}},
   171  															"nested messages": {(*MessageDescriptor).GetNestedMessageTypes, nil},
   172  															"nested enums": {(*MessageDescriptor).GetNestedEnumTypes, []descCase{
   173  																{
   174  																	name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.DeeplyNestedEnum",
   175  																	references: map[string]childCases{
   176  																		"values": {(*EnumDescriptor).GetValues, children(
   177  																			"testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.DeeplyNestedEnum.VALUE1",
   178  																			"testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.DeeplyNestedEnum.VALUE2"),
   179  																		},
   180  																	},
   181  																},
   182  															}},
   183  															"nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil},
   184  															"one ofs":           {(*MessageDescriptor).GetOneOfs, nil},
   185  														},
   186  													},
   187  												}},
   188  												"nested enums": {(*MessageDescriptor).GetNestedEnumTypes, nil},
   189  												"nested extensions": {(*MessageDescriptor).GetNestedExtensions, []descCase{
   190  													{
   191  														name:   "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.flags",
   192  														number: 200,
   193  														references: map[string]childCases{
   194  															"owner":        {(*FieldDescriptor).GetOwner, refs("testprotos.AnotherTestMessage")},
   195  															"message type": {(*FieldDescriptor).GetMessageType, nil},
   196  															"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   197  															"one of":       {(*FieldDescriptor).GetOneOf, nil},
   198  														},
   199  													},
   200  												}},
   201  												"one ofs": {(*MessageDescriptor).GetOneOfs, nil},
   202  											},
   203  										},
   204  									}},
   205  									"nested enums":      {(*MessageDescriptor).GetNestedEnumTypes, nil},
   206  									"nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil},
   207  									"one ofs":           {(*MessageDescriptor).GetOneOfs, nil},
   208  								},
   209  							},
   210  						}},
   211  						"nested enums": {(*MessageDescriptor).GetNestedEnumTypes, []descCase{
   212  							{
   213  								name: "testprotos.TestMessage.NestedEnum",
   214  								references: map[string]childCases{
   215  									"values": {(*EnumDescriptor).GetValues, children(
   216  										"testprotos.TestMessage.NestedEnum.VALUE1", "testprotos.TestMessage.NestedEnum.VALUE2"),
   217  									},
   218  								},
   219  							},
   220  						}},
   221  						"nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil},
   222  						"one ofs":           {(*MessageDescriptor).GetOneOfs, nil},
   223  					},
   224  				},
   225  				{
   226  					name: "testprotos.AnotherTestMessage",
   227  					references: map[string]childCases{
   228  						"fields": {(*MessageDescriptor).GetFields, []descCase{
   229  							{
   230  								name: "testprotos.AnotherTestMessage.dne",
   231  								references: map[string]childCases{
   232  									"message type": {(*FieldDescriptor).GetMessageType, nil},
   233  									"enum type":    {(*FieldDescriptor).GetEnumType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.DeeplyNestedEnum")},
   234  									"one of":       {(*FieldDescriptor).GetOneOf, nil},
   235  								},
   236  							},
   237  							{
   238  								name: "testprotos.AnotherTestMessage.map_field1",
   239  								references: map[string]childCases{
   240  									"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage.MapField1Entry")},
   241  									"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   242  									"one of":       {(*FieldDescriptor).GetOneOf, nil},
   243  								},
   244  							},
   245  							{
   246  								name: "testprotos.AnotherTestMessage.map_field2",
   247  								references: map[string]childCases{
   248  									"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage.MapField2Entry")},
   249  									"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   250  									"one of":       {(*FieldDescriptor).GetOneOf, nil},
   251  								},
   252  							},
   253  							{
   254  								name: "testprotos.AnotherTestMessage.map_field3",
   255  								references: map[string]childCases{
   256  									"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage.MapField3Entry")},
   257  									"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   258  									"one of":       {(*FieldDescriptor).GetOneOf, nil},
   259  								},
   260  							},
   261  							{
   262  								name: "testprotos.AnotherTestMessage.map_field4",
   263  								references: map[string]childCases{
   264  									"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage.MapField4Entry")},
   265  									"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   266  									"one of":       {(*FieldDescriptor).GetOneOf, nil},
   267  								},
   268  							},
   269  							{
   270  								name: "testprotos.AnotherTestMessage.rocknroll",
   271  								references: map[string]childCases{
   272  									"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage.RockNRoll")},
   273  									"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   274  									"one of":       {(*FieldDescriptor).GetOneOf, nil},
   275  								},
   276  							},
   277  							{
   278  								name: "testprotos.AnotherTestMessage.str",
   279  								references: map[string]childCases{
   280  									"message type": {(*FieldDescriptor).GetMessageType, nil},
   281  									"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   282  									"one of":       {(*FieldDescriptor).GetOneOf, refs("testprotos.AnotherTestMessage.atmoo")},
   283  								},
   284  							},
   285  							{
   286  								name: "testprotos.AnotherTestMessage.int",
   287  								references: map[string]childCases{
   288  									"message type": {(*FieldDescriptor).GetMessageType, nil},
   289  									"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   290  									"one of":       {(*FieldDescriptor).GetOneOf, refs("testprotos.AnotherTestMessage.atmoo")},
   291  								},
   292  							},
   293  							{
   294  								name: "testprotos.AnotherTestMessage.withoptions",
   295  								references: map[string]childCases{
   296  									"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage.WithOptions")},
   297  									"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   298  									"one of":       {(*FieldDescriptor).GetOneOf, nil},
   299  								},
   300  							},
   301  						}},
   302  						"one ofs": {(*MessageDescriptor).GetOneOfs, []descCase{
   303  							{
   304  								name:       "testprotos.AnotherTestMessage.atmoo",
   305  								skipParent: true,
   306  								references: map[string]childCases{
   307  									"fields": {(*OneOfDescriptor).GetChoices, fields(
   308  										fld{"testprotos.AnotherTestMessage.str", 7},
   309  										fld{"testprotos.AnotherTestMessage.int", 8}),
   310  									},
   311  								},
   312  							},
   313  						}},
   314  						"nested messages": {(*MessageDescriptor).GetNestedMessageTypes, []descCase{
   315  							{
   316  								name: "testprotos.AnotherTestMessage.MapField1Entry",
   317  								references: map[string]childCases{
   318  									"fields": {(*MessageDescriptor).GetFields, []descCase{
   319  										{
   320  											name: "testprotos.AnotherTestMessage.MapField1Entry.key",
   321  											references: map[string]childCases{
   322  												"message type": {(*FieldDescriptor).GetMessageType, nil},
   323  												"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   324  												"one of":       {(*FieldDescriptor).GetOneOf, nil},
   325  											},
   326  										},
   327  										{
   328  											name: "testprotos.AnotherTestMessage.MapField1Entry.value",
   329  											references: map[string]childCases{
   330  												"message type": {(*FieldDescriptor).GetMessageType, nil},
   331  												"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   332  												"one of":       {(*FieldDescriptor).GetOneOf, nil},
   333  											},
   334  										},
   335  									}},
   336  									"nested messages":   {(*MessageDescriptor).GetNestedMessageTypes, nil},
   337  									"nested enums":      {(*MessageDescriptor).GetNestedEnumTypes, nil},
   338  									"nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil},
   339  									"one ofs":           {(*MessageDescriptor).GetOneOfs, nil},
   340  								},
   341  							},
   342  							{
   343  								name: "testprotos.AnotherTestMessage.MapField2Entry",
   344  								references: map[string]childCases{
   345  									"fields": {(*MessageDescriptor).GetFields, []descCase{
   346  										{
   347  											name: "testprotos.AnotherTestMessage.MapField2Entry.key",
   348  											references: map[string]childCases{
   349  												"message type": {(*FieldDescriptor).GetMessageType, nil},
   350  												"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   351  												"one of":       {(*FieldDescriptor).GetOneOf, nil},
   352  											},
   353  										},
   354  										{
   355  											name: "testprotos.AnotherTestMessage.MapField2Entry.value",
   356  											references: map[string]childCases{
   357  												"message type": {(*FieldDescriptor).GetMessageType, nil},
   358  												"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   359  												"one of":       {(*FieldDescriptor).GetOneOf, nil},
   360  											},
   361  										},
   362  									}},
   363  									"nested messages":   {(*MessageDescriptor).GetNestedMessageTypes, nil},
   364  									"nested enums":      {(*MessageDescriptor).GetNestedEnumTypes, nil},
   365  									"nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil},
   366  									"one ofs":           {(*MessageDescriptor).GetOneOfs, nil},
   367  								},
   368  							},
   369  							{
   370  								name: "testprotos.AnotherTestMessage.MapField3Entry",
   371  								references: map[string]childCases{
   372  									"fields": {(*MessageDescriptor).GetFields, []descCase{
   373  										{
   374  											name: "testprotos.AnotherTestMessage.MapField3Entry.key",
   375  											references: map[string]childCases{
   376  												"message type": {(*FieldDescriptor).GetMessageType, nil},
   377  												"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   378  												"one of":       {(*FieldDescriptor).GetOneOf, nil},
   379  											},
   380  										},
   381  										{
   382  											name: "testprotos.AnotherTestMessage.MapField3Entry.value",
   383  											references: map[string]childCases{
   384  												"message type": {(*FieldDescriptor).GetMessageType, nil},
   385  												"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   386  												"one of":       {(*FieldDescriptor).GetOneOf, nil},
   387  											},
   388  										},
   389  									}},
   390  									"nested messages":   {(*MessageDescriptor).GetNestedMessageTypes, nil},
   391  									"nested enums":      {(*MessageDescriptor).GetNestedEnumTypes, nil},
   392  									"nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil},
   393  									"one ofs":           {(*MessageDescriptor).GetOneOfs, nil},
   394  								},
   395  							},
   396  							{
   397  								name: "testprotos.AnotherTestMessage.MapField4Entry",
   398  								references: map[string]childCases{
   399  									"fields": {(*MessageDescriptor).GetFields, []descCase{
   400  										{
   401  											name: "testprotos.AnotherTestMessage.MapField4Entry.key",
   402  											references: map[string]childCases{
   403  												"message type": {(*FieldDescriptor).GetMessageType, nil},
   404  												"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   405  												"one of":       {(*FieldDescriptor).GetOneOf, nil},
   406  											},
   407  										},
   408  										{
   409  											name: "testprotos.AnotherTestMessage.MapField4Entry.value",
   410  											references: map[string]childCases{
   411  												"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage")},
   412  												"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   413  												"one of":       {(*FieldDescriptor).GetOneOf, nil},
   414  											},
   415  										},
   416  									}},
   417  									"nested messages":   {(*MessageDescriptor).GetNestedMessageTypes, nil},
   418  									"nested enums":      {(*MessageDescriptor).GetNestedEnumTypes, nil},
   419  									"nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil},
   420  									"one ofs":           {(*MessageDescriptor).GetOneOfs, nil},
   421  								},
   422  							},
   423  							{
   424  								name: "testprotos.AnotherTestMessage.RockNRoll",
   425  								references: map[string]childCases{
   426  									"fields": {(*MessageDescriptor).GetFields, []descCase{
   427  										{
   428  											name: "testprotos.AnotherTestMessage.RockNRoll.beatles",
   429  											references: map[string]childCases{
   430  												"message type": {(*FieldDescriptor).GetMessageType, nil},
   431  												"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   432  												"one of":       {(*FieldDescriptor).GetOneOf, nil},
   433  											},
   434  										},
   435  										{
   436  											name: "testprotos.AnotherTestMessage.RockNRoll.stones",
   437  											references: map[string]childCases{
   438  												"message type": {(*FieldDescriptor).GetMessageType, nil},
   439  												"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   440  												"one of":       {(*FieldDescriptor).GetOneOf, nil},
   441  											},
   442  										},
   443  										{
   444  											name: "testprotos.AnotherTestMessage.RockNRoll.doors",
   445  											references: map[string]childCases{
   446  												"message type": {(*FieldDescriptor).GetMessageType, nil},
   447  												"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   448  												"one of":       {(*FieldDescriptor).GetOneOf, nil},
   449  											},
   450  										},
   451  									}},
   452  									"nested messages":   {(*MessageDescriptor).GetNestedMessageTypes, nil},
   453  									"nested enums":      {(*MessageDescriptor).GetNestedEnumTypes, nil},
   454  									"nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil},
   455  									"one ofs":           {(*MessageDescriptor).GetOneOfs, nil},
   456  								},
   457  							},
   458  							{
   459  								name: "testprotos.AnotherTestMessage.WithOptions",
   460  								references: map[string]childCases{
   461  									"fields":            {(*MessageDescriptor).GetFields, nil},
   462  									"nested messages":   {(*MessageDescriptor).GetNestedMessageTypes, nil},
   463  									"nested enums":      {(*MessageDescriptor).GetNestedEnumTypes, nil},
   464  									"nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil},
   465  									"one ofs":           {(*MessageDescriptor).GetOneOfs, nil},
   466  								},
   467  							},
   468  						}},
   469  						"nested enums":      {(*MessageDescriptor).GetNestedEnumTypes, nil},
   470  						"nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil},
   471  					},
   472  				},
   473  			}},
   474  			"enums":    {(*FileDescriptor).GetEnumTypes, nil},
   475  			"services": {(*FileDescriptor).GetServices, nil},
   476  			"extensions": {(*FileDescriptor).GetExtensions, []descCase{
   477  				{
   478  					name:   "testprotos.xtm",
   479  					number: 100,
   480  					references: map[string]childCases{
   481  						"owner":        {(*FieldDescriptor).GetOwner, refs("testprotos.AnotherTestMessage")},
   482  						"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage")},
   483  						"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   484  						"one of":       {(*FieldDescriptor).GetOneOf, nil},
   485  					},
   486  				},
   487  				{
   488  					name:   "testprotos.xs",
   489  					number: 101,
   490  					references: map[string]childCases{
   491  						"owner":        {(*FieldDescriptor).GetOwner, refs("testprotos.AnotherTestMessage")},
   492  						"message type": {(*FieldDescriptor).GetMessageType, nil},
   493  						"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   494  						"one of":       {(*FieldDescriptor).GetOneOf, nil},
   495  					},
   496  				},
   497  				{
   498  					name:   "testprotos.xi",
   499  					number: 102,
   500  					references: map[string]childCases{
   501  						"owner":        {(*FieldDescriptor).GetOwner, refs("testprotos.AnotherTestMessage")},
   502  						"message type": {(*FieldDescriptor).GetMessageType, nil},
   503  						"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   504  						"one of":       {(*FieldDescriptor).GetOneOf, nil},
   505  					},
   506  				},
   507  				{
   508  					name:   "testprotos.xui",
   509  					number: 103,
   510  					references: map[string]childCases{
   511  						"owner":        {(*FieldDescriptor).GetOwner, refs("testprotos.AnotherTestMessage")},
   512  						"message type": {(*FieldDescriptor).GetMessageType, nil},
   513  						"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   514  						"one of":       {(*FieldDescriptor).GetOneOf, nil},
   515  					},
   516  				},
   517  			}},
   518  		},
   519  	})
   520  }
   521  
   522  func TestOneOfDescriptors(t *testing.T) {
   523  	fd, err := LoadFileDescriptor("desc_test2.proto")
   524  	testutil.Ok(t, err)
   525  	md, err := LoadMessageDescriptor("testprotos.Frobnitz")
   526  	testutil.Ok(t, err)
   527  	checkDescriptor(t, "message", 0, md, fd, fd, descCase{
   528  		name: "testprotos.Frobnitz",
   529  		references: map[string]childCases{
   530  			"fields": {(*MessageDescriptor).GetFields, []descCase{
   531  				{
   532  					name: "testprotos.Frobnitz.a",
   533  					references: map[string]childCases{
   534  						"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage")},
   535  						"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   536  						"one of":       {(*FieldDescriptor).GetOneOf, nil},
   537  					},
   538  				},
   539  				{
   540  					name: "testprotos.Frobnitz.b",
   541  					references: map[string]childCases{
   542  						"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage")},
   543  						"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   544  						"one of":       {(*FieldDescriptor).GetOneOf, nil},
   545  					},
   546  				},
   547  				{
   548  					name: "testprotos.Frobnitz.c1",
   549  					references: map[string]childCases{
   550  						"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage")},
   551  						"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   552  						"one of":       {(*FieldDescriptor).GetOneOf, refs("testprotos.Frobnitz.abc")},
   553  					},
   554  				},
   555  				{
   556  					name: "testprotos.Frobnitz.c2",
   557  					references: map[string]childCases{
   558  						"message type": {(*FieldDescriptor).GetMessageType, nil},
   559  						"enum type":    {(*FieldDescriptor).GetEnumType, refs("testprotos.TestMessage.NestedEnum")},
   560  						"one of":       {(*FieldDescriptor).GetOneOf, refs("testprotos.Frobnitz.abc")},
   561  					},
   562  				},
   563  				{
   564  					name: "testprotos.Frobnitz.d",
   565  					references: map[string]childCases{
   566  						"message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage")},
   567  						"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   568  						"one of":       {(*FieldDescriptor).GetOneOf, nil},
   569  					},
   570  				},
   571  				{
   572  					name: "testprotos.Frobnitz.e",
   573  					references: map[string]childCases{
   574  						"message type": {(*FieldDescriptor).GetMessageType, nil},
   575  						"enum type":    {(*FieldDescriptor).GetEnumType, refs("testprotos.TestMessage.NestedEnum")},
   576  						"one of":       {(*FieldDescriptor).GetOneOf, nil},
   577  					},
   578  				},
   579  				{
   580  					name: "testprotos.Frobnitz.f",
   581  					references: map[string]childCases{
   582  						"message type": {(*FieldDescriptor).GetMessageType, nil},
   583  						"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   584  						"one of":       {(*FieldDescriptor).GetOneOf, nil},
   585  					},
   586  				},
   587  				{
   588  					name: "testprotos.Frobnitz.g1",
   589  					references: map[string]childCases{
   590  						"message type": {(*FieldDescriptor).GetMessageType, nil},
   591  						"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   592  						"one of":       {(*FieldDescriptor).GetOneOf, refs("testprotos.Frobnitz.def")},
   593  					},
   594  				},
   595  				{
   596  					name: "testprotos.Frobnitz.g2",
   597  					references: map[string]childCases{
   598  						"message type": {(*FieldDescriptor).GetMessageType, nil},
   599  						"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   600  						"one of":       {(*FieldDescriptor).GetOneOf, refs("testprotos.Frobnitz.def")},
   601  					},
   602  				},
   603  				{
   604  					name: "testprotos.Frobnitz.g3",
   605  					references: map[string]childCases{
   606  						"message type": {(*FieldDescriptor).GetMessageType, nil},
   607  						"enum type":    {(*FieldDescriptor).GetEnumType, nil},
   608  						"one of":       {(*FieldDescriptor).GetOneOf, refs("testprotos.Frobnitz.def")},
   609  					},
   610  				},
   611  			}},
   612  			"nested messages":   {(*MessageDescriptor).GetNestedMessageTypes, nil},
   613  			"nested enums":      {(*MessageDescriptor).GetNestedEnumTypes, nil},
   614  			"nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil},
   615  			"one ofs": {(*MessageDescriptor).GetOneOfs, []descCase{
   616  				{
   617  					name:       "testprotos.Frobnitz.abc",
   618  					skipParent: true,
   619  					references: map[string]childCases{
   620  						"fields": {(*OneOfDescriptor).GetChoices, fields(
   621  							fld{"testprotos.Frobnitz.c1", 3},
   622  							fld{"testprotos.Frobnitz.c2", 4}),
   623  						},
   624  					},
   625  				},
   626  				{
   627  					name:       "testprotos.Frobnitz.def",
   628  					skipParent: true,
   629  					references: map[string]childCases{
   630  						"fields": {(*OneOfDescriptor).GetChoices, fields(
   631  							fld{"testprotos.Frobnitz.g1", 8},
   632  							fld{"testprotos.Frobnitz.g2", 9},
   633  							fld{"testprotos.Frobnitz.g3", 10}),
   634  						},
   635  					},
   636  				},
   637  			}},
   638  		},
   639  	})
   640  }
   641  
   642  func TestMessageDescriptorFindField(t *testing.T) {
   643  	md, err := LoadMessageDescriptor("testprotos.Frobnitz")
   644  	testutil.Ok(t, err)
   645  	for _, fd := range md.GetFields() {
   646  		found := md.FindFieldByName(fd.GetName())
   647  		testutil.Eq(t, fd, found)
   648  		found = md.FindFieldByNumber(fd.GetNumber())
   649  		testutil.Eq(t, fd, found)
   650  	}
   651  	testutil.Eq(t, (*FieldDescriptor)(nil), md.FindFieldByName("junk name"))
   652  	testutil.Eq(t, (*FieldDescriptor)(nil), md.FindFieldByNumber(99999))
   653  }
   654  
   655  func TestEnumDescriptorFindValue(t *testing.T) {
   656  	fd, err := LoadFileDescriptor("desc_test_defaults.proto")
   657  	testutil.Ok(t, err)
   658  	ed, ok := fd.FindSymbol("testprotos.Number").(*EnumDescriptor)
   659  	testutil.Eq(t, true, ok)
   660  	lastNumber := int32(-1)
   661  	for _, vd := range ed.GetValues() {
   662  		found := ed.FindValueByName(vd.GetName())
   663  		testutil.Eq(t, vd, found)
   664  		found = ed.FindValueByNumber(vd.GetNumber())
   665  		if lastNumber == vd.GetNumber() {
   666  			// found value will be the first one with the given number, not this one
   667  			testutil.Eq(t, false, vd == found)
   668  		} else {
   669  			testutil.Eq(t, vd, found)
   670  			lastNumber = vd.GetNumber()
   671  		}
   672  	}
   673  	testutil.Eq(t, (*EnumValueDescriptor)(nil), ed.FindValueByName("junk name"))
   674  	testutil.Eq(t, (*EnumValueDescriptor)(nil), ed.FindValueByNumber(99999))
   675  }
   676  
   677  func TestServiceDescriptors(t *testing.T) {
   678  	fd, err := LoadFileDescriptor("desc_test_proto3.proto")
   679  	testutil.Ok(t, err)
   680  	sd := fd.FindSymbol("testprotos.TestService").(*ServiceDescriptor)
   681  	// check the descriptor graph for this service and its descendants
   682  	checkDescriptor(t, "service", 0, sd, fd, fd, descCase{
   683  		name: "testprotos.TestService",
   684  		references: map[string]childCases{
   685  			"methods": {(*ServiceDescriptor).GetMethods, []descCase{
   686  				{
   687  					name: "testprotos.TestService.DoSomething",
   688  					references: map[string]childCases{
   689  						"request":  {(*MethodDescriptor).GetInputType, refs("testprotos.TestRequest")},
   690  						"response": {(*MethodDescriptor).GetOutputType, refs("jhump.protoreflect.desc.Bar")},
   691  					},
   692  				},
   693  				{
   694  					name: "testprotos.TestService.DoSomethingElse",
   695  					references: map[string]childCases{
   696  						"request":  {(*MethodDescriptor).GetInputType, refs("testprotos.TestMessage")},
   697  						"response": {(*MethodDescriptor).GetOutputType, refs("testprotos.TestResponse")},
   698  					},
   699  				},
   700  				{
   701  					name: "testprotos.TestService.DoSomethingAgain",
   702  					references: map[string]childCases{
   703  						"request":  {(*MethodDescriptor).GetInputType, refs("jhump.protoreflect.desc.Bar")},
   704  						"response": {(*MethodDescriptor).GetOutputType, refs("testprotos.AnotherTestMessage")},
   705  					},
   706  				},
   707  				{
   708  					name: "testprotos.TestService.DoSomethingForever",
   709  					references: map[string]childCases{
   710  						"request":  {(*MethodDescriptor).GetInputType, refs("testprotos.TestRequest")},
   711  						"response": {(*MethodDescriptor).GetOutputType, refs("testprotos.TestResponse")},
   712  					},
   713  				},
   714  			}},
   715  		},
   716  	})
   717  	// now verify that FindMethodByName works correctly
   718  	for _, md := range sd.GetMethods() {
   719  		found := sd.FindMethodByName(md.GetName())
   720  		testutil.Eq(t, md, found)
   721  	}
   722  	testutil.Eq(t, (*MethodDescriptor)(nil), sd.FindMethodByName("junk name"))
   723  }
   724  
   725  type descCase struct {
   726  	name       string
   727  	number     int32
   728  	skipParent bool
   729  	references map[string]childCases
   730  }
   731  
   732  type childCases struct {
   733  	query interface{}
   734  	cases []descCase
   735  }
   736  
   737  func refs(names ...string) []descCase {
   738  	r := make([]descCase, len(names))
   739  	for i, n := range names {
   740  		r[i] = descCase{name: n, skipParent: true}
   741  	}
   742  	return r
   743  }
   744  
   745  func children(names ...string) []descCase {
   746  	ch := make([]descCase, len(names))
   747  	for i, n := range names {
   748  		ch[i] = descCase{name: n}
   749  	}
   750  	return ch
   751  }
   752  
   753  type fld struct {
   754  	name   string
   755  	number int32
   756  }
   757  
   758  func fields(flds ...fld) []descCase {
   759  	f := make([]descCase, len(flds))
   760  	for i, field := range flds {
   761  		f[i] = descCase{name: field.name, number: field.number, skipParent: true}
   762  	}
   763  	return f
   764  }
   765  
   766  func checkDescriptor(t *testing.T, caseName string, num int32, d Descriptor, parent Descriptor, fd *FileDescriptor, c descCase) {
   767  	// name and fully-qualified name
   768  	testutil.Eq(t, c.name, d.GetFullyQualifiedName(), caseName)
   769  	if _, ok := d.(*FileDescriptor); ok {
   770  		testutil.Eq(t, c.name, d.GetName(), caseName)
   771  	} else {
   772  		pos := strings.LastIndex(c.name, ".")
   773  		n := c.name
   774  		if pos >= 0 {
   775  			n = c.name[pos+1:]
   776  		}
   777  		testutil.Eq(t, n, d.GetName(), caseName)
   778  		// check that this object matches the canonical one returned by file descriptor
   779  		testutil.Eq(t, d, d.GetFile().FindSymbol(d.GetFullyQualifiedName()), caseName)
   780  	}
   781  
   782  	// number
   783  	switch d := d.(type) {
   784  	case (*FieldDescriptor):
   785  		n := num + 1
   786  		if c.number != 0 {
   787  			n = c.number
   788  		}
   789  		testutil.Eq(t, n, d.GetNumber(), caseName)
   790  	case (*EnumValueDescriptor):
   791  		n := num + 1
   792  		if c.number != 0 {
   793  			n = c.number
   794  		}
   795  		testutil.Eq(t, n, d.GetNumber(), caseName)
   796  	default:
   797  		if c.number != 0 {
   798  			panic(fmt.Sprintf("%s: number should only be specified by fields and enum values! numnber = %d, desc = %v", caseName, c.number, d))
   799  		}
   800  	}
   801  
   802  	// parent and file
   803  	if !c.skipParent {
   804  		testutil.Eq(t, parent, d.GetParent(), caseName)
   805  		testutil.Eq(t, fd, d.GetFile(), caseName)
   806  	}
   807  
   808  	// comment
   809  	if fd.GetName() == "desc_test1.proto" && d.GetName() != "desc_test1.proto" {
   810  		expectedComment := "Comment for " + d.GetName()
   811  		if msg, ok := d.(*MessageDescriptor); ok && msg.IsMapEntry() {
   812  			// There are no comments on synthetic map-entry messages.
   813  			expectedComment = ""
   814  		} else if field, ok := d.(*FieldDescriptor); ok {
   815  			if field.GetOwner().IsMapEntry() || field.GetType() == dpb.FieldDescriptorProto_TYPE_GROUP {
   816  				// There are no comments for fields of synthetic map-entry messages either.
   817  				// And comments for group fields end up on the synthetic message, not the field.
   818  				expectedComment = ""
   819  			}
   820  		}
   821  		testutil.Eq(t, expectedComment, strings.TrimSpace(d.GetSourceInfo().GetLeadingComments()), caseName)
   822  	}
   823  
   824  	// references
   825  	for name, cases := range c.references {
   826  		caseName := fmt.Sprintf("%s>%s", caseName, name)
   827  		children := runQuery(d, cases.query)
   828  		if testutil.Eq(t, len(cases.cases), len(children), caseName+" length") {
   829  			for i, childCase := range cases.cases {
   830  				caseName := fmt.Sprintf("%s[%d]", caseName, i)
   831  				checkDescriptor(t, caseName, int32(i), children[i], d, fd, childCase)
   832  			}
   833  		}
   834  	}
   835  }
   836  
   837  func runQuery(d Descriptor, query interface{}) []Descriptor {
   838  	r := reflect.ValueOf(query).Call([]reflect.Value{reflect.ValueOf(d)})[0]
   839  	if r.Kind() == reflect.Slice {
   840  		ret := make([]Descriptor, r.Len())
   841  		for i := 0; i < r.Len(); i++ {
   842  			ret[i] = r.Index(i).Interface().(Descriptor)
   843  		}
   844  		return ret
   845  	} else if r.IsNil() {
   846  		return []Descriptor{}
   847  	} else {
   848  		return []Descriptor{r.Interface().(Descriptor)}
   849  	}
   850  }
   851  
   852  func TestFileDescriptorDeps(t *testing.T) {
   853  	// tests accessors for public and weak dependencies
   854  	fd1 := createDesc(t, &dpb.FileDescriptorProto{Name: proto.String("a")})
   855  	fd2 := createDesc(t, &dpb.FileDescriptorProto{Name: proto.String("b")})
   856  	fd3 := createDesc(t, &dpb.FileDescriptorProto{Name: proto.String("c")})
   857  	fd4 := createDesc(t, &dpb.FileDescriptorProto{Name: proto.String("d")})
   858  	fd5 := createDesc(t, &dpb.FileDescriptorProto{Name: proto.String("e")})
   859  	fd := createDesc(t, &dpb.FileDescriptorProto{
   860  		Name:             proto.String("f"),
   861  		Dependency:       []string{"a", "b", "c", "d", "e"},
   862  		PublicDependency: []int32{1, 3},
   863  		WeakDependency:   []int32{2, 4},
   864  	}, fd1, fd2, fd3, fd4, fd5)
   865  
   866  	deps := fd.GetDependencies()
   867  	testutil.Eq(t, 5, len(deps))
   868  	testutil.Eq(t, fd1, deps[0])
   869  	testutil.Eq(t, fd2, deps[1])
   870  	testutil.Eq(t, fd3, deps[2])
   871  	testutil.Eq(t, fd4, deps[3])
   872  	testutil.Eq(t, fd5, deps[4])
   873  
   874  	deps = fd.GetPublicDependencies()
   875  	testutil.Eq(t, 2, len(deps))
   876  	testutil.Eq(t, fd2, deps[0])
   877  	testutil.Eq(t, fd4, deps[1])
   878  
   879  	deps = fd.GetWeakDependencies()
   880  	testutil.Eq(t, 2, len(deps))
   881  	testutil.Eq(t, fd3, deps[0])
   882  	testutil.Eq(t, fd5, deps[1])
   883  
   884  	// Now try on a simple descriptor emitted by protoc
   885  	fd6, err := LoadFileDescriptor("nopkg/desc_test_nopkg.proto")
   886  	testutil.Ok(t, err)
   887  	fd7, err := LoadFileDescriptor("nopkg/desc_test_nopkg_new.proto")
   888  	testutil.Ok(t, err)
   889  	deps = fd6.GetPublicDependencies()
   890  	testutil.Eq(t, 1, len(deps))
   891  	testutil.Eq(t, fd7, deps[0])
   892  }
   893  
   894  func createDesc(t *testing.T, fd *dpb.FileDescriptorProto, deps ...*FileDescriptor) *FileDescriptor {
   895  	desc, err := CreateFileDescriptor(fd, deps...)
   896  	testutil.Ok(t, err)
   897  	return desc
   898  }
   899  
   900  func TestLoadFileDescriptor(t *testing.T) {
   901  	fd, err := LoadFileDescriptor("desc_test1.proto")
   902  	testutil.Ok(t, err)
   903  	// some very shallow tests (we have more detailed ones in other test cases)
   904  	testutil.Eq(t, "desc_test1.proto", fd.GetName())
   905  	testutil.Eq(t, "desc_test1.proto", fd.GetFullyQualifiedName())
   906  	testutil.Eq(t, "testprotos", fd.GetPackage())
   907  }
   908  
   909  func TestLoadMessageDescriptor(t *testing.T) {
   910  	// loading enclosed messages should return the same descriptor
   911  	// and have a reference to the same file descriptor
   912  	md, err := LoadMessageDescriptor("testprotos.TestMessage")
   913  	testutil.Ok(t, err)
   914  	testutil.Eq(t, "TestMessage", md.GetName())
   915  	testutil.Eq(t, "testprotos.TestMessage", md.GetFullyQualifiedName())
   916  	fd := md.GetFile()
   917  	testutil.Eq(t, "desc_test1.proto", fd.GetName())
   918  	testutil.Eq(t, fd, md.GetParent())
   919  
   920  	md2, err := LoadMessageDescriptorForMessage((*testprotos.TestMessage)(nil))
   921  	testutil.Ok(t, err)
   922  	testutil.Eq(t, md, md2)
   923  
   924  	md3, err := LoadMessageDescriptorForType(reflect.TypeOf((*testprotos.TestMessage)(nil)))
   925  	testutil.Ok(t, err)
   926  	testutil.Eq(t, md, md3)
   927  }
   928  
   929  func TestLoadEnumDescriptor(t *testing.T) {
   930  	ed, err := LoadEnumDescriptorForEnum(testprotos.TestMessage_NestedMessage_AnotherNestedMessage_YetAnotherNestedMessage_DeeplyNestedEnum(0))
   931  	testutil.Ok(t, err)
   932  	testutil.Eq(t, "DeeplyNestedEnum", ed.GetName())
   933  	testutil.Eq(t, "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.DeeplyNestedEnum", ed.GetFullyQualifiedName())
   934  	fd := ed.GetFile()
   935  	testutil.Eq(t, "desc_test1.proto", fd.GetName())
   936  	ofd, err := LoadFileDescriptor("desc_test1.proto")
   937  	testutil.Ok(t, err)
   938  	testutil.Eq(t, ofd, fd)
   939  
   940  	ed2, err := LoadEnumDescriptorForEnum((*testprotos.TestEnum)(nil)) // pointer type for interface
   941  	testutil.Ok(t, err)
   942  	testutil.Eq(t, "TestEnum", ed2.GetName())
   943  	testutil.Eq(t, "testprotos.TestEnum", ed2.GetFullyQualifiedName())
   944  	fd = ed2.GetFile()
   945  	testutil.Eq(t, "desc_test_field_types.proto", fd.GetName())
   946  	ofd, err = LoadFileDescriptor("desc_test_field_types.proto")
   947  	testutil.Ok(t, err)
   948  	testutil.Eq(t, ofd, fd)
   949  	testutil.Eq(t, fd, ed2.GetParent())
   950  
   951  	// now use the APIs that take reflect.Type
   952  	ed3, err := LoadEnumDescriptorForType(reflect.TypeOf((*testprotos.TestMessage_NestedMessage_AnotherNestedMessage_YetAnotherNestedMessage_DeeplyNestedEnum)(nil)))
   953  	testutil.Ok(t, err)
   954  	testutil.Eq(t, ed, ed3)
   955  
   956  	ed4, err := LoadEnumDescriptorForType(reflect.TypeOf(testprotos.TestEnum_FIRST))
   957  	testutil.Ok(t, err)
   958  	testutil.Eq(t, ed2, ed4)
   959  }
   960  
   961  func TestLoadFileDescriptorWithDeps(t *testing.T) {
   962  	// Try one with some imports
   963  	fd, err := LoadFileDescriptor("desc_test2.proto")
   964  	testutil.Ok(t, err)
   965  	testutil.Eq(t, "desc_test2.proto", fd.GetName())
   966  	testutil.Eq(t, "desc_test2.proto", fd.GetFullyQualifiedName())
   967  	testutil.Eq(t, "testprotos", fd.GetPackage())
   968  
   969  	deps := fd.GetDependencies()
   970  	testutil.Eq(t, 3, len(deps))
   971  	testutil.Eq(t, "desc_test1.proto", deps[0].GetName())
   972  	testutil.Eq(t, "pkg/desc_test_pkg.proto", deps[1].GetName())
   973  	testutil.Eq(t, "nopkg/desc_test_nopkg.proto", deps[2].GetName())
   974  
   975  	// loading the dependencies yields same descriptor objects
   976  	fd, err = LoadFileDescriptor("desc_test1.proto")
   977  	testutil.Ok(t, err)
   978  	testutil.Eq(t, deps[0], fd)
   979  	fd, err = LoadFileDescriptor("pkg/desc_test_pkg.proto")
   980  	testutil.Ok(t, err)
   981  	testutil.Eq(t, deps[1], fd)
   982  	fd, err = LoadFileDescriptor("nopkg/desc_test_nopkg.proto")
   983  	testutil.Ok(t, err)
   984  	testutil.Eq(t, deps[2], fd)
   985  }
   986  
   987  func TestLoadFileDescriptorForWellKnownProtos(t *testing.T) {
   988  	wellKnownProtos := map[string][]string{
   989  		"google/protobuf/any.proto":             {"google.protobuf.Any"},
   990  		"google/protobuf/api.proto":             {"google.protobuf.Api", "google.protobuf.Method", "google.protobuf.Mixin"},
   991  		"google/protobuf/descriptor.proto":      {"google.protobuf.FileDescriptorSet", "google.protobuf.DescriptorProto"},
   992  		"google/protobuf/duration.proto":        {"google.protobuf.Duration"},
   993  		"google/protobuf/empty.proto":           {"google.protobuf.Empty"},
   994  		"google/protobuf/field_mask.proto":      {"google.protobuf.FieldMask"},
   995  		"google/protobuf/source_context.proto":  {"google.protobuf.SourceContext"},
   996  		"google/protobuf/struct.proto":          {"google.protobuf.Struct", "google.protobuf.Value", "google.protobuf.NullValue"},
   997  		"google/protobuf/timestamp.proto":       {"google.protobuf.Timestamp"},
   998  		"google/protobuf/type.proto":            {"google.protobuf.Type", "google.protobuf.Field", "google.protobuf.Syntax"},
   999  		"google/protobuf/wrappers.proto":        {"google.protobuf.DoubleValue", "google.protobuf.Int32Value", "google.protobuf.StringValue"},
  1000  		"google/protobuf/compiler/plugin.proto": {"google.protobuf.compiler.CodeGeneratorRequest"},
  1001  	}
  1002  
  1003  	for file, types := range wellKnownProtos {
  1004  		fd, err := LoadFileDescriptor(file)
  1005  		testutil.Ok(t, err)
  1006  		testutil.Eq(t, file, fd.GetName())
  1007  		for _, typ := range types {
  1008  			d := fd.FindSymbol(typ)
  1009  			testutil.Require(t, d != nil, "file %q does not have type %s", file, typ)
  1010  			d2 := fd.FindSymbol("." + typ)
  1011  			testutil.Eq(t, d, d2)
  1012  		}
  1013  
  1014  		// also try loading via alternate name
  1015  		file = internal.StdFileAliases[file]
  1016  		if file == "" {
  1017  			// not a file that has a known alternate, so nothing else to check...
  1018  			continue
  1019  		}
  1020  		fd, err = LoadFileDescriptor(file)
  1021  		testutil.Ok(t, err)
  1022  		testutil.Eq(t, file, fd.GetName())
  1023  		for _, typ := range types {
  1024  			d := fd.FindSymbol(typ)
  1025  			testutil.Require(t, d != nil, "file %q does not have type %s", file, typ)
  1026  			d2 := fd.FindSymbol("." + typ)
  1027  			testutil.Eq(t, d, d2)
  1028  		}
  1029  	}
  1030  }
  1031  
  1032  func TestDefaultValues(t *testing.T) {
  1033  	fd, err := LoadFileDescriptor("desc_test_defaults.proto")
  1034  	testutil.Ok(t, err)
  1035  
  1036  	testCases := []struct {
  1037  		message, field string
  1038  		defaultVal     interface{}
  1039  	}{
  1040  		{"testprotos.PrimitiveDefaults", "fl32", float32(3.14159)},
  1041  		{"testprotos.PrimitiveDefaults", "fl64", 3.14159},
  1042  		{"testprotos.PrimitiveDefaults", "fl32d", float32(6.022140857e23)},
  1043  		{"testprotos.PrimitiveDefaults", "fl64d", 6.022140857e23},
  1044  		{"testprotos.PrimitiveDefaults", "fl32inf", float32(math.Inf(1))},
  1045  		{"testprotos.PrimitiveDefaults", "fl64inf", math.Inf(1)},
  1046  		{"testprotos.PrimitiveDefaults", "fl32negInf", float32(math.Inf(-1))},
  1047  		{"testprotos.PrimitiveDefaults", "fl64negInf", math.Inf(-1)},
  1048  		{"testprotos.PrimitiveDefaults", "fl32nan", float32(math.NaN())},
  1049  		{"testprotos.PrimitiveDefaults", "fl64nan", math.NaN()},
  1050  		{"testprotos.PrimitiveDefaults", "bl1", true},
  1051  		{"testprotos.PrimitiveDefaults", "bl2", false},
  1052  		{"testprotos.PrimitiveDefaults", "i32", int32(10101)},
  1053  		{"testprotos.PrimitiveDefaults", "i32n", int32(-10101)},
  1054  		{"testprotos.PrimitiveDefaults", "i32x", int32(0x20202)},
  1055  		{"testprotos.PrimitiveDefaults", "i32xn", int32(-0x20202)},
  1056  		{"testprotos.PrimitiveDefaults", "i64", int64(10101)},
  1057  		{"testprotos.PrimitiveDefaults", "i64n", int64(-10101)},
  1058  		{"testprotos.PrimitiveDefaults", "i64x", int64(0x20202)},
  1059  		{"testprotos.PrimitiveDefaults", "i64xn", int64(-0x20202)},
  1060  		{"testprotos.PrimitiveDefaults", "i32s", int32(10101)},
  1061  		{"testprotos.PrimitiveDefaults", "i32sn", int32(-10101)},
  1062  		{"testprotos.PrimitiveDefaults", "i32sx", int32(0x20202)},
  1063  		{"testprotos.PrimitiveDefaults", "i32sxn", int32(-0x20202)},
  1064  		{"testprotos.PrimitiveDefaults", "i64s", int64(10101)},
  1065  		{"testprotos.PrimitiveDefaults", "i64sn", int64(-10101)},
  1066  		{"testprotos.PrimitiveDefaults", "i64sx", int64(0x20202)},
  1067  		{"testprotos.PrimitiveDefaults", "i64sxn", int64(-0x20202)},
  1068  		{"testprotos.PrimitiveDefaults", "i32f", int32(10101)},
  1069  		{"testprotos.PrimitiveDefaults", "i32fn", int32(-10101)},
  1070  		{"testprotos.PrimitiveDefaults", "i32fx", int32(0x20202)},
  1071  		{"testprotos.PrimitiveDefaults", "i32fxn", int32(-0x20202)},
  1072  		{"testprotos.PrimitiveDefaults", "i64f", int64(10101)},
  1073  		{"testprotos.PrimitiveDefaults", "i64fn", int64(-10101)},
  1074  		{"testprotos.PrimitiveDefaults", "i64fx", int64(0x20202)},
  1075  		{"testprotos.PrimitiveDefaults", "i64fxn", int64(-0x20202)},
  1076  		{"testprotos.PrimitiveDefaults", "u32", uint32(10101)},
  1077  		{"testprotos.PrimitiveDefaults", "u32x", uint32(0x20202)},
  1078  		{"testprotos.PrimitiveDefaults", "u64", uint64(10101)},
  1079  		{"testprotos.PrimitiveDefaults", "u64x", uint64(0x20202)},
  1080  		{"testprotos.PrimitiveDefaults", "u32f", uint32(10101)},
  1081  		{"testprotos.PrimitiveDefaults", "u32fx", uint32(0x20202)},
  1082  		{"testprotos.PrimitiveDefaults", "u64f", uint64(10101)},
  1083  		{"testprotos.PrimitiveDefaults", "u64fx", uint64(0x20202)},
  1084  
  1085  		{"testprotos.StringAndBytesDefaults", "dq", "this is a string with \"nested quotes\""},
  1086  		{"testprotos.StringAndBytesDefaults", "sq", "this is a string with \"nested quotes\""},
  1087  		{"testprotos.StringAndBytesDefaults", "escaped_bytes", []byte("\000\001\a\b\f\n\r\t\v\\'\"\xfe")},
  1088  		{"testprotos.StringAndBytesDefaults", "utf8_string", "\341\210\264"},
  1089  		{"testprotos.StringAndBytesDefaults", "string_with_zero", "hel\000lo"},
  1090  		{"testprotos.StringAndBytesDefaults", "bytes_with_zero", []byte("wor\000ld")},
  1091  
  1092  		{"testprotos.EnumDefaults", "red", int32(0)},
  1093  		{"testprotos.EnumDefaults", "green", int32(1)},
  1094  		{"testprotos.EnumDefaults", "blue", int32(2)},
  1095  		{"testprotos.EnumDefaults", "zero", int32(0)},
  1096  		{"testprotos.EnumDefaults", "zed", int32(0)},
  1097  		{"testprotos.EnumDefaults", "one", int32(1)},
  1098  		{"testprotos.EnumDefaults", "dos", int32(2)},
  1099  	}
  1100  	for i, tc := range testCases {
  1101  		def := fd.FindMessage(tc.message).FindFieldByName(tc.field).GetDefaultValue()
  1102  		testutil.Eq(t, tc.defaultVal, def, "wrong default value for case %d: %s.%s", i, tc.message, tc.field)
  1103  	}
  1104  }
  1105  
  1106  func TestUnescape(t *testing.T) {
  1107  	testCases := []struct {
  1108  		in, out string
  1109  	}{
  1110  		// EOF, bad escapes
  1111  		{"\\", "\\"},
  1112  		{"\\y", "\\y"},
  1113  		// octal escapes
  1114  		{"\\0", "\000"},
  1115  		{"\\7", "\007"},
  1116  		{"\\07", "\007"},
  1117  		{"\\77", "\077"},
  1118  		{"\\78", "\0078"},
  1119  		{"\\077", "\077"},
  1120  		{"\\377", "\377"},
  1121  		{"\\128", "\0128"},
  1122  		{"\\0001", "\0001"},
  1123  		{"\\0008", "\0008"},
  1124  		// bad octal escape
  1125  		{"\\8", "\\8"},
  1126  		// hex escapes
  1127  		{"\\x0", "\x00"},
  1128  		{"\\x7", "\x07"},
  1129  		{"\\x07", "\x07"},
  1130  		{"\\x77", "\x77"},
  1131  		{"\\x7g", "\x07g"},
  1132  		{"\\xcc", "\xcc"},
  1133  		{"\\xfff", "\xfff"},
  1134  		// bad hex escape
  1135  		{"\\xg7", "\\xg7"},
  1136  		{"\\x", "\\x"},
  1137  		// short unicode escapes
  1138  		{"\\u0020", "\u0020"},
  1139  		{"\\u007e", "\u007e"},
  1140  		{"\\u1234", "\u1234"},
  1141  		{"\\uffff", "\uffff"},
  1142  		// long unicode escapes
  1143  		{"\\U00000024", "\U00000024"},
  1144  		{"\\U00000076", "\U00000076"},
  1145  		{"\\U00001234", "\U00001234"},
  1146  		{"\\U0010FFFF", "\U0010FFFF"},
  1147  		// bad unicode escapes
  1148  		{"\\u12", "\\u12"},
  1149  		{"\\ug1232", "\\ug1232"},
  1150  		{"\\u", "\\u"},
  1151  		{"\\U1234567", "\\U1234567"},
  1152  		{"\\U12345678", "\\U12345678"},
  1153  		{"\\U0010Fghi", "\\U0010Fghi"},
  1154  		{"\\U", "\\U"},
  1155  	}
  1156  	for _, tc := range testCases {
  1157  		for _, p := range []string{"", "prefix"} {
  1158  			for _, s := range []string{"", "suffix"} {
  1159  				i := p + tc.in + s
  1160  				o := p + tc.out + s
  1161  				u := unescape(i)
  1162  				testutil.Eq(t, o, u, "unescaped %q into %q, but should have been %q", i, u, o)
  1163  			}
  1164  		}
  1165  	}
  1166  }
  1167  
  1168  func loadProtoset(path string) (*FileDescriptor, error) {
  1169  	var fds dpb.FileDescriptorSet
  1170  	f, err := os.Open(path)
  1171  	if err != nil {
  1172  		return nil, err
  1173  	}
  1174  	defer f.Close()
  1175  	bb, err := ioutil.ReadAll(f)
  1176  	if err != nil {
  1177  		return nil, err
  1178  	}
  1179  	if err = proto.Unmarshal(bb, &fds); err != nil {
  1180  		return nil, err
  1181  	}
  1182  	return CreateFileDescriptorFromSet(&fds)
  1183  }
  1184  
  1185  func TestToFileDescriptorSet(t *testing.T) {
  1186  	fd, err := LoadFileDescriptor("desc_test2.proto")
  1187  	testutil.Ok(t, err, "failed to load descriptor")
  1188  	fdset := ToFileDescriptorSet(fd)
  1189  	expectedOrder := []string{
  1190  		"desc_test1.proto",
  1191  		"pkg/desc_test_pkg.proto",
  1192  		"nopkg/desc_test_nopkg_new.proto",
  1193  		"nopkg/desc_test_nopkg.proto",
  1194  		"desc_test2.proto",
  1195  	}
  1196  	testutil.Eq(t, len(expectedOrder), len(fdset.File), "wrong number of files in set")
  1197  	for i, f := range fdset.File {
  1198  		testutil.Eq(t, expectedOrder[i], f.GetName(), "wrong file at index %d", i+1)
  1199  		expectedFile, err := LoadFileDescriptor(f.GetName())
  1200  		testutil.Ok(t, err, "failed to load descriptor for %q", f.GetName())
  1201  		testutil.Eq(t, expectedFile.AsFileDescriptorProto(), f)
  1202  	}
  1203  }
  1204  
  1205  func TestJsonCamelCase(t *testing.T) {
  1206  	testCases := map[string]string{
  1207  		// NB: these simple test cases come from protoc's descriptor_unittest.cc:
  1208  		"field_name1":  "fieldName1",
  1209  		"fieldName2":   "fieldName2",
  1210  		"FieldName3":   "FieldName3",
  1211  		"_field_name4": "FieldName4",
  1212  		"FIELD_NAME5":  "FIELDNAME5",
  1213  
  1214  		// NB: these are more interesting examples; all keys were all run through
  1215  		// protoc and the values below are the json_name values computed by protoc
  1216  		// (to make sure we correctly mirror protoc behavior)
  1217  		"abc":       "abc",
  1218  		"__def":     "Def",
  1219  		"a_b_":      "aB",
  1220  		"d_e":       "dE",
  1221  		"abc_def":   "abcDef",
  1222  		"c_d_e":     "cDE",
  1223  		"_a_b_c_d":  "ABCD",
  1224  		"a_b_c_d_e": "aBCDE",
  1225  		"abc1":      "abc1",
  1226  		"__2def":    "2def",
  1227  		"a_b_3":     "aB3",
  1228  		"d_e4_":     "dE4",
  1229  		"abc4_5def": "abc45def",
  1230  	}
  1231  	for k, v := range testCases {
  1232  		testutil.Eq(t, v, jsonCamelCase(k))
  1233  	}
  1234  }
  1235  
  1236  func TestProto3Optional(t *testing.T) {
  1237  	fd, err := loadProtoset("../internal/testprotos/proto3_optional/desc_test_proto3_optional.protoset")
  1238  	testutil.Ok(t, err)
  1239  	md := fd.FindSymbol("MessageWithOptionalFields").(*MessageDescriptor)
  1240  	testutil.Eq(t, 2, len(md.GetOneOfs()))
  1241  	testutil.Eq(t, 2, len(md.GetFields()))
  1242  	for i, fld := range md.GetFields() {
  1243  		testutil.Require(t, fld.IsProto3Optional())
  1244  		testutil.Eq(t, fld.GetOneOf(), md.GetOneOfs()[i])
  1245  		testutil.Require(t, md.GetOneOfs()[i].IsSynthetic())
  1246  	}
  1247  	fld := fd.FindSymbol("some_custom_options").(*FieldDescriptor)
  1248  	testutil.Require(t, fld.IsProto3Optional())
  1249  }