| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701 |
- // +build go1.8,codegen
- package api
- import (
- "reflect"
- "strconv"
- "strings"
- "testing"
- )
- func TestUniqueInputAndOutputs(t *testing.T) {
- const serviceName = "FooService"
- shamelist[serviceName] = map[string]persistAPIType{
- "OpOutputNoRename": {
- output: true,
- },
- "OpInputNoRename": {
- input: true,
- },
- "OpBothNoRename": {
- input: true,
- output: true,
- },
- }
- cases := [][]struct {
- expectedInput string
- expectedOutput string
- operation string
- input string
- output string
- }{
- {
- {
- expectedInput: "FooOperationInput",
- expectedOutput: "FooOperationOutput",
- operation: "FooOperation",
- input: "FooInputShape",
- output: "FooOutputShape",
- },
- {
- expectedInput: "BarOperationInput",
- expectedOutput: "BarOperationOutput",
- operation: "BarOperation",
- input: "FooInputShape",
- output: "FooOutputShape",
- },
- },
- {
- {
- expectedInput: "FooOperationInput",
- expectedOutput: "FooOperationOutput",
- operation: "FooOperation",
- input: "FooInputShape",
- output: "FooOutputShape",
- },
- {
- expectedInput: "OpOutputNoRenameInput",
- expectedOutput: "OpOutputNoRenameOutputShape",
- operation: "OpOutputNoRename",
- input: "OpOutputNoRenameInputShape",
- output: "OpOutputNoRenameOutputShape",
- },
- },
- {
- {
- expectedInput: "FooOperationInput",
- expectedOutput: "FooOperationOutput",
- operation: "FooOperation",
- input: "FooInputShape",
- output: "FooOutputShape",
- },
- {
- expectedInput: "OpInputNoRenameInputShape",
- expectedOutput: "OpInputNoRenameOutput",
- operation: "OpInputNoRename",
- input: "OpInputNoRenameInputShape",
- output: "OpInputNoRenameOutputShape",
- },
- },
- {
- {
- expectedInput: "FooOperationInput",
- expectedOutput: "FooOperationOutput",
- operation: "FooOperation",
- input: "FooInputShape",
- output: "FooOutputShape",
- },
- {
- expectedInput: "OpInputNoRenameInputShape",
- expectedOutput: "OpInputNoRenameOutputShape",
- operation: "OpBothNoRename",
- input: "OpInputNoRenameInputShape",
- output: "OpInputNoRenameOutputShape",
- },
- },
- }
- for i, c := range cases {
- t.Run(strconv.Itoa(i), func(t *testing.T) {
- a := &API{
- name: serviceName,
- Operations: map[string]*Operation{},
- Shapes: map[string]*Shape{},
- }
- expected := map[string][]string{}
- for _, op := range c {
- o := &Operation{
- Name: op.operation,
- ExportedName: op.operation,
- InputRef: ShapeRef{
- API: a,
- ShapeName: op.input,
- Shape: &Shape{
- API: a,
- ShapeName: op.input,
- },
- },
- OutputRef: ShapeRef{
- API: a,
- ShapeName: op.input,
- Shape: &Shape{
- API: a,
- ShapeName: op.input,
- },
- },
- }
- o.InputRef.Shape.refs = append(o.InputRef.Shape.refs, &o.InputRef)
- o.OutputRef.Shape.refs = append(o.OutputRef.Shape.refs, &o.OutputRef)
- a.Operations[o.Name] = o
- a.Shapes[op.input] = o.InputRef.Shape
- a.Shapes[op.output] = o.OutputRef.Shape
- expected[op.operation] = append(expected[op.operation],
- op.expectedInput,
- op.expectedOutput,
- )
- }
- a.fixStutterNames()
- a.applyShapeNameAliases()
- a.createInputOutputShapes()
- for k, v := range expected {
- if a.Operations[k].InputRef.Shape.ShapeName != v[0] {
- t.Errorf("Error %s case: Expected %q, but received %q", k, v[0], a.Operations[k].InputRef.Shape.ShapeName)
- }
- if a.Operations[k].OutputRef.Shape.ShapeName != v[1] {
- t.Errorf("Error %s case: Expected %q, but received %q", k, v[1], a.Operations[k].OutputRef.Shape.ShapeName)
- }
- }
- })
- }
- }
- func TestCollidingFields(t *testing.T) {
- cases := map[string]struct {
- MemberRefs map[string]*ShapeRef
- Expect []string
- IsException bool
- }{
- "SimpleMembers": {
- MemberRefs: map[string]*ShapeRef{
- "Code": {},
- "Foo": {},
- "GoString": {},
- "Message": {},
- "OrigErr": {},
- "SetFoo": {},
- "String": {},
- "Validate": {},
- },
- Expect: []string{
- "Code",
- "Foo",
- "GoString_",
- "Message",
- "OrigErr",
- "SetFoo_",
- "String_",
- "Validate_",
- },
- },
- "ExceptionShape": {
- IsException: true,
- MemberRefs: map[string]*ShapeRef{
- "Code": {},
- "Message": {},
- "OrigErr": {},
- "Other": {},
- "String": {},
- },
- Expect: []string{
- "Code_",
- "Message_",
- "OrigErr_",
- "Other",
- "String_",
- },
- },
- }
- for k, c := range cases {
- t.Run(k, func(t *testing.T) {
- a := &API{
- Shapes: map[string]*Shape{
- "shapename": {
- ShapeName: k,
- MemberRefs: c.MemberRefs,
- Exception: c.IsException,
- },
- },
- }
- a.renameCollidingFields()
- for i, name := range a.Shapes["shapename"].MemberNames() {
- if e, a := c.Expect[i], name; e != a {
- t.Errorf("expect %v, got %v", e, a)
- }
- }
- })
- }
- }
- func TestSupressHTTP2EventStreams(t *testing.T) {
- const baseModel = `
- {
- "version":"2.0",
- "metadata":{
- "apiVersion":"0000-00-00",
- "endpointPrefix":"rpcservice",
- "jsonVersion":"1.1",
- "protocol":"json",
- "protocolSettings":{"h2":"{h2Option}"},
- "serviceAbbreviation":"RPCService",
- "serviceFullName":"RPC Service",
- "serviceId":"RPCService",
- "signatureVersion":"v4",
- "targetPrefix":"RPCService_00000000",
- "uid":"RPCService-0000-00-00"
- },
- "operations":{
- "BarOp":{
- "name":"BarOp",
- "http":{
- "method":"POST",
- "requestUri":"/"
- },
- "input":{"shape": "BarOpRequest"},
- "output":{"shape":"BarOpResponse"}
- },
- "EventStreamOp":{
- "name":"EventStreamOp",
- "http":{
- "method":"POST",
- "requestUri":"/"
- },
- "input":{"shape": "EventStreamOpRequest"},
- "output":{"shape":"EventStreamOpResponse"}
- },
- "FooOp":{
- "name":"FooOp",
- "http":{
- "method":"POST",
- "requestUri":"/"
- },
- "input":{"shape": "FooOpRequest"},
- "output":{"shape":"FooOpResponse"}
- }
- },
- "shapes":{
- "BarOpRequest":{
- "type":"structure",
- "members":{}
- },
- "BarOpResponse":{
- "type":"structure",
- "members":{}
- },
- "EventStreamOpRequest":{
- "type":"structure",
- "members":{
- }
- },
- "EventStreamOpResponse":{
- "type":"structure",
- "members":{
- "EventStream":{"shape":"EventStream"}
- }
- },
- "FooOpRequest":{
- "type":"structure",
- "members":{}
- },
- "FooOpResponse":{
- "type":"structure",
- "members":{}
- },
- "EventStream":{
- "type":"structure",
- "members":{
- "Empty":{"shape":"EmptyEvent"}
- },
- "eventstream":true
- },
- "EmptyEvent": {
- "type":"structure",
- "members":{},
- "event": true
- }
- }
- }
- `
- cases := map[string]struct {
- Model string
- ExpectOps []string
- ExpectShapes []string
- }{
- "control": {
- Model: strings.Replace(baseModel, "{h2Option}", "", -1),
- ExpectOps: []string{"BarOp", "EventStreamOp", "FooOp"},
- ExpectShapes: []string{
- "BarOpInput", "BarOpOutput", "EmptyEvent",
- "EventStreamOpEventStream", "EventStreamOpInput",
- "EventStreamOpOutput", "FooOpInput", "FooOpOutput",
- },
- },
- "HTTP/2 with EventStreams": {
- Model: strings.Replace(baseModel, "{h2Option}", "eventstream", 1),
- ExpectOps: []string{"BarOp", "FooOp"},
- ExpectShapes: []string{
- "BarOpInput", "BarOpOutput", "FooOpInput", "FooOpOutput",
- },
- },
- "HTTP/2 with optional": {
- Model: strings.Replace(baseModel, "{h2Option}", "optional", 1),
- ExpectOps: []string{"BarOp", "EventStreamOp", "FooOp"},
- ExpectShapes: []string{
- "BarOpInput", "BarOpOutput", "EmptyEvent",
- "EventStreamOpEventStream", "EventStreamOpInput",
- "EventStreamOpOutput", "FooOpInput", "FooOpOutput",
- },
- },
- }
- for name, c := range cases {
- t.Run(name, func(t *testing.T) {
- var a API
- a.AttachString(c.Model)
- a.APIGoCode()
- if e, a := c.ExpectOps, a.OperationNames(); !reflect.DeepEqual(e, a) {
- t.Errorf("expect %v ops, got %v", e, a)
- }
- if e, a := c.ExpectShapes, a.ShapeNames(); !reflect.DeepEqual(e, a) {
- t.Errorf("expect %v shapes, got %v", e, a)
- }
- })
- }
- }
- func TestCreateInputOutputShapes(t *testing.T) {
- meta := Metadata{
- APIVersion: "0000-00-00",
- EndpointPrefix: "rpcservice",
- JSONVersion: "1.1",
- Protocol: "json",
- ServiceAbbreviation: "RPCService",
- ServiceFullName: "RPC Service",
- ServiceID: "RPCService",
- SignatureVersion: "v4",
- TargetPrefix: "RPCService_00000000",
- UID: "RPCService-0000-00-00",
- }
- type OpExpect struct {
- Input string
- Output string
- }
- cases := map[string]struct {
- API *API
- ExpectOps map[string]OpExpect
- ExpectShapes []string
- }{
- "allRename": {
- API: &API{Metadata: meta,
- Operations: map[string]*Operation{
- "FirstOp": {Name: "FirstOp",
- InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
- OutputRef: ShapeRef{ShapeName: "FirstOpResponse"},
- },
- "SecondOp": {Name: "SecondOp",
- InputRef: ShapeRef{ShapeName: "SecondOpRequest"},
- OutputRef: ShapeRef{ShapeName: "SecondOpResponse"},
- },
- },
- Shapes: map[string]*Shape{
- "FirstOpRequest": {ShapeName: "FirstOpRequest", Type: "structure"},
- "FirstOpResponse": {ShapeName: "FirstOpResponse", Type: "structure"},
- "SecondOpRequest": {ShapeName: "SecondOpRequest", Type: "structure"},
- "SecondOpResponse": {ShapeName: "SecondOpResponse", Type: "structure"},
- },
- },
- ExpectOps: map[string]OpExpect{
- "FirstOp": {
- Input: "FirstOpInput",
- Output: "FirstOpOutput",
- },
- "SecondOp": {
- Input: "SecondOpInput",
- Output: "SecondOpOutput",
- },
- },
- ExpectShapes: []string{
- "FirstOpInput", "FirstOpOutput",
- "SecondOpInput", "SecondOpOutput",
- },
- },
- "noRename": {
- API: &API{Metadata: meta,
- Operations: map[string]*Operation{
- "FirstOp": {Name: "FirstOp",
- InputRef: ShapeRef{ShapeName: "FirstOpInput"},
- OutputRef: ShapeRef{ShapeName: "FirstOpOutput"},
- },
- "SecondOp": {Name: "SecondOp",
- InputRef: ShapeRef{ShapeName: "SecondOpInput"},
- OutputRef: ShapeRef{ShapeName: "SecondOpOutput"},
- },
- },
- Shapes: map[string]*Shape{
- "FirstOpInput": {ShapeName: "FirstOpInput", Type: "structure"},
- "FirstOpOutput": {ShapeName: "FirstOpOutput", Type: "structure"},
- "SecondOpInput": {ShapeName: "SecondOpInput", Type: "structure"},
- "SecondOpOutput": {ShapeName: "SecondOpOutput", Type: "structure"},
- },
- },
- ExpectOps: map[string]OpExpect{
- "FirstOp": {
- Input: "FirstOpInput",
- Output: "FirstOpOutput",
- },
- "SecondOp": {
- Input: "SecondOpInput",
- Output: "SecondOpOutput",
- },
- },
- ExpectShapes: []string{
- "FirstOpInput", "FirstOpOutput",
- "SecondOpInput", "SecondOpOutput",
- },
- },
- "renameWithNested": {
- API: &API{Metadata: meta,
- Operations: map[string]*Operation{
- "FirstOp": {Name: "FirstOp",
- InputRef: ShapeRef{ShapeName: "FirstOpWriteMe"},
- OutputRef: ShapeRef{ShapeName: "FirstOpReadMe"},
- },
- "SecondOp": {Name: "SecondOp",
- InputRef: ShapeRef{ShapeName: "SecondOpWriteMe"},
- OutputRef: ShapeRef{ShapeName: "SecondOpReadMe"},
- },
- },
- Shapes: map[string]*Shape{
- "FirstOpWriteMe": {ShapeName: "FirstOpWriteMe", Type: "structure",
- MemberRefs: map[string]*ShapeRef{
- "Foo": {ShapeName: "String"},
- },
- },
- "FirstOpReadMe": {ShapeName: "FirstOpReadMe", Type: "structure",
- MemberRefs: map[string]*ShapeRef{
- "Bar": {ShapeName: "Struct"},
- "Once": {ShapeName: "Once"},
- },
- },
- "SecondOpWriteMe": {ShapeName: "SecondOpWriteMe", Type: "structure"},
- "SecondOpReadMe": {ShapeName: "SecondOpReadMe", Type: "structure"},
- "Once": {ShapeName: "Once", Type: "string"},
- "String": {ShapeName: "String", Type: "string"},
- "Struct": {ShapeName: "Struct", Type: "structure",
- MemberRefs: map[string]*ShapeRef{
- "Foo": {ShapeName: "String"},
- "Bar": {ShapeName: "Struct"},
- },
- },
- },
- },
- ExpectOps: map[string]OpExpect{
- "FirstOp": {
- Input: "FirstOpInput",
- Output: "FirstOpOutput",
- },
- "SecondOp": {
- Input: "SecondOpInput",
- Output: "SecondOpOutput",
- },
- },
- ExpectShapes: []string{
- "FirstOpInput", "FirstOpOutput",
- "Once",
- "SecondOpInput", "SecondOpOutput",
- "String", "Struct",
- },
- },
- "aliasedInput": {
- API: &API{Metadata: meta,
- Operations: map[string]*Operation{
- "FirstOp": {Name: "FirstOp",
- InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
- OutputRef: ShapeRef{ShapeName: "FirstOpResponse"},
- },
- },
- Shapes: map[string]*Shape{
- "FirstOpRequest": {ShapeName: "FirstOpRequest", Type: "structure",
- AliasedShapeName: true,
- },
- "FirstOpResponse": {ShapeName: "FirstOpResponse", Type: "structure"},
- },
- },
- ExpectOps: map[string]OpExpect{
- "FirstOp": {
- Input: "FirstOpRequest",
- Output: "FirstOpOutput",
- },
- },
- ExpectShapes: []string{
- "FirstOpOutput", "FirstOpRequest",
- },
- },
- "aliasedOutput": {
- API: &API{Metadata: meta,
- Operations: map[string]*Operation{
- "FirstOp": {Name: "FirstOp",
- InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
- OutputRef: ShapeRef{ShapeName: "FirstOpResponse"},
- },
- },
- Shapes: map[string]*Shape{
- "FirstOpRequest": {ShapeName: "FirstOpRequest", Type: "structure"},
- "FirstOpResponse": {ShapeName: "FirstOpResponse", Type: "structure",
- AliasedShapeName: true,
- },
- },
- },
- ExpectOps: map[string]OpExpect{
- "FirstOp": {
- Input: "FirstOpInput",
- Output: "FirstOpResponse",
- },
- },
- ExpectShapes: []string{
- "FirstOpInput", "FirstOpResponse",
- },
- },
- "resusedShape": {
- API: &API{Metadata: meta,
- Operations: map[string]*Operation{
- "FirstOp": {Name: "FirstOp",
- InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
- OutputRef: ShapeRef{ShapeName: "ReusedShape"},
- },
- },
- Shapes: map[string]*Shape{
- "FirstOpRequest": {ShapeName: "FirstOpRequest", Type: "structure",
- MemberRefs: map[string]*ShapeRef{
- "Foo": {ShapeName: "ReusedShape"},
- "ooF": {ShapeName: "ReusedShapeList"},
- },
- },
- "ReusedShape": {ShapeName: "ReusedShape", Type: "structure"},
- "ReusedShapeList": {ShapeName: "ReusedShapeList", Type: "list",
- MemberRef: ShapeRef{ShapeName: "ReusedShape"},
- },
- },
- },
- ExpectOps: map[string]OpExpect{
- "FirstOp": {
- Input: "FirstOpInput",
- Output: "FirstOpOutput",
- },
- },
- ExpectShapes: []string{
- "FirstOpInput", "FirstOpOutput",
- "ReusedShape", "ReusedShapeList",
- },
- },
- "aliasedResusedShape": {
- API: &API{Metadata: meta,
- Operations: map[string]*Operation{
- "FirstOp": {Name: "FirstOp",
- InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
- OutputRef: ShapeRef{ShapeName: "ReusedShape"},
- },
- },
- Shapes: map[string]*Shape{
- "FirstOpRequest": {ShapeName: "FirstOpRequest", Type: "structure",
- MemberRefs: map[string]*ShapeRef{
- "Foo": {ShapeName: "ReusedShape"},
- "ooF": {ShapeName: "ReusedShapeList"},
- },
- },
- "ReusedShape": {ShapeName: "ReusedShape", Type: "structure",
- AliasedShapeName: true,
- },
- "ReusedShapeList": {ShapeName: "ReusedShapeList", Type: "list",
- MemberRef: ShapeRef{ShapeName: "ReusedShape"},
- },
- },
- },
- ExpectOps: map[string]OpExpect{
- "FirstOp": {
- Input: "FirstOpInput",
- Output: "ReusedShape",
- },
- },
- ExpectShapes: []string{
- "FirstOpInput",
- "ReusedShape", "ReusedShapeList",
- },
- },
- "unsetInput": {
- API: &API{Metadata: meta,
- Operations: map[string]*Operation{
- "FirstOp": {Name: "FirstOp",
- OutputRef: ShapeRef{ShapeName: "FirstOpResponse"},
- },
- },
- Shapes: map[string]*Shape{
- "FirstOpResponse": {ShapeName: "FirstOpResponse", Type: "structure"},
- },
- },
- ExpectOps: map[string]OpExpect{
- "FirstOp": {
- Input: "FirstOpInput",
- Output: "FirstOpOutput",
- },
- },
- ExpectShapes: []string{
- "FirstOpInput", "FirstOpOutput",
- },
- },
- "unsetOutput": {
- API: &API{Metadata: meta,
- Operations: map[string]*Operation{
- "FirstOp": {Name: "FirstOp",
- InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
- },
- },
- Shapes: map[string]*Shape{
- "FirstOpRequest": {ShapeName: "FirstOpRequest", Type: "structure"},
- },
- },
- ExpectOps: map[string]OpExpect{
- "FirstOp": {
- Input: "FirstOpInput",
- Output: "FirstOpOutput",
- },
- },
- ExpectShapes: []string{
- "FirstOpInput", "FirstOpOutput",
- },
- },
- }
- for name, c := range cases {
- t.Run(name, func(t *testing.T) {
- a := c.API
- a.Setup()
- for opName, op := range a.Operations {
- if e, a := op.InputRef.ShapeName, op.InputRef.Shape.ShapeName; e != a {
- t.Errorf("expect input ref and shape names to match, %s, %s", e, a)
- }
- if e, a := c.ExpectOps[opName].Input, op.InputRef.ShapeName; e != a {
- t.Errorf("expect %v input shape, got %v", e, a)
- }
- if e, a := op.OutputRef.ShapeName, op.OutputRef.Shape.ShapeName; e != a {
- t.Errorf("expect output ref and shape names to match, %s, %s", e, a)
- }
- if e, a := c.ExpectOps[opName].Output, op.OutputRef.ShapeName; e != a {
- t.Errorf("expect %v output shape, got %v", e, a)
- }
- }
- if e, a := c.ExpectShapes, a.ShapeNames(); !reflect.DeepEqual(e, a) {
- t.Errorf("expect %v shapes, got %v", e, a)
- }
- })
- }
- }
|