789 lines
23 KiB
Go
789 lines
23 KiB
Go
package genswagger
|
|
|
|
import (
|
|
"encoding/json"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
protodescriptor "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
|
plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
|
|
"github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/descriptor"
|
|
"github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule"
|
|
)
|
|
|
|
func crossLinkFixture(f *descriptor.File) *descriptor.File {
|
|
for _, m := range f.Messages {
|
|
m.File = f
|
|
}
|
|
for _, svc := range f.Services {
|
|
svc.File = f
|
|
for _, m := range svc.Methods {
|
|
m.Service = svc
|
|
for _, b := range m.Bindings {
|
|
b.Method = m
|
|
for _, param := range b.PathParams {
|
|
param.Method = m
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return f
|
|
}
|
|
|
|
func TestMessageToQueryParameters(t *testing.T) {
|
|
type test struct {
|
|
MsgDescs []*protodescriptor.DescriptorProto
|
|
Message string
|
|
Params []swaggerParameterObject
|
|
}
|
|
|
|
tests := []test{
|
|
{
|
|
MsgDescs: []*protodescriptor.DescriptorProto{
|
|
&protodescriptor.DescriptorProto{
|
|
Name: proto.String("ExampleMessage"),
|
|
Field: []*protodescriptor.FieldDescriptorProto{
|
|
{
|
|
Name: proto.String("a"),
|
|
Type: protodescriptor.FieldDescriptorProto_TYPE_STRING.Enum(),
|
|
Number: proto.Int32(1),
|
|
},
|
|
{
|
|
Name: proto.String("b"),
|
|
Type: protodescriptor.FieldDescriptorProto_TYPE_DOUBLE.Enum(),
|
|
Number: proto.Int32(2),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Message: "ExampleMessage",
|
|
Params: []swaggerParameterObject{
|
|
swaggerParameterObject{
|
|
Name: "a",
|
|
In: "query",
|
|
Required: false,
|
|
Type: "string",
|
|
},
|
|
swaggerParameterObject{
|
|
Name: "b",
|
|
In: "query",
|
|
Required: false,
|
|
Type: "number",
|
|
Format: "double",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
MsgDescs: []*protodescriptor.DescriptorProto{
|
|
&protodescriptor.DescriptorProto{
|
|
Name: proto.String("ExampleMessage"),
|
|
Field: []*protodescriptor.FieldDescriptorProto{
|
|
{
|
|
Name: proto.String("nested"),
|
|
Type: protodescriptor.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
|
|
TypeName: proto.String(".example.Nested"),
|
|
Number: proto.Int32(1),
|
|
},
|
|
},
|
|
},
|
|
&protodescriptor.DescriptorProto{
|
|
Name: proto.String("Nested"),
|
|
Field: []*protodescriptor.FieldDescriptorProto{
|
|
{
|
|
Name: proto.String("a"),
|
|
Type: protodescriptor.FieldDescriptorProto_TYPE_STRING.Enum(),
|
|
Number: proto.Int32(1),
|
|
},
|
|
{
|
|
Name: proto.String("deep"),
|
|
Type: protodescriptor.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
|
|
TypeName: proto.String(".example.Nested.DeepNested"),
|
|
Number: proto.Int32(2),
|
|
},
|
|
},
|
|
NestedType: []*protodescriptor.DescriptorProto{{
|
|
Name: proto.String("DeepNested"),
|
|
Field: []*protodescriptor.FieldDescriptorProto{
|
|
{
|
|
Name: proto.String("b"),
|
|
Type: protodescriptor.FieldDescriptorProto_TYPE_STRING.Enum(),
|
|
Number: proto.Int32(1),
|
|
},
|
|
{
|
|
Name: proto.String("c"),
|
|
Type: protodescriptor.FieldDescriptorProto_TYPE_ENUM.Enum(),
|
|
TypeName: proto.String(".example.Nested.DeepNested.DeepEnum"),
|
|
Number: proto.Int32(2),
|
|
},
|
|
},
|
|
EnumType: []*protodescriptor.EnumDescriptorProto{
|
|
{
|
|
Name: proto.String("DeepEnum"),
|
|
Value: []*protodescriptor.EnumValueDescriptorProto{
|
|
{Name: proto.String("FALSE"), Number: proto.Int32(0)},
|
|
{Name: proto.String("TRUE"), Number: proto.Int32(1)},
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
},
|
|
Message: "ExampleMessage",
|
|
Params: []swaggerParameterObject{
|
|
swaggerParameterObject{
|
|
Name: "nested.a",
|
|
In: "query",
|
|
Required: false,
|
|
Type: "string",
|
|
},
|
|
swaggerParameterObject{
|
|
Name: "nested.deep.b",
|
|
In: "query",
|
|
Required: false,
|
|
Type: "string",
|
|
},
|
|
swaggerParameterObject{
|
|
Name: "nested.deep.c",
|
|
In: "query",
|
|
Required: false,
|
|
Type: "string",
|
|
Enum: []string{"FALSE", "TRUE"},
|
|
Default: "FALSE",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
reg := descriptor.NewRegistry()
|
|
msgs := []*descriptor.Message{}
|
|
for _, msgdesc := range test.MsgDescs {
|
|
msgs = append(msgs, &descriptor.Message{DescriptorProto: msgdesc})
|
|
}
|
|
file := descriptor.File{
|
|
FileDescriptorProto: &protodescriptor.FileDescriptorProto{
|
|
SourceCodeInfo: &protodescriptor.SourceCodeInfo{},
|
|
Name: proto.String("example.proto"),
|
|
Package: proto.String("example"),
|
|
Dependency: []string{},
|
|
MessageType: test.MsgDescs,
|
|
Service: []*protodescriptor.ServiceDescriptorProto{},
|
|
},
|
|
GoPkg: descriptor.GoPackage{
|
|
Path: "example.com/path/to/example/example.pb",
|
|
Name: "example_pb",
|
|
},
|
|
Messages: msgs,
|
|
}
|
|
reg.Load(&plugin.CodeGeneratorRequest{
|
|
ProtoFile: []*protodescriptor.FileDescriptorProto{file.FileDescriptorProto},
|
|
})
|
|
|
|
message, err := reg.LookupMsg("", ".example."+test.Message)
|
|
if err != nil {
|
|
t.Fatalf("failed to lookup message: %s", err)
|
|
}
|
|
params, err := messageToQueryParameters(message, reg, []descriptor.Parameter{})
|
|
if err != nil {
|
|
t.Fatalf("failed to convert message to query parameters: %s", err)
|
|
}
|
|
if !reflect.DeepEqual(params, test.Params) {
|
|
t.Errorf("expected %v, got %v", test.Params, params)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestApplyTemplateSimple(t *testing.T) {
|
|
msgdesc := &protodescriptor.DescriptorProto{
|
|
Name: proto.String("ExampleMessage"),
|
|
}
|
|
meth := &protodescriptor.MethodDescriptorProto{
|
|
Name: proto.String("Example"),
|
|
InputType: proto.String("ExampleMessage"),
|
|
OutputType: proto.String("ExampleMessage"),
|
|
}
|
|
svc := &protodescriptor.ServiceDescriptorProto{
|
|
Name: proto.String("ExampleService"),
|
|
Method: []*protodescriptor.MethodDescriptorProto{meth},
|
|
}
|
|
msg := &descriptor.Message{
|
|
DescriptorProto: msgdesc,
|
|
}
|
|
file := descriptor.File{
|
|
FileDescriptorProto: &protodescriptor.FileDescriptorProto{
|
|
SourceCodeInfo: &protodescriptor.SourceCodeInfo{},
|
|
Name: proto.String("example.proto"),
|
|
Package: proto.String("example"),
|
|
Dependency: []string{"a.example/b/c.proto", "a.example/d/e.proto"},
|
|
MessageType: []*protodescriptor.DescriptorProto{msgdesc},
|
|
Service: []*protodescriptor.ServiceDescriptorProto{svc},
|
|
},
|
|
GoPkg: descriptor.GoPackage{
|
|
Path: "example.com/path/to/example/example.pb",
|
|
Name: "example_pb",
|
|
},
|
|
Messages: []*descriptor.Message{msg},
|
|
Services: []*descriptor.Service{
|
|
{
|
|
ServiceDescriptorProto: svc,
|
|
Methods: []*descriptor.Method{
|
|
{
|
|
MethodDescriptorProto: meth,
|
|
RequestType: msg,
|
|
ResponseType: msg,
|
|
Bindings: []*descriptor.Binding{
|
|
{
|
|
HTTPMethod: "GET",
|
|
Body: &descriptor.Body{FieldPath: nil},
|
|
PathTmpl: httprule.Template{
|
|
Version: 1,
|
|
OpCodes: []int{0, 0},
|
|
Template: "/v1/echo", // TODO(achew22): Figure out what this should really be
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
result, err := applyTemplate(param{File: crossLinkFixture(&file), reg: descriptor.NewRegistry()})
|
|
if err != nil {
|
|
t.Errorf("applyTemplate(%#v) failed with %v; want success", file, err)
|
|
return
|
|
}
|
|
got := new(swaggerObject)
|
|
err = json.Unmarshal([]byte(result), got)
|
|
if err != nil {
|
|
t.Errorf("json.Unmarshal(%s) failed with %v; want success", result, err)
|
|
return
|
|
}
|
|
if want, is, name := "2.0", got.Swagger, "Swagger"; !reflect.DeepEqual(is, want) {
|
|
t.Errorf("applyTemplate(%#v).%s = %s want to be %s", file, name, is, want)
|
|
}
|
|
if want, is, name := "", got.BasePath, "BasePath"; !reflect.DeepEqual(is, want) {
|
|
t.Errorf("applyTemplate(%#v).%s = %s want to be %s", file, name, is, want)
|
|
}
|
|
if want, is, name := []string{"http", "https"}, got.Schemes, "Schemes"; !reflect.DeepEqual(is, want) {
|
|
t.Errorf("applyTemplate(%#v).%s = %s want to be %s", file, name, is, want)
|
|
}
|
|
if want, is, name := []string{"application/json"}, got.Consumes, "Consumes"; !reflect.DeepEqual(is, want) {
|
|
t.Errorf("applyTemplate(%#v).%s = %s want to be %s", file, name, is, want)
|
|
}
|
|
if want, is, name := []string{"application/json"}, got.Produces, "Produces"; !reflect.DeepEqual(is, want) {
|
|
t.Errorf("applyTemplate(%#v).%s = %s want to be %s", file, name, is, want)
|
|
}
|
|
|
|
// If there was a failure, print out the input and the json result for debugging.
|
|
if t.Failed() {
|
|
t.Errorf("had: %s", file)
|
|
t.Errorf("got: %s", result)
|
|
}
|
|
}
|
|
|
|
func TestApplyTemplateRequestWithoutClientStreaming(t *testing.T) {
|
|
t.Skip()
|
|
msgdesc := &protodescriptor.DescriptorProto{
|
|
Name: proto.String("ExampleMessage"),
|
|
Field: []*protodescriptor.FieldDescriptorProto{
|
|
{
|
|
Name: proto.String("nested"),
|
|
Label: protodescriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
|
|
Type: protodescriptor.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
|
|
TypeName: proto.String("NestedMessage"),
|
|
Number: proto.Int32(1),
|
|
},
|
|
},
|
|
}
|
|
nesteddesc := &protodescriptor.DescriptorProto{
|
|
Name: proto.String("NestedMessage"),
|
|
Field: []*protodescriptor.FieldDescriptorProto{
|
|
{
|
|
Name: proto.String("int32"),
|
|
Label: protodescriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
|
|
Type: protodescriptor.FieldDescriptorProto_TYPE_INT32.Enum(),
|
|
Number: proto.Int32(1),
|
|
},
|
|
{
|
|
Name: proto.String("bool"),
|
|
Label: protodescriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
|
|
Type: protodescriptor.FieldDescriptorProto_TYPE_BOOL.Enum(),
|
|
Number: proto.Int32(2),
|
|
},
|
|
},
|
|
}
|
|
meth := &protodescriptor.MethodDescriptorProto{
|
|
Name: proto.String("Echo"),
|
|
InputType: proto.String("ExampleMessage"),
|
|
OutputType: proto.String("ExampleMessage"),
|
|
ClientStreaming: proto.Bool(false),
|
|
}
|
|
svc := &protodescriptor.ServiceDescriptorProto{
|
|
Name: proto.String("ExampleService"),
|
|
Method: []*protodescriptor.MethodDescriptorProto{meth},
|
|
}
|
|
|
|
meth.ServerStreaming = proto.Bool(false)
|
|
|
|
msg := &descriptor.Message{
|
|
DescriptorProto: msgdesc,
|
|
}
|
|
nested := &descriptor.Message{
|
|
DescriptorProto: nesteddesc,
|
|
}
|
|
|
|
nestedField := &descriptor.Field{
|
|
Message: msg,
|
|
FieldDescriptorProto: msg.GetField()[0],
|
|
}
|
|
intField := &descriptor.Field{
|
|
Message: nested,
|
|
FieldDescriptorProto: nested.GetField()[0],
|
|
}
|
|
boolField := &descriptor.Field{
|
|
Message: nested,
|
|
FieldDescriptorProto: nested.GetField()[1],
|
|
}
|
|
file := descriptor.File{
|
|
FileDescriptorProto: &protodescriptor.FileDescriptorProto{
|
|
SourceCodeInfo: &protodescriptor.SourceCodeInfo{},
|
|
Name: proto.String("example.proto"),
|
|
Package: proto.String("example"),
|
|
MessageType: []*protodescriptor.DescriptorProto{msgdesc, nesteddesc},
|
|
Service: []*protodescriptor.ServiceDescriptorProto{svc},
|
|
},
|
|
GoPkg: descriptor.GoPackage{
|
|
Path: "example.com/path/to/example/example.pb",
|
|
Name: "example_pb",
|
|
},
|
|
Messages: []*descriptor.Message{msg, nested},
|
|
Services: []*descriptor.Service{
|
|
{
|
|
ServiceDescriptorProto: svc,
|
|
Methods: []*descriptor.Method{
|
|
{
|
|
MethodDescriptorProto: meth,
|
|
RequestType: msg,
|
|
ResponseType: msg,
|
|
Bindings: []*descriptor.Binding{
|
|
{
|
|
HTTPMethod: "POST",
|
|
PathTmpl: httprule.Template{
|
|
Version: 1,
|
|
OpCodes: []int{0, 0},
|
|
Template: "/v1/echo", // TODO(achew): Figure out what this hsould really be
|
|
},
|
|
PathParams: []descriptor.Parameter{
|
|
{
|
|
FieldPath: descriptor.FieldPath([]descriptor.FieldPathComponent{
|
|
{
|
|
Name: "nested",
|
|
Target: nestedField,
|
|
},
|
|
{
|
|
Name: "int32",
|
|
Target: intField,
|
|
},
|
|
}),
|
|
Target: intField,
|
|
},
|
|
},
|
|
Body: &descriptor.Body{
|
|
FieldPath: descriptor.FieldPath([]descriptor.FieldPathComponent{
|
|
{
|
|
Name: "nested",
|
|
Target: nestedField,
|
|
},
|
|
{
|
|
Name: "bool",
|
|
Target: boolField,
|
|
},
|
|
}),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
result, err := applyTemplate(param{File: crossLinkFixture(&file)})
|
|
if err != nil {
|
|
t.Errorf("applyTemplate(%#v) failed with %v; want success", file, err)
|
|
return
|
|
}
|
|
var obj swaggerObject
|
|
err = json.Unmarshal([]byte(result), &obj)
|
|
if err != nil {
|
|
t.Errorf("applyTemplate(%#v) failed with %v; want success", file, err)
|
|
return
|
|
}
|
|
if want, got := "2.0", obj.Swagger; !reflect.DeepEqual(got, want) {
|
|
t.Errorf("applyTemplate(%#v).Swagger = %s want to be %s", file, got, want)
|
|
}
|
|
if want, got := "", obj.BasePath; !reflect.DeepEqual(got, want) {
|
|
t.Errorf("applyTemplate(%#v).BasePath = %s want to be %s", file, got, want)
|
|
}
|
|
if want, got := []string{"http", "https"}, obj.Schemes; !reflect.DeepEqual(got, want) {
|
|
t.Errorf("applyTemplate(%#v).Schemes = %s want to be %s", file, got, want)
|
|
}
|
|
if want, got := []string{"application/json"}, obj.Consumes; !reflect.DeepEqual(got, want) {
|
|
t.Errorf("applyTemplate(%#v).Consumes = %s want to be %s", file, got, want)
|
|
}
|
|
if want, got := []string{"application/json"}, obj.Produces; !reflect.DeepEqual(got, want) {
|
|
t.Errorf("applyTemplate(%#v).Produces = %s want to be %s", file, got, want)
|
|
}
|
|
if want, got, name := "Generated for ExampleService.Echo - ", obj.Paths["/v1/echo"].Post.Summary, "Paths[/v1/echo].Post.Summary"; !reflect.DeepEqual(got, want) {
|
|
t.Errorf("applyTemplate(%#v).%s = %s want to be %s", file, name, got, want)
|
|
}
|
|
|
|
// If there was a failure, print out the input and the json result for debugging.
|
|
if t.Failed() {
|
|
t.Errorf("had: %s", file)
|
|
t.Errorf("got: %s", result)
|
|
}
|
|
}
|
|
|
|
func TestApplyTemplateRequestWithClientStreaming(t *testing.T) {
|
|
t.Skip()
|
|
msgdesc := &protodescriptor.DescriptorProto{
|
|
Name: proto.String("ExampleMessage"),
|
|
Field: []*protodescriptor.FieldDescriptorProto{
|
|
{
|
|
Name: proto.String("nested"),
|
|
Label: protodescriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
|
|
Type: protodescriptor.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
|
|
TypeName: proto.String("NestedMessage"),
|
|
Number: proto.Int32(1),
|
|
},
|
|
},
|
|
}
|
|
nesteddesc := &protodescriptor.DescriptorProto{
|
|
Name: proto.String("NestedMessage"),
|
|
Field: []*protodescriptor.FieldDescriptorProto{
|
|
{
|
|
Name: proto.String("int32"),
|
|
Label: protodescriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
|
|
Type: protodescriptor.FieldDescriptorProto_TYPE_INT32.Enum(),
|
|
Number: proto.Int32(1),
|
|
},
|
|
{
|
|
Name: proto.String("bool"),
|
|
Label: protodescriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
|
|
Type: protodescriptor.FieldDescriptorProto_TYPE_BOOL.Enum(),
|
|
Number: proto.Int32(2),
|
|
},
|
|
},
|
|
}
|
|
meth := &protodescriptor.MethodDescriptorProto{
|
|
Name: proto.String("Echo"),
|
|
InputType: proto.String("ExampleMessage"),
|
|
OutputType: proto.String("ExampleMessage"),
|
|
ClientStreaming: proto.Bool(true),
|
|
ServerStreaming: proto.Bool(true),
|
|
}
|
|
svc := &protodescriptor.ServiceDescriptorProto{
|
|
Name: proto.String("ExampleService"),
|
|
Method: []*protodescriptor.MethodDescriptorProto{meth},
|
|
}
|
|
|
|
msg := &descriptor.Message{
|
|
DescriptorProto: msgdesc,
|
|
}
|
|
nested := &descriptor.Message{
|
|
DescriptorProto: nesteddesc,
|
|
}
|
|
|
|
nestedField := &descriptor.Field{
|
|
Message: msg,
|
|
FieldDescriptorProto: msg.GetField()[0],
|
|
}
|
|
intField := &descriptor.Field{
|
|
Message: nested,
|
|
FieldDescriptorProto: nested.GetField()[0],
|
|
}
|
|
boolField := &descriptor.Field{
|
|
Message: nested,
|
|
FieldDescriptorProto: nested.GetField()[1],
|
|
}
|
|
file := descriptor.File{
|
|
FileDescriptorProto: &protodescriptor.FileDescriptorProto{
|
|
SourceCodeInfo: &protodescriptor.SourceCodeInfo{},
|
|
Name: proto.String("example.proto"),
|
|
Package: proto.String("example"),
|
|
MessageType: []*protodescriptor.DescriptorProto{msgdesc, nesteddesc},
|
|
Service: []*protodescriptor.ServiceDescriptorProto{svc},
|
|
},
|
|
GoPkg: descriptor.GoPackage{
|
|
Path: "example.com/path/to/example/example.pb",
|
|
Name: "example_pb",
|
|
},
|
|
Messages: []*descriptor.Message{msg, nested},
|
|
Services: []*descriptor.Service{
|
|
{
|
|
ServiceDescriptorProto: svc,
|
|
Methods: []*descriptor.Method{
|
|
{
|
|
MethodDescriptorProto: meth,
|
|
RequestType: msg,
|
|
ResponseType: msg,
|
|
Bindings: []*descriptor.Binding{
|
|
{
|
|
HTTPMethod: "POST",
|
|
PathTmpl: httprule.Template{
|
|
Version: 1,
|
|
OpCodes: []int{0, 0},
|
|
Template: "/v1/echo", // TODO(achew): Figure out what this hsould really be
|
|
},
|
|
PathParams: []descriptor.Parameter{
|
|
{
|
|
FieldPath: descriptor.FieldPath([]descriptor.FieldPathComponent{
|
|
{
|
|
Name: "nested",
|
|
Target: nestedField,
|
|
},
|
|
{
|
|
Name: "int32",
|
|
Target: intField,
|
|
},
|
|
}),
|
|
Target: intField,
|
|
},
|
|
},
|
|
Body: &descriptor.Body{
|
|
FieldPath: descriptor.FieldPath([]descriptor.FieldPathComponent{
|
|
{
|
|
Name: "nested",
|
|
Target: nestedField,
|
|
},
|
|
{
|
|
Name: "bool",
|
|
Target: boolField,
|
|
},
|
|
}),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
_, err := applyTemplate(param{File: crossLinkFixture(&file)})
|
|
if err == nil {
|
|
t.Errorf("applyTemplate(%#v) should have failed cause swagger doesn't support streaming", file)
|
|
return
|
|
}
|
|
}
|
|
|
|
func TestApplyTemplateRequestWithUnusedReferences(t *testing.T) {
|
|
reqdesc := &protodescriptor.DescriptorProto{
|
|
Name: proto.String("ExampleMessage"),
|
|
Field: []*protodescriptor.FieldDescriptorProto{
|
|
{
|
|
Name: proto.String("string"),
|
|
Label: protodescriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
|
|
Type: protodescriptor.FieldDescriptorProto_TYPE_STRING.Enum(),
|
|
Number: proto.Int32(1),
|
|
},
|
|
},
|
|
}
|
|
respdesc := &protodescriptor.DescriptorProto{
|
|
Name: proto.String("EmptyMessage"),
|
|
}
|
|
meth := &protodescriptor.MethodDescriptorProto{
|
|
Name: proto.String("Example"),
|
|
InputType: proto.String("ExampleMessage"),
|
|
OutputType: proto.String("EmptyMessage"),
|
|
ClientStreaming: proto.Bool(false),
|
|
ServerStreaming: proto.Bool(false),
|
|
}
|
|
svc := &protodescriptor.ServiceDescriptorProto{
|
|
Name: proto.String("ExampleService"),
|
|
Method: []*protodescriptor.MethodDescriptorProto{meth},
|
|
}
|
|
|
|
req := &descriptor.Message{
|
|
DescriptorProto: reqdesc,
|
|
}
|
|
resp := &descriptor.Message{
|
|
DescriptorProto: respdesc,
|
|
}
|
|
stringField := &descriptor.Field{
|
|
Message: req,
|
|
FieldDescriptorProto: req.GetField()[0],
|
|
}
|
|
file := descriptor.File{
|
|
FileDescriptorProto: &protodescriptor.FileDescriptorProto{
|
|
SourceCodeInfo: &protodescriptor.SourceCodeInfo{},
|
|
Name: proto.String("example.proto"),
|
|
Package: proto.String("example"),
|
|
MessageType: []*protodescriptor.DescriptorProto{reqdesc, respdesc},
|
|
Service: []*protodescriptor.ServiceDescriptorProto{svc},
|
|
},
|
|
GoPkg: descriptor.GoPackage{
|
|
Path: "example.com/path/to/example/example.pb",
|
|
Name: "example_pb",
|
|
},
|
|
Messages: []*descriptor.Message{req, resp},
|
|
Services: []*descriptor.Service{
|
|
{
|
|
ServiceDescriptorProto: svc,
|
|
Methods: []*descriptor.Method{
|
|
{
|
|
MethodDescriptorProto: meth,
|
|
RequestType: req,
|
|
ResponseType: resp,
|
|
Bindings: []*descriptor.Binding{
|
|
{
|
|
HTTPMethod: "GET",
|
|
PathTmpl: httprule.Template{
|
|
Version: 1,
|
|
OpCodes: []int{0, 0},
|
|
Template: "/v1/example",
|
|
},
|
|
},
|
|
{
|
|
HTTPMethod: "POST",
|
|
PathTmpl: httprule.Template{
|
|
Version: 1,
|
|
OpCodes: []int{0, 0},
|
|
Template: "/v1/example/{string}",
|
|
},
|
|
PathParams: []descriptor.Parameter{
|
|
{
|
|
FieldPath: descriptor.FieldPath([]descriptor.FieldPathComponent{
|
|
{
|
|
Name: "string",
|
|
Target: stringField,
|
|
},
|
|
}),
|
|
Target: stringField,
|
|
},
|
|
},
|
|
Body: &descriptor.Body{
|
|
FieldPath: descriptor.FieldPath([]descriptor.FieldPathComponent{
|
|
{
|
|
Name: "string",
|
|
Target: stringField,
|
|
},
|
|
}),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
reg := descriptor.NewRegistry()
|
|
reg.Load(&plugin.CodeGeneratorRequest{ProtoFile: []*protodescriptor.FileDescriptorProto{file.FileDescriptorProto}})
|
|
result, err := applyTemplate(param{File: crossLinkFixture(&file), reg: reg})
|
|
if err != nil {
|
|
t.Errorf("applyTemplate(%#v) failed with %v; want success", file, err)
|
|
return
|
|
}
|
|
var obj swaggerObject
|
|
err = json.Unmarshal([]byte(result), &obj)
|
|
if err != nil {
|
|
t.Errorf("applyTemplate(%#v) failed with %v; want success", file, err)
|
|
return
|
|
}
|
|
|
|
// Only EmptyMessage must be present, not ExampleMessage
|
|
if want, got, name := 1, len(obj.Definitions), "len(Definitions)"; !reflect.DeepEqual(got, want) {
|
|
t.Errorf("applyTemplate(%#v).%s = %d want to be %d", file, name, got, want)
|
|
}
|
|
|
|
// If there was a failure, print out the input and the json result for debugging.
|
|
if t.Failed() {
|
|
t.Errorf("had: %s", file)
|
|
t.Errorf("got: %s", result)
|
|
}
|
|
}
|
|
|
|
func TestTemplateToSwaggerPath(t *testing.T) {
|
|
var tests = []struct {
|
|
input string
|
|
expected string
|
|
}{
|
|
{"/test", "/test"},
|
|
{"/{test}", "/{test}"},
|
|
{"/{test=prefix/*}", "/{test}"},
|
|
{"/{test=prefix/that/has/multiple/parts/to/it/*}", "/{test}"},
|
|
{"/{test1}/{test2}", "/{test1}/{test2}"},
|
|
{"/{test1}/{test2}/", "/{test1}/{test2}/"},
|
|
}
|
|
|
|
for _, data := range tests {
|
|
actual := templateToSwaggerPath(data.input)
|
|
if data.expected != actual {
|
|
t.Errorf("Expected templateToSwaggerPath(%v) = %v, actual: %v", data.input, data.expected, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestResolveFullyQualifiedNameToSwaggerName(t *testing.T) {
|
|
var tests = []struct {
|
|
input string
|
|
output string
|
|
listOfFQMNs []string
|
|
}{
|
|
{
|
|
".a.b.C",
|
|
"C",
|
|
[]string{
|
|
".a.b.C",
|
|
},
|
|
},
|
|
{
|
|
".a.b.C",
|
|
"abC",
|
|
[]string{
|
|
".a.C",
|
|
".a.b.C",
|
|
},
|
|
},
|
|
{
|
|
".a.b.C",
|
|
"abC",
|
|
[]string{
|
|
".C",
|
|
".a.C",
|
|
".a.b.C",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, data := range tests {
|
|
output := resolveFullyQualifiedNameToSwaggerName(data.input, data.listOfFQMNs)
|
|
if output != data.output {
|
|
t.Errorf("Expected fullyQualifiedNameToSwaggerName(%v) to be %s but got %s",
|
|
data.input, data.output, output)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFQMNtoSwaggerName(t *testing.T) {
|
|
var tests = []struct {
|
|
input string
|
|
expected string
|
|
}{
|
|
{"/test", "/test"},
|
|
{"/{test}", "/{test}"},
|
|
{"/{test=prefix/*}", "/{test}"},
|
|
{"/{test=prefix/that/has/multiple/parts/to/it/*}", "/{test}"},
|
|
{"/{test1}/{test2}", "/{test1}/{test2}"},
|
|
{"/{test1}/{test2}/", "/{test1}/{test2}/"},
|
|
}
|
|
|
|
for _, data := range tests {
|
|
actual := templateToSwaggerPath(data.input)
|
|
if data.expected != actual {
|
|
t.Errorf("Expected templateToSwaggerPath(%v) = %v, actual: %v", data.input, data.expected, actual)
|
|
}
|
|
}
|
|
}
|