github.com/aavshr/aws-sdk-go@v1.41.3/private/model/api/passes_test.go (about)

     1  //go:build go1.8 && codegen
     2  // +build go1.8,codegen
     3  
     4  package api
     5  
     6  import (
     7  	"reflect"
     8  	"strconv"
     9  	"strings"
    10  	"testing"
    11  )
    12  
    13  func TestUniqueInputAndOutputs(t *testing.T) {
    14  	const serviceName = "FooService"
    15  
    16  	shamelist[serviceName] = map[string]persistAPIType{
    17  		"OpOutputNoRename": {
    18  			output: true,
    19  		},
    20  		"OpInputNoRename": {
    21  			input: true,
    22  		},
    23  		"OpBothNoRename": {
    24  			input:  true,
    25  			output: true,
    26  		},
    27  	}
    28  
    29  	cases := [][]struct {
    30  		expectedInput  string
    31  		expectedOutput string
    32  		operation      string
    33  		input          string
    34  		output         string
    35  	}{
    36  		{
    37  			{
    38  				expectedInput:  "FooOperationInput",
    39  				expectedOutput: "FooOperationOutput",
    40  				operation:      "FooOperation",
    41  				input:          "FooInputShape",
    42  				output:         "FooOutputShape",
    43  			},
    44  			{
    45  				expectedInput:  "BarOperationInput",
    46  				expectedOutput: "BarOperationOutput",
    47  				operation:      "BarOperation",
    48  				input:          "FooInputShape",
    49  				output:         "FooOutputShape",
    50  			},
    51  		},
    52  		{
    53  			{
    54  				expectedInput:  "FooOperationInput",
    55  				expectedOutput: "FooOperationOutput",
    56  				operation:      "FooOperation",
    57  				input:          "FooInputShape",
    58  				output:         "FooOutputShape",
    59  			},
    60  			{
    61  				expectedInput:  "OpOutputNoRenameInput",
    62  				expectedOutput: "OpOutputNoRenameOutputShape",
    63  				operation:      "OpOutputNoRename",
    64  				input:          "OpOutputNoRenameInputShape",
    65  				output:         "OpOutputNoRenameOutputShape",
    66  			},
    67  		},
    68  		{
    69  			{
    70  				expectedInput:  "FooOperationInput",
    71  				expectedOutput: "FooOperationOutput",
    72  				operation:      "FooOperation",
    73  				input:          "FooInputShape",
    74  				output:         "FooOutputShape",
    75  			},
    76  			{
    77  				expectedInput:  "OpInputNoRenameInputShape",
    78  				expectedOutput: "OpInputNoRenameOutput",
    79  				operation:      "OpInputNoRename",
    80  				input:          "OpInputNoRenameInputShape",
    81  				output:         "OpInputNoRenameOutputShape",
    82  			},
    83  		},
    84  		{
    85  			{
    86  				expectedInput:  "FooOperationInput",
    87  				expectedOutput: "FooOperationOutput",
    88  				operation:      "FooOperation",
    89  				input:          "FooInputShape",
    90  				output:         "FooOutputShape",
    91  			},
    92  			{
    93  				expectedInput:  "OpInputNoRenameInputShape",
    94  				expectedOutput: "OpInputNoRenameOutputShape",
    95  				operation:      "OpBothNoRename",
    96  				input:          "OpInputNoRenameInputShape",
    97  				output:         "OpInputNoRenameOutputShape",
    98  			},
    99  		},
   100  	}
   101  
   102  	for i, c := range cases {
   103  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   104  			a := &API{
   105  				name:       serviceName,
   106  				Operations: map[string]*Operation{},
   107  				Shapes:     map[string]*Shape{},
   108  			}
   109  
   110  			expected := map[string][]string{}
   111  			for _, op := range c {
   112  				o := &Operation{
   113  					Name:         op.operation,
   114  					ExportedName: op.operation,
   115  					InputRef: ShapeRef{
   116  						API:       a,
   117  						ShapeName: op.input,
   118  						Shape: &Shape{
   119  							API:       a,
   120  							ShapeName: op.input,
   121  						},
   122  					},
   123  					OutputRef: ShapeRef{
   124  						API:       a,
   125  						ShapeName: op.output,
   126  						Shape: &Shape{
   127  							API:       a,
   128  							ShapeName: op.output,
   129  						},
   130  					},
   131  				}
   132  				o.InputRef.Shape.refs = append(o.InputRef.Shape.refs, &o.InputRef)
   133  				o.OutputRef.Shape.refs = append(o.OutputRef.Shape.refs, &o.OutputRef)
   134  
   135  				a.Operations[o.Name] = o
   136  
   137  				a.Shapes[op.input] = o.InputRef.Shape
   138  				a.Shapes[op.output] = o.OutputRef.Shape
   139  
   140  				expected[op.operation] = append(expected[op.operation],
   141  					op.expectedInput,
   142  					op.expectedOutput,
   143  				)
   144  			}
   145  
   146  			a.fixStutterNames()
   147  			a.applyShapeNameAliases()
   148  			a.createInputOutputShapes()
   149  			for k, v := range expected {
   150  				if e, ac := v[0], a.Operations[k].InputRef.Shape.ShapeName; e != ac {
   151  					t.Errorf("Error %s case: Expected %q, but received %q",
   152  						k, e, ac)
   153  				}
   154  				if e, ac := v[1], a.Operations[k].OutputRef.Shape.ShapeName; e != ac {
   155  					t.Errorf("Error %s case: Expected %q, but received %q",
   156  						k, e, ac)
   157  				}
   158  			}
   159  		})
   160  
   161  	}
   162  }
   163  
   164  func TestCollidingFields(t *testing.T) {
   165  	cases := map[string]struct {
   166  		MemberRefs  map[string]*ShapeRef
   167  		Expect      []string
   168  		IsException bool
   169  	}{
   170  		"SimpleMembers": {
   171  			MemberRefs: map[string]*ShapeRef{
   172  				"Code":     {},
   173  				"Foo":      {},
   174  				"GoString": {},
   175  				"Message":  {},
   176  				"OrigErr":  {},
   177  				"SetFoo":   {},
   178  				"String":   {},
   179  				"Validate": {},
   180  			},
   181  			Expect: []string{
   182  				"Code",
   183  				"Foo",
   184  				"GoString_",
   185  				"Message",
   186  				"OrigErr",
   187  				"SetFoo_",
   188  				"String_",
   189  				"Validate_",
   190  			},
   191  		},
   192  		"ExceptionShape": {
   193  			IsException: true,
   194  			MemberRefs: map[string]*ShapeRef{
   195  				"Code":    {},
   196  				"Message": {},
   197  				"OrigErr": {},
   198  				"Other":   {},
   199  				"String":  {},
   200  			},
   201  			Expect: []string{
   202  				"Code_",
   203  				"Message_",
   204  				"OrigErr_",
   205  				"Other",
   206  				"String_",
   207  			},
   208  		},
   209  	}
   210  
   211  	for k, c := range cases {
   212  		t.Run(k, func(t *testing.T) {
   213  			a := &API{
   214  				Shapes: map[string]*Shape{
   215  					"shapename": {
   216  						ShapeName:  k,
   217  						MemberRefs: c.MemberRefs,
   218  						Exception:  c.IsException,
   219  					},
   220  				},
   221  			}
   222  
   223  			a.renameCollidingFields()
   224  
   225  			for i, name := range a.Shapes["shapename"].MemberNames() {
   226  				if e, a := c.Expect[i], name; e != a {
   227  					t.Errorf("expect %v, got %v", e, a)
   228  				}
   229  			}
   230  		})
   231  	}
   232  }
   233  
   234  func TestCollidingFields_MaintainOriginalName(t *testing.T) {
   235  	cases := map[string]struct {
   236  		MemberRefs map[string]*ShapeRef
   237  		Expect     map[string]*ShapeRef
   238  	}{
   239  		"NoLocationName": {
   240  			MemberRefs: map[string]*ShapeRef{
   241  				"String": {},
   242  			},
   243  			Expect: map[string]*ShapeRef{
   244  				"String_": {LocationName: "String"},
   245  			},
   246  		},
   247  		"ExitingLocationName": {
   248  			MemberRefs: map[string]*ShapeRef{
   249  				"String": {LocationName: "OtherName"},
   250  			},
   251  			Expect: map[string]*ShapeRef{
   252  				"String_": {LocationName: "OtherName"},
   253  			},
   254  		},
   255  	}
   256  
   257  	for k, c := range cases {
   258  		t.Run(k, func(t *testing.T) {
   259  			a := &API{
   260  				Shapes: map[string]*Shape{
   261  					"shapename": {
   262  						ShapeName:  k,
   263  						MemberRefs: c.MemberRefs,
   264  					},
   265  				},
   266  			}
   267  
   268  			a.renameCollidingFields()
   269  
   270  			if e, a := c.Expect, a.Shapes["shapename"].MemberRefs; !reflect.DeepEqual(e, a) {
   271  				t.Errorf("expect %v, got %v", e, a)
   272  			}
   273  		})
   274  	}
   275  }
   276  
   277  func TestCreateInputOutputShapes(t *testing.T) {
   278  	meta := Metadata{
   279  		APIVersion:          "0000-00-00",
   280  		EndpointPrefix:      "rpcservice",
   281  		JSONVersion:         "1.1",
   282  		Protocol:            "json",
   283  		ServiceAbbreviation: "RPCService",
   284  		ServiceFullName:     "RPC Service",
   285  		ServiceID:           "RPCService",
   286  		SignatureVersion:    "v4",
   287  		TargetPrefix:        "RPCService_00000000",
   288  		UID:                 "RPCService-0000-00-00",
   289  	}
   290  
   291  	type OpExpect struct {
   292  		Input  string
   293  		Output string
   294  	}
   295  
   296  	cases := map[string]struct {
   297  		API          *API
   298  		ExpectOps    map[string]OpExpect
   299  		ExpectShapes []string
   300  	}{
   301  		"allRename": {
   302  			API: &API{Metadata: meta,
   303  				Operations: map[string]*Operation{
   304  					"FirstOp": {
   305  						Name:      "FirstOp",
   306  						InputRef:  ShapeRef{ShapeName: "FirstOpRequest"},
   307  						OutputRef: ShapeRef{ShapeName: "FirstOpResponse"},
   308  					},
   309  					"SecondOp": {
   310  						Name:      "SecondOp",
   311  						InputRef:  ShapeRef{ShapeName: "SecondOpRequest"},
   312  						OutputRef: ShapeRef{ShapeName: "SecondOpResponse"},
   313  					},
   314  				},
   315  				Shapes: map[string]*Shape{
   316  					"FirstOpRequest": {
   317  						ShapeName: "FirstOpRequest",
   318  						Type:      "structure",
   319  					},
   320  					"FirstOpResponse": {
   321  						ShapeName: "FirstOpResponse",
   322  						Type:      "structure",
   323  					},
   324  					"SecondOpRequest": {
   325  						ShapeName: "SecondOpRequest",
   326  						Type:      "structure",
   327  					},
   328  					"SecondOpResponse": {
   329  						ShapeName: "SecondOpResponse",
   330  						Type:      "structure",
   331  					},
   332  				},
   333  			},
   334  			ExpectOps: map[string]OpExpect{
   335  				"FirstOp": {
   336  					Input:  "FirstOpInput",
   337  					Output: "FirstOpOutput",
   338  				},
   339  				"SecondOp": {
   340  					Input:  "SecondOpInput",
   341  					Output: "SecondOpOutput",
   342  				},
   343  			},
   344  			ExpectShapes: []string{
   345  				"FirstOpInput",
   346  				"FirstOpOutput",
   347  				"SecondOpInput",
   348  				"SecondOpOutput",
   349  			},
   350  		},
   351  		"noRename": {
   352  			API: &API{Metadata: meta,
   353  				Operations: map[string]*Operation{
   354  					"FirstOp": {
   355  						Name:      "FirstOp",
   356  						InputRef:  ShapeRef{ShapeName: "FirstOpInput"},
   357  						OutputRef: ShapeRef{ShapeName: "FirstOpOutput"},
   358  					},
   359  					"SecondOp": {
   360  						Name:      "SecondOp",
   361  						InputRef:  ShapeRef{ShapeName: "SecondOpInput"},
   362  						OutputRef: ShapeRef{ShapeName: "SecondOpOutput"},
   363  					},
   364  				},
   365  				Shapes: map[string]*Shape{
   366  					"FirstOpInput": {
   367  						ShapeName: "FirstOpInput",
   368  						Type:      "structure",
   369  					},
   370  					"FirstOpOutput": {
   371  						ShapeName: "FirstOpOutput",
   372  						Type:      "structure",
   373  					},
   374  					"SecondOpInput": {
   375  						ShapeName: "SecondOpInput",
   376  						Type:      "structure",
   377  					},
   378  					"SecondOpOutput": {
   379  						ShapeName: "SecondOpOutput",
   380  						Type:      "structure",
   381  					},
   382  				},
   383  			},
   384  			ExpectOps: map[string]OpExpect{
   385  				"FirstOp": {
   386  					Input:  "FirstOpInput",
   387  					Output: "FirstOpOutput",
   388  				},
   389  				"SecondOp": {
   390  					Input:  "SecondOpInput",
   391  					Output: "SecondOpOutput",
   392  				},
   393  			},
   394  			ExpectShapes: []string{
   395  				"FirstOpInput",
   396  				"FirstOpOutput",
   397  				"SecondOpInput",
   398  				"SecondOpOutput",
   399  			},
   400  		},
   401  		"renameWithNested": {
   402  			API: &API{Metadata: meta,
   403  				Operations: map[string]*Operation{
   404  					"FirstOp": {
   405  						Name:      "FirstOp",
   406  						InputRef:  ShapeRef{ShapeName: "FirstOpWriteMe"},
   407  						OutputRef: ShapeRef{ShapeName: "FirstOpReadMe"},
   408  					},
   409  					"SecondOp": {
   410  						Name:      "SecondOp",
   411  						InputRef:  ShapeRef{ShapeName: "SecondOpWriteMe"},
   412  						OutputRef: ShapeRef{ShapeName: "SecondOpReadMe"},
   413  					},
   414  				},
   415  				Shapes: map[string]*Shape{
   416  					"FirstOpWriteMe": {
   417  						ShapeName: "FirstOpWriteMe",
   418  						Type:      "structure",
   419  						MemberRefs: map[string]*ShapeRef{
   420  							"Foo": {ShapeName: "String"},
   421  						},
   422  					},
   423  					"FirstOpReadMe": {
   424  						ShapeName: "FirstOpReadMe",
   425  						Type:      "structure",
   426  						MemberRefs: map[string]*ShapeRef{
   427  							"Bar":  {ShapeName: "Struct"},
   428  							"Once": {ShapeName: "Once"},
   429  						},
   430  					},
   431  					"SecondOpWriteMe": {
   432  						ShapeName: "SecondOpWriteMe",
   433  						Type:      "structure",
   434  					},
   435  					"SecondOpReadMe": {
   436  						ShapeName: "SecondOpReadMe",
   437  						Type:      "structure",
   438  					},
   439  					"Once": {
   440  						ShapeName: "Once",
   441  						Type:      "string",
   442  					},
   443  					"String": {
   444  						ShapeName: "String",
   445  						Type:      "string",
   446  					},
   447  					"Struct": {
   448  						ShapeName: "Struct",
   449  						Type:      "structure",
   450  						MemberRefs: map[string]*ShapeRef{
   451  							"Foo": {ShapeName: "String"},
   452  							"Bar": {ShapeName: "Struct"},
   453  						},
   454  					},
   455  				},
   456  			},
   457  			ExpectOps: map[string]OpExpect{
   458  				"FirstOp": {
   459  					Input:  "FirstOpInput",
   460  					Output: "FirstOpOutput",
   461  				},
   462  				"SecondOp": {
   463  					Input:  "SecondOpInput",
   464  					Output: "SecondOpOutput",
   465  				},
   466  			},
   467  			ExpectShapes: []string{
   468  				"FirstOpInput",
   469  				"FirstOpOutput",
   470  				"Once",
   471  				"SecondOpInput",
   472  				"SecondOpOutput",
   473  				"String",
   474  				"Struct",
   475  			},
   476  		},
   477  		"aliasedInput": {
   478  			API: &API{Metadata: meta,
   479  				Operations: map[string]*Operation{
   480  					"FirstOp": {
   481  						Name:      "FirstOp",
   482  						InputRef:  ShapeRef{ShapeName: "FirstOpRequest"},
   483  						OutputRef: ShapeRef{ShapeName: "FirstOpResponse"},
   484  					},
   485  				},
   486  				Shapes: map[string]*Shape{
   487  					"FirstOpRequest": {
   488  						ShapeName:        "FirstOpRequest",
   489  						Type:             "structure",
   490  						AliasedShapeName: true,
   491  					},
   492  					"FirstOpResponse": {
   493  						ShapeName: "FirstOpResponse",
   494  						Type:      "structure",
   495  					},
   496  				},
   497  			},
   498  			ExpectOps: map[string]OpExpect{
   499  				"FirstOp": {
   500  					Input:  "FirstOpRequest",
   501  					Output: "FirstOpOutput",
   502  				},
   503  			},
   504  			ExpectShapes: []string{
   505  				"FirstOpOutput",
   506  				"FirstOpRequest",
   507  			},
   508  		},
   509  		"aliasedOutput": {
   510  			API: &API{
   511  				Metadata: meta,
   512  				Operations: map[string]*Operation{
   513  					"FirstOp": {
   514  						Name:      "FirstOp",
   515  						InputRef:  ShapeRef{ShapeName: "FirstOpRequest"},
   516  						OutputRef: ShapeRef{ShapeName: "FirstOpResponse"},
   517  					},
   518  				},
   519  				Shapes: map[string]*Shape{
   520  					"FirstOpRequest": {
   521  						ShapeName: "FirstOpRequest",
   522  						Type:      "structure",
   523  					},
   524  					"FirstOpResponse": {
   525  						ShapeName:        "FirstOpResponse",
   526  						Type:             "structure",
   527  						AliasedShapeName: true,
   528  					},
   529  				},
   530  			},
   531  			ExpectOps: map[string]OpExpect{
   532  				"FirstOp": {
   533  					Input:  "FirstOpInput",
   534  					Output: "FirstOpResponse",
   535  				},
   536  			},
   537  			ExpectShapes: []string{
   538  				"FirstOpInput", "FirstOpResponse",
   539  			},
   540  		},
   541  		"resusedShape": {
   542  			API: &API{
   543  				Metadata: meta,
   544  				Operations: map[string]*Operation{
   545  					"FirstOp": {
   546  						Name:      "FirstOp",
   547  						InputRef:  ShapeRef{ShapeName: "FirstOpRequest"},
   548  						OutputRef: ShapeRef{ShapeName: "ReusedShape"},
   549  					},
   550  				},
   551  				Shapes: map[string]*Shape{
   552  					"FirstOpRequest": {
   553  						ShapeName: "FirstOpRequest",
   554  						Type:      "structure",
   555  						MemberRefs: map[string]*ShapeRef{
   556  							"Foo": {ShapeName: "ReusedShape"},
   557  							"ooF": {ShapeName: "ReusedShapeList"},
   558  						},
   559  					},
   560  					"ReusedShape": {
   561  						ShapeName: "ReusedShape",
   562  						Type:      "structure",
   563  					},
   564  					"ReusedShapeList": {
   565  						ShapeName: "ReusedShapeList",
   566  						Type:      "list",
   567  						MemberRef: ShapeRef{ShapeName: "ReusedShape"},
   568  					},
   569  				},
   570  			},
   571  			ExpectOps: map[string]OpExpect{
   572  				"FirstOp": {
   573  					Input:  "FirstOpInput",
   574  					Output: "FirstOpOutput",
   575  				},
   576  			},
   577  			ExpectShapes: []string{
   578  				"FirstOpInput",
   579  				"FirstOpOutput",
   580  				"ReusedShape",
   581  				"ReusedShapeList",
   582  			},
   583  		},
   584  		"aliasedResusedShape": {
   585  			API: &API{
   586  				Metadata: meta,
   587  				Operations: map[string]*Operation{
   588  					"FirstOp": {
   589  						Name:      "FirstOp",
   590  						InputRef:  ShapeRef{ShapeName: "FirstOpRequest"},
   591  						OutputRef: ShapeRef{ShapeName: "ReusedShape"},
   592  					},
   593  				},
   594  				Shapes: map[string]*Shape{
   595  					"FirstOpRequest": {
   596  						ShapeName: "FirstOpRequest",
   597  						Type:      "structure",
   598  						MemberRefs: map[string]*ShapeRef{
   599  							"Foo": {ShapeName: "ReusedShape"},
   600  							"ooF": {ShapeName: "ReusedShapeList"},
   601  						},
   602  					},
   603  					"ReusedShape": {
   604  						ShapeName:        "ReusedShape",
   605  						Type:             "structure",
   606  						AliasedShapeName: true,
   607  					},
   608  					"ReusedShapeList": {
   609  						ShapeName: "ReusedShapeList",
   610  						Type:      "list",
   611  						MemberRef: ShapeRef{ShapeName: "ReusedShape"},
   612  					},
   613  				},
   614  			},
   615  			ExpectOps: map[string]OpExpect{
   616  				"FirstOp": {
   617  					Input:  "FirstOpInput",
   618  					Output: "ReusedShape",
   619  				},
   620  			},
   621  			ExpectShapes: []string{
   622  				"FirstOpInput",
   623  				"ReusedShape",
   624  				"ReusedShapeList",
   625  			},
   626  		},
   627  		"unsetInput": {
   628  			API: &API{Metadata: meta,
   629  				Operations: map[string]*Operation{
   630  					"FirstOp": {
   631  						Name:      "FirstOp",
   632  						OutputRef: ShapeRef{ShapeName: "FirstOpResponse"},
   633  					},
   634  				},
   635  				Shapes: map[string]*Shape{
   636  					"FirstOpResponse": {
   637  						ShapeName: "FirstOpResponse",
   638  						Type:      "structure",
   639  					},
   640  				},
   641  			},
   642  			ExpectOps: map[string]OpExpect{
   643  				"FirstOp": {
   644  					Input:  "FirstOpInput",
   645  					Output: "FirstOpOutput",
   646  				},
   647  			},
   648  			ExpectShapes: []string{
   649  				"FirstOpInput",
   650  				"FirstOpOutput",
   651  			},
   652  		},
   653  		"unsetOutput": {
   654  			API: &API{Metadata: meta,
   655  				Operations: map[string]*Operation{
   656  					"FirstOp": {
   657  						Name:     "FirstOp",
   658  						InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
   659  					},
   660  				},
   661  				Shapes: map[string]*Shape{
   662  					"FirstOpRequest": {
   663  						ShapeName: "FirstOpRequest",
   664  						Type:      "structure",
   665  					},
   666  				},
   667  			},
   668  			ExpectOps: map[string]OpExpect{
   669  				"FirstOp": {
   670  					Input:  "FirstOpInput",
   671  					Output: "FirstOpOutput",
   672  				},
   673  			},
   674  			ExpectShapes: []string{
   675  				"FirstOpInput",
   676  				"FirstOpOutput",
   677  			},
   678  		},
   679  		"collidingShape": {
   680  			API: &API{
   681  				name:     "APIClientName",
   682  				Metadata: meta,
   683  				Operations: map[string]*Operation{
   684  					"FirstOp": {
   685  						Name:     "FirstOp",
   686  						InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
   687  					},
   688  				},
   689  				Shapes: map[string]*Shape{
   690  					"FirstOpRequest": {
   691  						ShapeName: "FirstOpRequest",
   692  						Type:      "structure",
   693  						MemberRefs: map[string]*ShapeRef{
   694  							"Foo": {ShapeName: "APIClientName"},
   695  							"ooF": {ShapeName: "APIClientNameList"},
   696  						},
   697  					},
   698  					"APIClientName": {
   699  						ShapeName: "APIClientName", Type: "structure",
   700  					},
   701  					"APIClientNameList": {
   702  						ShapeName: "APIClientNameList", Type: "list",
   703  						MemberRef: ShapeRef{ShapeName: "APIClientName"},
   704  					},
   705  				},
   706  			},
   707  			ExpectOps: map[string]OpExpect{
   708  				"FirstOp": {
   709  					Input:  "FirstOpInput",
   710  					Output: "FirstOpOutput",
   711  				},
   712  			},
   713  			ExpectShapes: []string{
   714  				"APIClientNameList",
   715  				"APIClientName_",
   716  				"FirstOpInput",
   717  				"FirstOpOutput",
   718  			},
   719  		},
   720  		"MemberShapesWithInputAsSuffix": {
   721  			API: &API{
   722  				name:     "APIClientName",
   723  				Metadata: meta,
   724  				Operations: map[string]*Operation{
   725  					"FirstOp": {
   726  						Name:     "FirstOp",
   727  						InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
   728  					},
   729  				},
   730  				Shapes: map[string]*Shape{
   731  					"FirstOpRequest": {
   732  						ShapeName: "FirstOpRequest",
   733  						Type:      "structure",
   734  						MemberRefs: map[string]*ShapeRef{
   735  							"Foo": {ShapeName: "APIClientName"},
   736  							"ooF": {ShapeName: "FirstOpInput"},
   737  						},
   738  					},
   739  					"APIClientName": {
   740  						ShapeName: "APIClientName", Type: "structure",
   741  					},
   742  					"FirstOpInput": {
   743  						ShapeName: "FirstOpInput", Type: "list",
   744  						MemberRef: ShapeRef{
   745  							ShapeName: "APIClientName",
   746  						},
   747  					},
   748  				},
   749  			},
   750  			ExpectOps: map[string]OpExpect{
   751  				"FirstOp": {
   752  					Input:  "FirstOpInput",
   753  					Output: "FirstOpOutput",
   754  				},
   755  			},
   756  			ExpectShapes: []string{
   757  				"APIClientName_",
   758  				"FirstOpInput",
   759  				"FirstOpInput_",
   760  				"FirstOpOutput",
   761  			},
   762  		},
   763  		"MemberShapesWithOutputAsSuffix": {
   764  			API: &API{
   765  				name:     "APIClientName",
   766  				Metadata: meta,
   767  				Operations: map[string]*Operation{
   768  					"FirstOp": {
   769  						Name:      "FirstOp",
   770  						OutputRef: ShapeRef{ShapeName: "FirstOpResponse"},
   771  					},
   772  				},
   773  				Shapes: map[string]*Shape{
   774  					"FirstOpResponse": {
   775  						ShapeName: "FirstOpResponse",
   776  						Type:      "structure",
   777  						MemberRefs: map[string]*ShapeRef{
   778  							"Foo": {ShapeName: "APIClientName"},
   779  							"ooF": {ShapeName: "FirstOpOutput"},
   780  						},
   781  					},
   782  					"APIClientName": {
   783  						ShapeName: "APIClientName", Type: "structure",
   784  					},
   785  					"FirstOpOutput": {
   786  						ShapeName: "FirstOpOutput", Type: "list",
   787  						MemberRef: ShapeRef{ShapeName: "APIClientName"},
   788  					},
   789  				},
   790  			},
   791  			ExpectOps: map[string]OpExpect{
   792  				"FirstOp": {
   793  					Input:  "FirstOpInput",
   794  					Output: "FirstOpOutput",
   795  				},
   796  			},
   797  			ExpectShapes: []string{
   798  				"APIClientName_",
   799  				"FirstOpInput",
   800  				"FirstOpOutput",
   801  				"FirstOpOutput_",
   802  			},
   803  		},
   804  	}
   805  
   806  	for name, c := range cases {
   807  		t.Run(name, func(t *testing.T) {
   808  			a := c.API
   809  			a.Setup()
   810  
   811  			for opName, op := range a.Operations {
   812  				if e, a := op.InputRef.ShapeName, op.InputRef.Shape.ShapeName; e != a {
   813  					t.Errorf("expect input ref and shape names to match, %s, %s", e, a)
   814  				}
   815  				if e, a := c.ExpectOps[opName].Input, op.InputRef.ShapeName; e != a {
   816  					t.Errorf("expect %v input shape, got %v", e, a)
   817  				}
   818  
   819  				if e, a := op.OutputRef.ShapeName, op.OutputRef.Shape.ShapeName; e != a {
   820  					t.Errorf("expect output ref and shape names to match, %s, %s", e, a)
   821  				}
   822  				if e, a := c.ExpectOps[opName].Output, op.OutputRef.ShapeName; e != a {
   823  					t.Errorf("expect %v output shape, got %v", e, a)
   824  				}
   825  			}
   826  
   827  			if e, a := c.ExpectShapes, a.ShapeNames(); !reflect.DeepEqual(e, a) {
   828  				t.Errorf("expect %v shapes, got %v", e, a)
   829  			}
   830  		})
   831  	}
   832  }
   833  
   834  func TestValidateShapeNameMethod(t *testing.T) {
   835  	cases := map[string]struct {
   836  		inputShapeName    string
   837  		shapeType         string
   838  		expectedShapeName string
   839  		expectedError     string
   840  	}{
   841  		"empty case": {
   842  			inputShapeName:    "",
   843  			shapeType:         "structure",
   844  			expectedShapeName: "",
   845  			expectedError:     "invalid shape name found",
   846  		},
   847  		"No rename": {
   848  			inputShapeName:    "Sample123Shape",
   849  			shapeType:         "structure",
   850  			expectedShapeName: "Sample123Shape",
   851  		},
   852  		"starts with underscores": {
   853  			inputShapeName:    "__Sample123Shape",
   854  			shapeType:         "structure",
   855  			expectedShapeName: "Sample123Shape",
   856  		},
   857  		"Contains underscores": {
   858  			inputShapeName:    "__sample_123_shape__",
   859  			shapeType:         "structure",
   860  			expectedShapeName: "Sample123Shape",
   861  		},
   862  		"Starts with numeric character": {
   863  			inputShapeName:    "123__sampleShape",
   864  			shapeType:         "structure",
   865  			expectedShapeName: "",
   866  			expectedError:     "invalid shape name found",
   867  		},
   868  		"Starts with non alphabetic or non underscore character": {
   869  			inputShapeName:    "&&SampleShape",
   870  			shapeType:         "structure",
   871  			expectedShapeName: "",
   872  			expectedError:     "invalid shape name found",
   873  		},
   874  		"Contains non Alphanumeric or non underscore character": {
   875  			inputShapeName:    "Sample&__Shape",
   876  			shapeType:         "structure",
   877  			expectedShapeName: "",
   878  			expectedError:     "invalid shape name found",
   879  		},
   880  		"Renamed Shape already exists": {
   881  			inputShapeName:    "__sample_shape",
   882  			shapeType:         "structure",
   883  			expectedShapeName: "",
   884  			expectedError:     "rename would result in shape name collision",
   885  		},
   886  		"empty case for enums shape type": {
   887  			inputShapeName:    "",
   888  			shapeType:         "string",
   889  			expectedShapeName: "",
   890  			expectedError:     "invalid shape name found",
   891  		},
   892  		"No rename for enums shape type": {
   893  			inputShapeName:    "Sample123Shape",
   894  			shapeType:         "string",
   895  			expectedShapeName: "Sample123Shape",
   896  		},
   897  		"starts with underscores for enums shape type": {
   898  			inputShapeName:    "__Sample123Shape",
   899  			shapeType:         "string",
   900  			expectedShapeName: "Sample123Shape",
   901  		},
   902  		"Contains underscores for enums shape type": {
   903  			inputShapeName:    "__sample_123_shape__",
   904  			shapeType:         "string",
   905  			expectedShapeName: "Sample123Shape",
   906  		},
   907  		"Starts with numeric character for enums shape type": {
   908  			inputShapeName:    "123__sampleShape",
   909  			shapeType:         "string",
   910  			expectedShapeName: "",
   911  			expectedError:     "invalid shape name found",
   912  		},
   913  		"Starts with non alphabetic or non underscore character for enums shape type": {
   914  			inputShapeName:    "&&SampleShape",
   915  			shapeType:         "string",
   916  			expectedShapeName: "",
   917  			expectedError:     "invalid shape name found",
   918  		},
   919  		"Contains non Alphanumeric or non underscore character for enums shape type": {
   920  			inputShapeName:    "Sample&__Shape",
   921  			shapeType:         "string",
   922  			expectedShapeName: "",
   923  			expectedError:     "invalid shape name found",
   924  		},
   925  		"Renamed Shape already exists for enums shape type": {
   926  			inputShapeName:    "__sample_shape",
   927  			shapeType:         "string",
   928  			expectedShapeName: "",
   929  			expectedError:     "rename would result in shape name collision",
   930  		},
   931  	}
   932  
   933  	for name, c := range cases {
   934  		operation := "FooOperation"
   935  		t.Run(name, func(t *testing.T) {
   936  			a := &API{
   937  				Operations: map[string]*Operation{},
   938  				Shapes:     map[string]*Shape{},
   939  			}
   940  			// add another shape with name SampleShape to check for collision
   941  			a.Shapes["SampleShape"] = &Shape{ShapeName: "SampleShape"}
   942  			o := &Operation{
   943  				Name:         operation,
   944  				ExportedName: operation,
   945  				InputRef: ShapeRef{
   946  					API:       a,
   947  					ShapeName: c.inputShapeName,
   948  					Shape: &Shape{
   949  						API:       a,
   950  						ShapeName: c.inputShapeName,
   951  						Type:      c.shapeType,
   952  						Enum:      []string{"x"},
   953  					},
   954  				},
   955  			}
   956  			o.InputRef.Shape.refs = append(o.InputRef.Shape.refs, &o.InputRef)
   957  			a.Operations[o.Name] = o
   958  			a.Shapes[c.inputShapeName] = o.InputRef.Shape
   959  
   960  			err := a.validateShapeNames()
   961  			if err != nil || c.expectedError != "" {
   962  				if err == nil {
   963  					t.Fatalf("Received no error, expected error with log: \n \t %v ", c.expectedError)
   964  				}
   965  				if c.expectedError == "" {
   966  					t.Fatalf("Expected no error, got %v", err.Error())
   967  				}
   968  				if e, a := err.Error(), c.expectedError; !strings.Contains(e, a) {
   969  					t.Fatalf("Expected to receive error containing %v, got %v", e, a)
   970  				}
   971  				return
   972  			}
   973  
   974  			if e, a := c.expectedShapeName, o.InputRef.Shape.ShapeName; e != a {
   975  				t.Fatalf("Expected shape name to be %v, got %v", e, a)
   976  			}
   977  		})
   978  	}
   979  }