...

Source file src/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/descriptor/registry_test.go

Documentation: github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/descriptor

     1  package descriptor
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/golang/protobuf/proto"
     7  	descriptor "github.com/golang/protobuf/protoc-gen-go/descriptor"
     8  	plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
     9  )
    10  
    11  func loadFile(t *testing.T, reg *Registry, src string) *descriptor.FileDescriptorProto {
    12  	var file descriptor.FileDescriptorProto
    13  	if err := proto.UnmarshalText(src, &file); err != nil {
    14  		t.Fatalf("proto.UnmarshalText(%s, &file) failed with %v; want success", src, err)
    15  	}
    16  	reg.loadFile(&file)
    17  	return &file
    18  }
    19  
    20  func load(t *testing.T, reg *Registry, src string) error {
    21  	var req plugin.CodeGeneratorRequest
    22  	if err := proto.UnmarshalText(src, &req); err != nil {
    23  		t.Fatalf("proto.UnmarshalText(%s, &file) failed with %v; want success", src, err)
    24  	}
    25  	return reg.Load(&req)
    26  }
    27  
    28  func TestLoadFile(t *testing.T) {
    29  	reg := NewRegistry()
    30  	fd := loadFile(t, reg, `
    31  		name: 'example.proto'
    32  		package: 'example'
    33  		message_type <
    34  			name: 'ExampleMessage'
    35  			field <
    36  				name: 'str'
    37  				label: LABEL_OPTIONAL
    38  				type: TYPE_STRING
    39  				number: 1
    40  			>
    41  		>
    42  	`)
    43  
    44  	file := reg.files["example.proto"]
    45  	if file == nil {
    46  		t.Errorf("reg.files[%q] = nil; want non-nil", "example.proto")
    47  		return
    48  	}
    49  	wantPkg := GoPackage{Path: ".", Name: "example"}
    50  	if got, want := file.GoPkg, wantPkg; got != want {
    51  		t.Errorf("file.GoPkg = %#v; want %#v", got, want)
    52  	}
    53  
    54  	msg, err := reg.LookupMsg("", ".example.ExampleMessage")
    55  	if err != nil {
    56  		t.Errorf("reg.LookupMsg(%q, %q)) failed with %v; want success", "", ".example.ExampleMessage", err)
    57  		return
    58  	}
    59  	if got, want := msg.DescriptorProto, fd.MessageType[0]; got != want {
    60  		t.Errorf("reg.lookupMsg(%q, %q).DescriptorProto = %#v; want %#v", "", ".example.ExampleMessage", got, want)
    61  	}
    62  	if got, want := msg.File, file; got != want {
    63  		t.Errorf("msg.File = %v; want %v", got, want)
    64  	}
    65  	if got := msg.Outers; got != nil {
    66  		t.Errorf("msg.Outers = %v; want %v", got, nil)
    67  	}
    68  	if got, want := len(msg.Fields), 1; got != want {
    69  		t.Errorf("len(msg.Fields) = %d; want %d", got, want)
    70  	} else if got, want := msg.Fields[0].FieldDescriptorProto, fd.MessageType[0].Field[0]; got != want {
    71  		t.Errorf("msg.Fields[0].FieldDescriptorProto = %v; want %v", got, want)
    72  	} else if got, want := msg.Fields[0].Message, msg; got != want {
    73  		t.Errorf("msg.Fields[0].Message = %v; want %v", got, want)
    74  	}
    75  
    76  	if got, want := len(file.Messages), 1; got != want {
    77  		t.Errorf("file.Meeesages = %#v; want %#v", file.Messages, []*Message{msg})
    78  	}
    79  	if got, want := file.Messages[0], msg; got != want {
    80  		t.Errorf("file.Meeesages[0] = %v; want %v", got, want)
    81  	}
    82  }
    83  
    84  func TestLoadFileNestedPackage(t *testing.T) {
    85  	reg := NewRegistry()
    86  	loadFile(t, reg, `
    87  		name: 'example.proto'
    88  		package: 'example.nested.nested2'
    89  	`)
    90  
    91  	file := reg.files["example.proto"]
    92  	if file == nil {
    93  		t.Errorf("reg.files[%q] = nil; want non-nil", "example.proto")
    94  		return
    95  	}
    96  	wantPkg := GoPackage{Path: ".", Name: "example_nested_nested2"}
    97  	if got, want := file.GoPkg, wantPkg; got != want {
    98  		t.Errorf("file.GoPkg = %#v; want %#v", got, want)
    99  	}
   100  }
   101  
   102  func TestLoadFileWithDir(t *testing.T) {
   103  	reg := NewRegistry()
   104  	loadFile(t, reg, `
   105  		name: 'path/to/example.proto'
   106  		package: 'example'
   107  	`)
   108  
   109  	file := reg.files["path/to/example.proto"]
   110  	if file == nil {
   111  		t.Errorf("reg.files[%q] = nil; want non-nil", "example.proto")
   112  		return
   113  	}
   114  	wantPkg := GoPackage{Path: "path/to", Name: "example"}
   115  	if got, want := file.GoPkg, wantPkg; got != want {
   116  		t.Errorf("file.GoPkg = %#v; want %#v", got, want)
   117  	}
   118  }
   119  
   120  func TestLoadFileWithoutPackage(t *testing.T) {
   121  	reg := NewRegistry()
   122  	loadFile(t, reg, `
   123  		name: 'path/to/example_file.proto'
   124  	`)
   125  
   126  	file := reg.files["path/to/example_file.proto"]
   127  	if file == nil {
   128  		t.Errorf("reg.files[%q] = nil; want non-nil", "example.proto")
   129  		return
   130  	}
   131  	wantPkg := GoPackage{Path: "path/to", Name: "example_file"}
   132  	if got, want := file.GoPkg, wantPkg; got != want {
   133  		t.Errorf("file.GoPkg = %#v; want %#v", got, want)
   134  	}
   135  }
   136  
   137  func TestLoadFileWithMapping(t *testing.T) {
   138  	reg := NewRegistry()
   139  	reg.AddPkgMap("path/to/example.proto", "example.com/proj/example/proto")
   140  	loadFile(t, reg, `
   141  		name: 'path/to/example.proto'
   142  		package: 'example'
   143  	`)
   144  
   145  	file := reg.files["path/to/example.proto"]
   146  	if file == nil {
   147  		t.Errorf("reg.files[%q] = nil; want non-nil", "example.proto")
   148  		return
   149  	}
   150  	wantPkg := GoPackage{Path: "example.com/proj/example/proto", Name: "example"}
   151  	if got, want := file.GoPkg, wantPkg; got != want {
   152  		t.Errorf("file.GoPkg = %#v; want %#v", got, want)
   153  	}
   154  }
   155  
   156  func TestLoadFileWithPackageNameCollision(t *testing.T) {
   157  	reg := NewRegistry()
   158  	loadFile(t, reg, `
   159  		name: 'path/to/another.proto'
   160  		package: 'example'
   161  	`)
   162  	loadFile(t, reg, `
   163  		name: 'path/to/example.proto'
   164  		package: 'example'
   165  	`)
   166  	if err := reg.ReserveGoPackageAlias("ioutil", "io/ioutil"); err != nil {
   167  		t.Fatalf("reg.ReserveGoPackageAlias(%q) failed with %v; want success", "ioutil", err)
   168  	}
   169  	loadFile(t, reg, `
   170  		name: 'path/to/ioutil.proto'
   171  		package: 'ioutil'
   172  	`)
   173  
   174  	file := reg.files["path/to/another.proto"]
   175  	if file == nil {
   176  		t.Errorf("reg.files[%q] = nil; want non-nil", "path/to/another.proto")
   177  		return
   178  	}
   179  	wantPkg := GoPackage{Path: "path/to", Name: "example"}
   180  	if got, want := file.GoPkg, wantPkg; got != want {
   181  		t.Errorf("file.GoPkg = %#v; want %#v", got, want)
   182  	}
   183  
   184  	file = reg.files["path/to/example.proto"]
   185  	if file == nil {
   186  		t.Errorf("reg.files[%q] = nil; want non-nil", "path/to/example.proto")
   187  		return
   188  	}
   189  	wantPkg = GoPackage{Path: "path/to", Name: "example", Alias: ""}
   190  	if got, want := file.GoPkg, wantPkg; got != want {
   191  		t.Errorf("file.GoPkg = %#v; want %#v", got, want)
   192  	}
   193  
   194  	file = reg.files["path/to/ioutil.proto"]
   195  	if file == nil {
   196  		t.Errorf("reg.files[%q] = nil; want non-nil", "path/to/ioutil.proto")
   197  		return
   198  	}
   199  	wantPkg = GoPackage{Path: "path/to", Name: "ioutil", Alias: "ioutil_0"}
   200  	if got, want := file.GoPkg, wantPkg; got != want {
   201  		t.Errorf("file.GoPkg = %#v; want %#v", got, want)
   202  	}
   203  }
   204  
   205  func TestLoadFileWithIdenticalGoPkg(t *testing.T) {
   206  	reg := NewRegistry()
   207  	reg.AddPkgMap("path/to/another.proto", "example.com/example")
   208  	reg.AddPkgMap("path/to/example.proto", "example.com/example")
   209  	loadFile(t, reg, `
   210  		name: 'path/to/another.proto'
   211  		package: 'example'
   212  	`)
   213  	loadFile(t, reg, `
   214  		name: 'path/to/example.proto'
   215  		package: 'example'
   216  	`)
   217  
   218  	file := reg.files["path/to/example.proto"]
   219  	if file == nil {
   220  		t.Errorf("reg.files[%q] = nil; want non-nil", "example.proto")
   221  		return
   222  	}
   223  	wantPkg := GoPackage{Path: "example.com/example", Name: "example"}
   224  	if got, want := file.GoPkg, wantPkg; got != want {
   225  		t.Errorf("file.GoPkg = %#v; want %#v", got, want)
   226  	}
   227  
   228  	file = reg.files["path/to/another.proto"]
   229  	if file == nil {
   230  		t.Errorf("reg.files[%q] = nil; want non-nil", "example.proto")
   231  		return
   232  	}
   233  	wantPkg = GoPackage{Path: "example.com/example", Name: "example"}
   234  	if got, want := file.GoPkg, wantPkg; got != want {
   235  		t.Errorf("file.GoPkg = %#v; want %#v", got, want)
   236  	}
   237  }
   238  
   239  func TestLoadFileWithPrefix(t *testing.T) {
   240  	reg := NewRegistry()
   241  	reg.SetPrefix("third_party")
   242  	loadFile(t, reg, `
   243  		name: 'path/to/example.proto'
   244  		package: 'example'
   245  	`)
   246  
   247  	file := reg.files["path/to/example.proto"]
   248  	if file == nil {
   249  		t.Errorf("reg.files[%q] = nil; want non-nil", "example.proto")
   250  		return
   251  	}
   252  	wantPkg := GoPackage{Path: "third_party/path/to", Name: "example"}
   253  	if got, want := file.GoPkg, wantPkg; got != want {
   254  		t.Errorf("file.GoPkg = %#v; want %#v", got, want)
   255  	}
   256  }
   257  
   258  func TestLookupMsgWithoutPackage(t *testing.T) {
   259  	reg := NewRegistry()
   260  	fd := loadFile(t, reg, `
   261  		name: 'example.proto'
   262  		message_type <
   263  			name: 'ExampleMessage'
   264  			field <
   265  				name: 'str'
   266  				label: LABEL_OPTIONAL
   267  				type: TYPE_STRING
   268  				number: 1
   269  			>
   270  		>
   271  	`)
   272  
   273  	msg, err := reg.LookupMsg("", ".ExampleMessage")
   274  	if err != nil {
   275  		t.Errorf("reg.LookupMsg(%q, %q)) failed with %v; want success", "", ".ExampleMessage", err)
   276  		return
   277  	}
   278  	if got, want := msg.DescriptorProto, fd.MessageType[0]; got != want {
   279  		t.Errorf("reg.lookupMsg(%q, %q).DescriptorProto = %#v; want %#v", "", ".ExampleMessage", got, want)
   280  	}
   281  }
   282  
   283  func TestLookupMsgWithNestedPackage(t *testing.T) {
   284  	reg := NewRegistry()
   285  	fd := loadFile(t, reg, `
   286  		name: 'example.proto'
   287  		package: 'nested.nested2.mypackage'
   288  		message_type <
   289  			name: 'ExampleMessage'
   290  			field <
   291  				name: 'str'
   292  				label: LABEL_OPTIONAL
   293  				type: TYPE_STRING
   294  				number: 1
   295  			>
   296  		>
   297  	`)
   298  
   299  	for _, name := range []string{
   300  		"nested.nested2.mypackage.ExampleMessage",
   301  		"nested2.mypackage.ExampleMessage",
   302  		"mypackage.ExampleMessage",
   303  		"ExampleMessage",
   304  	} {
   305  		msg, err := reg.LookupMsg("nested.nested2.mypackage", name)
   306  		if err != nil {
   307  			t.Errorf("reg.LookupMsg(%q, %q)) failed with %v; want success", ".nested.nested2.mypackage", name, err)
   308  			return
   309  		}
   310  		if got, want := msg.DescriptorProto, fd.MessageType[0]; got != want {
   311  			t.Errorf("reg.lookupMsg(%q, %q).DescriptorProto = %#v; want %#v", ".nested.nested2.mypackage", name, got, want)
   312  		}
   313  	}
   314  
   315  	for _, loc := range []string{
   316  		".nested.nested2.mypackage",
   317  		"nested.nested2.mypackage",
   318  		".nested.nested2",
   319  		"nested.nested2",
   320  		".nested",
   321  		"nested",
   322  		".",
   323  		"",
   324  		"somewhere.else",
   325  	} {
   326  		name := "nested.nested2.mypackage.ExampleMessage"
   327  		msg, err := reg.LookupMsg(loc, name)
   328  		if err != nil {
   329  			t.Errorf("reg.LookupMsg(%q, %q)) failed with %v; want success", loc, name, err)
   330  			return
   331  		}
   332  		if got, want := msg.DescriptorProto, fd.MessageType[0]; got != want {
   333  			t.Errorf("reg.lookupMsg(%q, %q).DescriptorProto = %#v; want %#v", loc, name, got, want)
   334  		}
   335  	}
   336  
   337  	for _, loc := range []string{
   338  		".nested.nested2.mypackage",
   339  		"nested.nested2.mypackage",
   340  		".nested.nested2",
   341  		"nested.nested2",
   342  		".nested",
   343  		"nested",
   344  	} {
   345  		name := "nested2.mypackage.ExampleMessage"
   346  		msg, err := reg.LookupMsg(loc, name)
   347  		if err != nil {
   348  			t.Errorf("reg.LookupMsg(%q, %q)) failed with %v; want success", loc, name, err)
   349  			return
   350  		}
   351  		if got, want := msg.DescriptorProto, fd.MessageType[0]; got != want {
   352  			t.Errorf("reg.lookupMsg(%q, %q).DescriptorProto = %#v; want %#v", loc, name, got, want)
   353  		}
   354  	}
   355  }
   356  
   357  func TestLoadWithInconsistentTargetPackage(t *testing.T) {
   358  	for _, spec := range []struct {
   359  		req        string
   360  		consistent bool
   361  	}{
   362  		// root package, no explicit go package
   363  		{
   364  			req: `
   365  				file_to_generate: 'a.proto'
   366  				file_to_generate: 'b.proto'
   367  				proto_file <
   368  					name: 'a.proto'
   369  					message_type < name: 'A' >
   370  					service <
   371  						name: "AService"
   372  						method <
   373  							name: "Meth"
   374  							input_type: "A"
   375  							output_type: "A"
   376  							options <
   377  								[google.api.http] < post: "/v1/a" body: "*" >
   378  							>
   379  						>
   380  					>
   381  				>
   382  				proto_file <
   383  					name: 'b.proto'
   384  					message_type < name: 'B' >
   385  					service <
   386  						name: "BService"
   387  						method <
   388  							name: "Meth"
   389  							input_type: "B"
   390  							output_type: "B"
   391  							options <
   392  								[google.api.http] < post: "/v1/b" body: "*" >
   393  							>
   394  						>
   395  					>
   396  				>
   397  			`,
   398  			consistent: false,
   399  		},
   400  		// named package, no explicit go package
   401  		{
   402  			req: `
   403  				file_to_generate: 'a.proto'
   404  				file_to_generate: 'b.proto'
   405  				proto_file <
   406  					name: 'a.proto'
   407  					package: 'example.foo'
   408  					message_type < name: 'A' >
   409  					service <
   410  						name: "AService"
   411  						method <
   412  							name: "Meth"
   413  							input_type: "A"
   414  							output_type: "A"
   415  							options <
   416  								[google.api.http] < post: "/v1/a" body: "*" >
   417  							>
   418  						>
   419  					>
   420  				>
   421  				proto_file <
   422  					name: 'b.proto'
   423  					package: 'example.foo'
   424  					message_type < name: 'B' >
   425  					service <
   426  						name: "BService"
   427  						method <
   428  							name: "Meth"
   429  							input_type: "B"
   430  							output_type: "B"
   431  							options <
   432  								[google.api.http] < post: "/v1/b" body: "*" >
   433  							>
   434  						>
   435  					>
   436  				>
   437  			`,
   438  			consistent: true,
   439  		},
   440  		// root package, explicit go package
   441  		{
   442  			req: `
   443  				file_to_generate: 'a.proto'
   444  				file_to_generate: 'b.proto'
   445  				proto_file <
   446  					name: 'a.proto'
   447  					options < go_package: 'foo' >
   448  					message_type < name: 'A' >
   449  					service <
   450  						name: "AService"
   451  						method <
   452  							name: "Meth"
   453  							input_type: "A"
   454  							output_type: "A"
   455  							options <
   456  								[google.api.http] < post: "/v1/a" body: "*" >
   457  							>
   458  						>
   459  					>
   460  				>
   461  				proto_file <
   462  					name: 'b.proto'
   463  					options < go_package: 'foo' >
   464  					message_type < name: 'B' >
   465  					service <
   466  						name: "BService"
   467  						method <
   468  							name: "Meth"
   469  							input_type: "B"
   470  							output_type: "B"
   471  							options <
   472  								[google.api.http] < post: "/v1/b" body: "*" >
   473  							>
   474  						>
   475  					>
   476  				>
   477  			`,
   478  			consistent: true,
   479  		},
   480  		// named package, explicit go package
   481  		{
   482  			req: `
   483  				file_to_generate: 'a.proto'
   484  				file_to_generate: 'b.proto'
   485  				proto_file <
   486  					name: 'a.proto'
   487  					package: 'example.foo'
   488  					options < go_package: 'foo' >
   489  					message_type < name: 'A' >
   490  					service <
   491  						name: "AService"
   492  						method <
   493  							name: "Meth"
   494  							input_type: "A"
   495  							output_type: "A"
   496  							options <
   497  								[google.api.http] < post: "/v1/a" body: "*" >
   498  							>
   499  						>
   500  					>
   501  				>
   502  				proto_file <
   503  					name: 'b.proto'
   504  					package: 'example.foo'
   505  					options < go_package: 'foo' >
   506  					message_type < name: 'B' >
   507  					service <
   508  						name: "BService"
   509  						method <
   510  							name: "Meth"
   511  							input_type: "B"
   512  							output_type: "B"
   513  							options <
   514  								[google.api.http] < post: "/v1/b" body: "*" >
   515  							>
   516  						>
   517  					>
   518  				>
   519  			`,
   520  			consistent: true,
   521  		},
   522  	} {
   523  		reg := NewRegistry()
   524  		err := load(t, reg, spec.req)
   525  		if got, want := err == nil, spec.consistent; got != want {
   526  			if want {
   527  				t.Errorf("reg.Load(%s) failed with %v; want success", spec.req, err)
   528  				continue
   529  			}
   530  			t.Errorf("reg.Load(%s) succeeded; want an package inconsistency error", spec.req)
   531  		}
   532  	}
   533  }
   534  
   535  func TestLoadOverridedPackageName(t *testing.T) {
   536  	reg := NewRegistry()
   537  	loadFile(t, reg, `
   538  		name: 'example.proto'
   539  		package: 'example'
   540  		options < go_package: 'example.com/xyz;pb' >
   541  	`)
   542  	file := reg.files["example.proto"]
   543  	if file == nil {
   544  		t.Errorf("reg.files[%q] = nil; want non-nil", "example.proto")
   545  		return
   546  	}
   547  	wantPkg := GoPackage{Path: "example.com/xyz", Name: "pb"}
   548  	if got, want := file.GoPkg, wantPkg; got != want {
   549  		t.Errorf("file.GoPkg = %#v; want %#v", got, want)
   550  	}
   551  }
   552  
   553  func TestLoadSetInputPath(t *testing.T) {
   554  	reg := NewRegistry()
   555  	reg.SetImportPath("foo/examplepb")
   556  	loadFile(t, reg, `
   557  		name: 'example.proto'
   558  		package: 'example'
   559  	`)
   560  	file := reg.files["example.proto"]
   561  	if file == nil {
   562  		t.Errorf("reg.files[%q] = nil; want non-nil", "example.proto")
   563  		return
   564  	}
   565  	wantPkg := GoPackage{Path: ".", Name: "examplepb"}
   566  	if got, want := file.GoPkg, wantPkg; got != want {
   567  		t.Errorf("file.GoPkg = %#v; want %#v", got, want)
   568  	}
   569  }
   570  
   571  func TestLoadGoPackageInputPath(t *testing.T) {
   572  	reg := NewRegistry()
   573  	reg.SetImportPath("examplepb")
   574  	loadFile(t, reg, `
   575  		name: 'example.proto'
   576  		package: 'example'
   577  		options < go_package: 'example.com/xyz;pb' >
   578  	`)
   579  	file := reg.files["example.proto"]
   580  	if file == nil {
   581  		t.Errorf("reg.files[%q] = nil; want non-nil", "example.proto")
   582  		return
   583  	}
   584  	wantPkg := GoPackage{Path: "example.com/xyz", Name: "pb"}
   585  	if got, want := file.GoPkg, wantPkg; got != want {
   586  		t.Errorf("file.GoPkg = %#v; want %#v", got, want)
   587  	}
   588  }
   589  
   590  func TestUnboundExternalHTTPRules(t *testing.T) {
   591  	reg := NewRegistry()
   592  	methodName := ".example.ExampleService.Echo"
   593  	reg.AddExternalHTTPRule(methodName, nil)
   594  	assertStringSlice(t, "unbound external HTTP rules", reg.UnboundExternalHTTPRules(), []string{methodName})
   595  	loadFile(t, reg, `
   596  		name: "path/to/example.proto",
   597  		package: "example"
   598  		message_type <
   599  			name: "StringMessage"
   600  			field <
   601  				name: "string"
   602  				number: 1
   603  				label: LABEL_OPTIONAL
   604  				type: TYPE_STRING
   605  			>
   606  		>
   607  		service <
   608  			name: "ExampleService"
   609  			method <
   610  				name: "Echo"
   611  				input_type: "StringMessage"
   612  				output_type: "StringMessage"
   613  			>
   614  		>
   615  	`)
   616  	assertStringSlice(t, "unbound external HTTP rules", reg.UnboundExternalHTTPRules(), []string{})
   617  }
   618  
   619  func assertStringSlice(t *testing.T, message string, got, want []string) {
   620  	if len(got) != len(want) {
   621  		t.Errorf("%s = %#v len(%d); want %#v len(%d)", message, got, len(got), want, len(want))
   622  	}
   623  	for i := range want {
   624  		if got[i] != want[i] {
   625  			t.Errorf("%s[%d] = %#v; want %#v", message, i, got[i], want[i])
   626  		}
   627  	}
   628  }
   629  

View as plain text