diff --git a/operation.go b/operation.go index 106fc82c2..b1ff5e00d 100644 --- a/operation.go +++ b/operation.go @@ -632,9 +632,11 @@ func findTypeDef(importPath, typeName string) (*ast.TypeSpec, error) { for i := range pkgInfo.Files { for _, astDeclaration := range pkgInfo.Files[i].Decls { - if generalDeclaration, ok := astDeclaration.(*ast.GenDecl); ok && generalDeclaration.Tok == token.TYPE { + generalDeclaration, ok := astDeclaration.(*ast.GenDecl) + if ok && generalDeclaration.Tok == token.TYPE { for _, astSpec := range generalDeclaration.Specs { - if typeSpec, ok := astSpec.(*ast.TypeSpec); ok { + typeSpec, ok := astSpec.(*ast.TypeSpec) + if ok { if typeSpec.Name.String() == typeName { return typeSpec, nil } @@ -771,8 +773,6 @@ func (operation *Operation) parseAPIObjectSchema(schemaType, refType string, ast } return spec.ArrayProperty(schema), nil - case PRIMITIVE: - return PrimitiveSchema(refType), nil default: return PrimitiveSchema(schemaType), nil } diff --git a/operation_test.go b/operation_test.go index a545b006e..31ec48e70 100644 --- a/operation_test.go +++ b/operation_test.go @@ -12,6 +12,8 @@ import ( ) func TestParseEmptyComment(t *testing.T) { + t.Parallel() + operation := NewOperation(nil) err := operation.ParseComment("//", nil) @@ -19,6 +21,8 @@ func TestParseEmptyComment(t *testing.T) { } func TestParseTagsComment(t *testing.T) { + t.Parallel() + expected := `{ "tags": [ "pet", @@ -35,6 +39,8 @@ func TestParseTagsComment(t *testing.T) { } func TestParseAcceptComment(t *testing.T) { + t.Parallel() + expected := `{ "consumes": [ "application/json", @@ -63,6 +69,8 @@ func TestParseAcceptComment(t *testing.T) { } func TestParseAcceptCommentErr(t *testing.T) { + t.Parallel() + comment := `/@Accept unknown` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -70,6 +78,8 @@ func TestParseAcceptCommentErr(t *testing.T) { } func TestParseProduceComment(t *testing.T) { + t.Parallel() + expected := `{ "produces": [ "application/json", @@ -96,13 +106,16 @@ func TestParseProduceComment(t *testing.T) { } func TestParseProduceCommentErr(t *testing.T) { - comment := `/@Produce foo` + t.Parallel() + operation := new(Operation) - err := operation.ParseComment(comment, nil) + err := operation.ParseComment("/@Produce foo", nil) assert.Error(t, err) } func TestParseRouterComment(t *testing.T) { + t.Parallel() + comment := `/@Router /customer/get-wishlist/{wishlist_id} [get]` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -113,6 +126,8 @@ func TestParseRouterComment(t *testing.T) { } func TestParseRouterMultipleComments(t *testing.T) { + t.Parallel() + comment := `/@Router /customer/get-wishlist/{wishlist_id} [get]` anotherComment := `/@Router /customer/get-the-wishlist/{wishlist_id} [post]` operation := NewOperation(nil) @@ -131,6 +146,8 @@ func TestParseRouterMultipleComments(t *testing.T) { } func TestParseRouterOnlySlash(t *testing.T) { + t.Parallel() + comment := `// @Router / [get]` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -141,6 +158,8 @@ func TestParseRouterOnlySlash(t *testing.T) { } func TestParseRouterCommentWithPlusSign(t *testing.T) { + t.Parallel() + comment := `/@Router /customer/get-wishlist/{proxy+} [post]` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -151,6 +170,8 @@ func TestParseRouterCommentWithPlusSign(t *testing.T) { } func TestParseRouterCommentWithColonSign(t *testing.T) { + t.Parallel() + comment := `/@Router /customer/get-wishlist/{wishlist_id}:move [post]` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -161,6 +182,8 @@ func TestParseRouterCommentWithColonSign(t *testing.T) { } func TestParseRouterCommentNoColonSignAtPathStartErr(t *testing.T) { + t.Parallel() + comment := `/@Router :customer/get-wishlist/{wishlist_id}:move [post]` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -168,6 +191,8 @@ func TestParseRouterCommentNoColonSignAtPathStartErr(t *testing.T) { } func TestParseRouterCommentMethodSeparationErr(t *testing.T) { + t.Parallel() + comment := `/@Router /api/{id}|,*[get` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -175,6 +200,8 @@ func TestParseRouterCommentMethodSeparationErr(t *testing.T) { } func TestParseRouterCommentMethodMissingErr(t *testing.T) { + t.Parallel() + comment := `/@Router /customer/get-wishlist/{wishlist_id}` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -182,6 +209,8 @@ func TestParseRouterCommentMethodMissingErr(t *testing.T) { } func TestParseResponseCommentWithObjectType(t *testing.T) { + t.Parallel() + comment := `@Success 200 {object} model.OrderRow "Error message, if code != 200` operation := NewOperation(nil) operation.parser.addTestType("model.OrderRow") @@ -208,6 +237,8 @@ func TestParseResponseCommentWithObjectType(t *testing.T) { } func TestParseResponseCommentWithNestedPrimitiveType(t *testing.T) { + t.Parallel() + comment := `@Success 200 {object} model.CommonHeader{data=string,data2=int} "Error message, if code != 200` operation := NewOperation(nil) @@ -250,6 +281,8 @@ func TestParseResponseCommentWithNestedPrimitiveType(t *testing.T) { } func TestParseResponseCommentWithNestedPrimitiveArrayType(t *testing.T) { + t.Parallel() + comment := `@Success 200 {object} model.CommonHeader{data=[]string,data2=[]int} "Error message, if code != 200` operation := NewOperation(nil) @@ -298,6 +331,8 @@ func TestParseResponseCommentWithNestedPrimitiveArrayType(t *testing.T) { } func TestParseResponseCommentWithNestedObjectType(t *testing.T) { + t.Parallel() + comment := `@Success 200 {object} model.CommonHeader{data=model.Payload,data2=model.Payload2} "Error message, if code != 200` operation := NewOperation(nil) operation.parser.addTestType("model.CommonHeader") @@ -341,6 +376,8 @@ func TestParseResponseCommentWithNestedObjectType(t *testing.T) { } func TestParseResponseCommentWithNestedArrayObjectType(t *testing.T) { + t.Parallel() + comment := `@Success 200 {object} model.CommonHeader{data=[]model.Payload,data2=[]model.Payload2} "Error message, if code != 200` operation := NewOperation(nil) @@ -391,6 +428,8 @@ func TestParseResponseCommentWithNestedArrayObjectType(t *testing.T) { } func TestParseResponseCommentWithNestedFields(t *testing.T) { + t.Parallel() + comment := `@Success 200 {object} model.CommonHeader{data1=int,data2=[]int,data3=model.Payload,data4=[]model.Payload} "Error message, if code != 200` operation := NewOperation(nil) @@ -446,6 +485,8 @@ func TestParseResponseCommentWithNestedFields(t *testing.T) { } func TestParseResponseCommentWithDeepNestedFields(t *testing.T) { + t.Parallel() + comment := `@Success 200 {object} model.CommonHeader{data1=int,data2=[]int,data3=model.Payload{data1=int,data2=model.DeepPayload},data4=[]model.Payload{data1=[]int,data2=[]model.DeepPayload}} "Error message, if code != 200` operation := NewOperation(nil) @@ -537,6 +578,8 @@ func TestParseResponseCommentWithDeepNestedFields(t *testing.T) { } func TestParseResponseCommentWithNestedArrayMapFields(t *testing.T) { + t.Parallel() + comment := `@Success 200 {object} []map[string]model.CommonHeader{data1=[]map[string]model.Payload,data2=map[string][]int} "Error message, if code != 200` operation := NewOperation(nil) @@ -597,6 +640,8 @@ func TestParseResponseCommentWithNestedArrayMapFields(t *testing.T) { } func TestParseResponseCommentWithObjectTypeInSameFile(t *testing.T) { + t.Parallel() + comment := `@Success 200 {object} testOwner "Error message, if code != 200"` operation := NewOperation(nil) @@ -636,6 +681,8 @@ func TestParseResponseCommentWithObjectTypeAnonymousField(t *testing.T) { } func TestParseResponseCommentWithObjectTypeErr(t *testing.T) { + t.Parallel() + comment := `@Success 200 {object} model.OrderRow "Error message, if code != 200"` operation := NewOperation(nil) @@ -646,6 +693,8 @@ func TestParseResponseCommentWithObjectTypeErr(t *testing.T) { } func TestParseResponseCommentWithArrayType(t *testing.T) { + t.Parallel() + comment := `@Success 200 {array} model.OrderRow "Error message, if code != 200` operation := NewOperation(nil) operation.parser.addTestType("model.OrderRow") @@ -675,6 +724,8 @@ func TestParseResponseCommentWithArrayType(t *testing.T) { } func TestParseResponseCommentWithBasicType(t *testing.T) { + t.Parallel() + comment := `@Success 200 {string} string "it's ok'"` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -695,6 +746,8 @@ func TestParseResponseCommentWithBasicType(t *testing.T) { } func TestParseResponseCommentWithBasicTypeAndCodes(t *testing.T) { + t.Parallel() + comment := `@Success 200,201,default {string} string "it's ok"` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -727,6 +780,8 @@ func TestParseResponseCommentWithBasicTypeAndCodes(t *testing.T) { } func TestParseEmptyResponseComment(t *testing.T) { + t.Parallel() + comment := `@Success 200 "it is ok"` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -745,6 +800,8 @@ func TestParseEmptyResponseComment(t *testing.T) { } func TestParseEmptyResponseCommentWithCodes(t *testing.T) { + t.Parallel() + comment := `@Success 200,201,default "it is ok"` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -769,13 +826,13 @@ func TestParseEmptyResponseCommentWithCodes(t *testing.T) { } func TestParseResponseCommentWithHeader(t *testing.T) { - comment := `@Success 200 "it's ok"` + t.Parallel() + operation := NewOperation(nil) - err := operation.ParseComment(comment, nil) + err := operation.ParseComment(`@Success 200 "it's ok"`, nil) assert.NoError(t, err, "ParseComment should not fail") - comment = `@Header 200 {string} Token "qwerty"` - err = operation.ParseComment(comment, nil) + err = operation.ParseComment(`@Header 200 {string} Token "qwerty"`, nil) assert.NoError(t, err, "ParseComment should not fail") b, err := json.MarshalIndent(operation, "", " ") @@ -796,17 +853,17 @@ func TestParseResponseCommentWithHeader(t *testing.T) { }` assert.Equal(t, expected, string(b)) - comment = `@Header 200 "Mallformed"` - err = operation.ParseComment(comment, nil) + err = operation.ParseComment(`@Header 200 "Mallformed"`, nil) assert.Error(t, err, "ParseComment should not fail") - comment = `@Header 200,asdsd {string} Token "qwerty"` - err = operation.ParseComment(comment, nil) + err = operation.ParseComment(`@Header 200,asdsd {string} Token "qwerty"`, nil) assert.Error(t, err, "ParseComment should not fail") } func TestParseResponseCommentWithHeaderForCodes(t *testing.T) { + t.Parallel() + operation := NewOperation(nil) comment := `@Success 200,201,default "it's ok"` @@ -875,9 +932,10 @@ func TestParseResponseCommentWithHeaderForCodes(t *testing.T) { } func TestParseEmptyResponseOnlyCode(t *testing.T) { - comment := `@Success 200` + t.Parallel() + operation := NewOperation(nil) - err := operation.ParseComment(comment, nil) + err := operation.ParseComment(`@Success 200`, nil) assert.NoError(t, err, "ParseComment should not fail") b, _ := json.MarshalIndent(operation, "", " ") @@ -893,6 +951,8 @@ func TestParseEmptyResponseOnlyCode(t *testing.T) { } func TestParseEmptyResponseOnlyCodes(t *testing.T) { + t.Parallel() + comment := `@Success 200,201,default` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -917,6 +977,8 @@ func TestParseEmptyResponseOnlyCodes(t *testing.T) { } func TestParseResponseCommentParamMissing(t *testing.T) { + t.Parallel() + operation := NewOperation(nil) paramLenErrComment := `@Success notIntCode` @@ -934,6 +996,8 @@ func TestParseResponseCommentParamMissing(t *testing.T) { // Test ParseParamComment func TestParseParamCommentByPathType(t *testing.T) { + t.Parallel() + comment := `@Param some_id path int true "Some ID"` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -956,6 +1020,8 @@ func TestParseParamCommentByPathType(t *testing.T) { // Test ParseParamComment Query Params func TestParseParamCommentBodyArray(t *testing.T) { + t.Parallel() + comment := `@Param names body []string true "Users List"` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -981,11 +1047,21 @@ func TestParseParamCommentBodyArray(t *testing.T) { assert.Equal(t, expected, string(b)) } +// Test ParseParamComment header Params +func TestParseParamCommentHeaderArray(t *testing.T) { + t.Parallel() + + comment := `@Param names header []string true "Users List"` + operation := NewOperation(nil) + assert.Error(t, operation.ParseComment(comment, nil)) +} + // Test ParseParamComment Query Params func TestParseParamCommentQueryArray(t *testing.T) { - comment := `@Param names query []string true "Users List"` + t.Parallel() + operation := NewOperation(nil) - err := operation.ParseComment(comment, nil) + err := operation.ParseComment(`@Param names query []string true "Users List"`, nil) assert.NoError(t, err) b, _ := json.MarshalIndent(operation, "", " ") @@ -1004,10 +1080,15 @@ func TestParseParamCommentQueryArray(t *testing.T) { ] }` assert.Equal(t, expected, string(b)) + + err = operation.ParseComment(`@Param names query []model.User true "Users List"`, nil) + assert.Error(t, err) } // Test TestParseParamCommentDefaultValue Query Params func TestParseParamCommentDefaultValue(t *testing.T) { + t.Parallel() + operation := NewOperation(nil) err := operation.ParseComment(`@Param names query string true "Users List" default(test)`, nil) assert.NoError(t, err) @@ -1031,6 +1112,8 @@ func TestParseParamCommentDefaultValue(t *testing.T) { // Test ParseParamComment Query Params func TestParseParamCommentQueryArrayFormat(t *testing.T) { + t.Parallel() + comment := `@Param names query []string true "Users List" collectionFormat(multi)` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -1056,6 +1139,8 @@ func TestParseParamCommentQueryArrayFormat(t *testing.T) { } func TestParseParamCommentByID(t *testing.T) { + t.Parallel() + comment := `@Param unsafe_id[lte] query int true "Unsafe query param"` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -1077,6 +1162,8 @@ func TestParseParamCommentByID(t *testing.T) { } func TestParseParamCommentByQueryType(t *testing.T) { + t.Parallel() + comment := `@Param some_id query int true "Some ID"` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -1098,6 +1185,8 @@ func TestParseParamCommentByQueryType(t *testing.T) { } func TestParseParamCommentByBodyType(t *testing.T) { + t.Parallel() + comment := `@Param some_id body model.OrderRow true "Some ID"` operation := NewOperation(nil) @@ -1123,6 +1212,8 @@ func TestParseParamCommentByBodyType(t *testing.T) { } func TestParseParamCommentByBodyTypeWithDeepNestedFields(t *testing.T) { + t.Parallel() + comment := `@Param body body model.CommonHeader{data=string,data2=int} true "test deep"` operation := NewOperation(nil) @@ -1168,6 +1259,8 @@ func TestParseParamCommentByBodyTypeWithDeepNestedFields(t *testing.T) { } func TestParseParamCommentByBodyTypeArrayOfPrimitiveGo(t *testing.T) { + t.Parallel() + comment := `@Param some_id body []int true "Some ID"` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -1194,6 +1287,8 @@ func TestParseParamCommentByBodyTypeArrayOfPrimitiveGo(t *testing.T) { } func TestParseParamCommentByBodyTypeArrayOfPrimitiveGoWithDeepNestedFields(t *testing.T) { + t.Parallel() + comment := `@Param body body []model.CommonHeader{data=string,data2=int} true "test deep"` operation := NewOperation(nil) operation.parser.addTestType("model.CommonHeader") @@ -1241,6 +1336,8 @@ func TestParseParamCommentByBodyTypeArrayOfPrimitiveGoWithDeepNestedFields(t *te } func TestParseParamCommentByBodyTypeErr(t *testing.T) { + t.Parallel() + comment := `@Param some_id body model.OrderRow true "Some ID"` operation := NewOperation(nil) operation.parser.addTestType("model.notexist") @@ -1250,6 +1347,8 @@ func TestParseParamCommentByBodyTypeErr(t *testing.T) { } func TestParseParamCommentByFormDataType(t *testing.T) { + t.Parallel() + comment := `@Param file formData file true "this is a test file"` operation := NewOperation(nil) @@ -1272,6 +1371,8 @@ func TestParseParamCommentByFormDataType(t *testing.T) { } func TestParseParamCommentByFormDataTypeUint64(t *testing.T) { + t.Parallel() + comment := `@Param file formData uint64 true "this is a test file"` operation := NewOperation(nil) @@ -1294,6 +1395,8 @@ func TestParseParamCommentByFormDataTypeUint64(t *testing.T) { } func TestParseParamCommentByNotSupportedType(t *testing.T) { + t.Parallel() + comment := `@Param some_id not_supported int true "Some ID"` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -1302,6 +1405,8 @@ func TestParseParamCommentByNotSupportedType(t *testing.T) { } func TestParseParamCommentNotMatch(t *testing.T) { + t.Parallel() + comment := `@Param some_id body mock true` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -1310,6 +1415,8 @@ func TestParseParamCommentNotMatch(t *testing.T) { } func TestParseParamCommentByEnums(t *testing.T) { + t.Parallel() + comment := `@Param some_id query string true "Some ID" Enums(A, B, C)` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -1421,6 +1528,8 @@ func TestParseParamCommentByEnums(t *testing.T) { } func TestParseParamCommentByMaxLength(t *testing.T) { + t.Parallel() + comment := `@Param some_id query string true "Some ID" MaxLength(10)` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -1449,6 +1558,8 @@ func TestParseParamCommentByMaxLength(t *testing.T) { } func TestParseParamCommentByMinLength(t *testing.T) { + t.Parallel() + comment := `@Param some_id query string true "Some ID" MinLength(10)` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -1477,6 +1588,8 @@ func TestParseParamCommentByMinLength(t *testing.T) { } func TestParseParamCommentByMinimum(t *testing.T) { + t.Parallel() + comment := `@Param some_id query int true "Some ID" Minimum(10)` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -1508,6 +1621,8 @@ func TestParseParamCommentByMinimum(t *testing.T) { } func TestParseParamCommentByMaximum(t *testing.T) { + t.Parallel() + comment := `@Param some_id query int true "Some ID" Maximum(10)` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -1540,6 +1655,8 @@ func TestParseParamCommentByMaximum(t *testing.T) { } func TestParseParamCommentByDefault(t *testing.T) { + t.Parallel() + comment := `@Param some_id query int true "Some ID" Default(10)` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -1562,6 +1679,8 @@ func TestParseParamCommentByDefault(t *testing.T) { } func TestParseParamArrayWithEnums(t *testing.T) { + t.Parallel() + comment := `@Param field query []string true "An enum collection" collectionFormat(csv) enums(also,valid)` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -1591,6 +1710,8 @@ func TestParseParamArrayWithEnums(t *testing.T) { } func TestParseIdComment(t *testing.T) { + t.Parallel() + comment := `@Id myOperationId` operation := NewOperation(nil) err := operation.ParseComment(comment, nil) @@ -1600,24 +1721,32 @@ func TestParseIdComment(t *testing.T) { } func TestFindTypeDefCoreLib(t *testing.T) { + t.Parallel() + spec, err := findTypeDef("net/http", "Request") assert.NoError(t, err) assert.NotNil(t, spec) } func TestFindTypeDefExternalPkg(t *testing.T) { + t.Parallel() + spec, err := findTypeDef("github.com/KyleBanks/depth", "Tree") assert.NoError(t, err) assert.NotNil(t, spec) } func TestFindTypeDefInvalidPkg(t *testing.T) { + t.Parallel() + spec, err := findTypeDef("does-not-exist", "foo") assert.Error(t, err) assert.Nil(t, spec) } func TestParseSecurityComment(t *testing.T) { + t.Parallel() + comment := `@Security OAuth2Implicit[read, write]` operation := NewOperation(nil) @@ -1639,6 +1768,8 @@ func TestParseSecurityComment(t *testing.T) { } func TestParseMultiDescription(t *testing.T) { + t.Parallel() + comment := `@Description line one` operation := NewOperation(nil) @@ -1660,6 +1791,8 @@ func TestParseMultiDescription(t *testing.T) { } func TestParseDescriptionMarkdown(t *testing.T) { + t.Parallel() + operation := NewOperation(nil) operation.parser.markdownFileDir = "example/markdown" @@ -1675,6 +1808,8 @@ func TestParseDescriptionMarkdown(t *testing.T) { } func TestParseSummary(t *testing.T) { + t.Parallel() + comment := `@summary line one` operation := NewOperation(nil) @@ -1687,6 +1822,8 @@ func TestParseSummary(t *testing.T) { } func TestParseDeprecationDescription(t *testing.T) { + t.Parallel() + comment := `@Deprecated` operation := NewOperation(nil) @@ -1699,6 +1836,7 @@ func TestParseDeprecationDescription(t *testing.T) { } func TestParseExtentions(t *testing.T) { + t.Parallel() // Fail if there are no args for attributes. { comment := `@x-amazon-apigateway-integration` @@ -1764,6 +1902,8 @@ func TestParseExtentions(t *testing.T) { } func TestFindInSlice(t *testing.T) { + t.Parallel() + assert.True(t, findInSlice([]string{"one", "two", "tree"}, "one")) assert.True(t, findInSlice([]string{"tree", "two", "one"}, "one")) assert.True(t, findInSlice([]string{"two", "one", "tree"}, "one")) @@ -1771,6 +1911,8 @@ func TestFindInSlice(t *testing.T) { } func TestParseResponseHeaderComment(t *testing.T) { + t.Parallel() + operation := NewOperation(nil) operation.Responses = &spec.Responses{} err := operation.ParseResponseComment(`default {string} string "other error"`, nil) @@ -1780,6 +1922,8 @@ func TestParseResponseHeaderComment(t *testing.T) { } func TestParseObjectSchema(t *testing.T) { + t.Parallel() + operation := NewOperation(nil) schema, err := operation.parseObjectSchema("interface{}", nil) @@ -1847,6 +1991,8 @@ func TestParseObjectSchema(t *testing.T) { } func TestParseCodeSamples(t *testing.T) { + t.Parallel() + t.Run("Find sample by file", func(t *testing.T) { comment := `@x-codeSamples file` operation := NewOperation(nil, SetCodeExampleFilesDirectory("testdata/code_examples")) diff --git a/parser.go b/parser.go index 10bd60b98..2493f78d0 100644 --- a/parser.go +++ b/parser.go @@ -104,7 +104,7 @@ type Parser struct { // New creates a new Parser with default properties. func New(options ...func(*Parser)) *Parser { - //parser.swagger.SecurityDefinitions = + // parser.swagger.SecurityDefinitions = parser := &Parser{ swagger: &spec.Swagger{ @@ -287,7 +287,7 @@ func (parser *Parser) ParseGeneralAPIInfo(mainAPIFile string) error { continue } comments := strings.Split(comment.Text(), "\n") - err := parseGeneralAPI(parser, comments) + err := parseGeneralAPIInfo(parser, comments) if err != nil { return err } @@ -296,7 +296,7 @@ func (parser *Parser) ParseGeneralAPIInfo(mainAPIFile string) error { return nil } -func parseGeneralAPI(parser *Parser, comments []string) error { +func parseGeneralAPIInfo(parser *Parser, comments []string) error { previousAttribute := "" // parsing classic meta data model @@ -379,71 +379,71 @@ func parseGeneralAPI(parser *Parser, comments []string) error { case "@securitydefinitions.basic": parser.swagger.SecurityDefinitions[value] = spec.BasicAuth() case "@securitydefinitions.apikey": - attrMap, _, _, err := extractSecurityAttribute(attribute, []string{"@in", "@name"}, comments[i+1:]) + attrMap, _, _, err := parseSecAttr(attribute, []string{"@in", "@name"}, comments[i+1:]) if err != nil { return err } parser.swagger.SecurityDefinitions[value] = spec.APIKeyAuth(attrMap["@name"], attrMap["@in"]) case "@securitydefinitions.oauth2.application": - attrMap, scopes, extensions, err := extractSecurityAttribute(attribute, []string{"@tokenurl"}, comments[i+1:]) + attrMap, scopes, extensions, err := parseSecAttr(attribute, []string{"@tokenurl"}, comments[i+1:]) if err != nil { return err } - parser.swagger.SecurityDefinitions[value] = securitySchemeOAuth2Application(attrMap["@tokenurl"], scopes, extensions) + parser.swagger.SecurityDefinitions[value] = secOAuth2Application(attrMap["@tokenurl"], scopes, extensions) case "@securitydefinitions.oauth2.implicit": - attrMap, scopes, extensions, err := extractSecurityAttribute(attribute, []string{"@authorizationurl"}, comments[i+1:]) + attrs, scopes, ext, err := parseSecAttr(attribute, []string{"@authorizationurl"}, comments[i+1:]) if err != nil { return err } - parser.swagger.SecurityDefinitions[value] = securitySchemeOAuth2Implicit(attrMap["@authorizationurl"], scopes, extensions) + parser.swagger.SecurityDefinitions[value] = secOAuth2Implicit(attrs["@authorizationurl"], scopes, ext) case "@securitydefinitions.oauth2.password": - attrMap, scopes, extensions, err := extractSecurityAttribute(attribute, []string{"@tokenurl"}, comments[i+1:]) + attrs, scopes, ext, err := parseSecAttr(attribute, []string{"@tokenurl"}, comments[i+1:]) if err != nil { return err } - parser.swagger.SecurityDefinitions[value] = securitySchemeOAuth2Password(attrMap["@tokenurl"], scopes, extensions) + parser.swagger.SecurityDefinitions[value] = secOAuth2Password(attrs["@tokenurl"], scopes, ext) case "@securitydefinitions.oauth2.accesscode": - attrMap, scopes, extensions, err := extractSecurityAttribute(attribute, []string{"@tokenurl", "@authorizationurl"}, comments[i+1:]) + attrs, scopes, ext, err := parseSecAttr(attribute, []string{"@tokenurl", "@authorizationurl"}, comments[i+1:]) if err != nil { return err } - parser.swagger.SecurityDefinitions[value] = securitySchemeOAuth2AccessToken(attrMap["@authorizationurl"], attrMap["@tokenurl"], scopes, extensions) + parser.swagger.SecurityDefinitions[value] = secOAuth2AccessToken(attrs["@authorizationurl"], attrs["@tokenurl"], scopes, ext) case "@query.collection.format": parser.collectionFormatInQuery = value default: prefixExtension := "@x-" - if len(attribute) > 5 { // Prefix extension + 1 char + 1 space + 1 char - if attribute[:len(prefixExtension)] == prefixExtension { - extExistsInSecurityDef := false - // for each security definition - for _, v := range parser.swagger.SecurityDefinitions { - // check if extension exists - _, extExistsInSecurityDef = v.VendorExtensible.Extensions.GetString(attribute[1:]) - // if it exists in at least one, then we stop iterating - if extExistsInSecurityDef { - break - } - } - // if it is present on security def, don't add it again + // Prefix extension + 1 char + 1 space + 1 char + if len(attribute) > 5 && attribute[:len(prefixExtension)] == prefixExtension { + extExistsInSecurityDef := false + // for each security definition + for _, v := range parser.swagger.SecurityDefinitions { + // check if extension exists + _, extExistsInSecurityDef = v.VendorExtensible.Extensions.GetString(attribute[1:]) + // if it exists in at least one, then we stop iterating if extExistsInSecurityDef { break } + } + // if it is present on security def, don't add it again + if extExistsInSecurityDef { + break + } - var valueJSON interface{} - split := strings.SplitAfter(commentLine, attribute+" ") - if len(split) < 2 { - return fmt.Errorf("annotation %s need a value", attribute) - } - extensionName := "x-" + strings.SplitAfter(attribute, prefixExtension)[1] - if err := json.Unmarshal([]byte(split[1]), &valueJSON); err != nil { - return fmt.Errorf("annotation %s need a valid json value", attribute) - } + var valueJSON interface{} + split := strings.SplitAfter(commentLine, attribute+" ") + if len(split) < 2 { + return fmt.Errorf("annotation %s need a value", attribute) + } + extensionName := "x-" + strings.SplitAfter(attribute, prefixExtension)[1] + err := json.Unmarshal([]byte(split[1]), &valueJSON) + if err != nil { + return fmt.Errorf("annotation %s need a valid json value", attribute) + } - if strings.Contains(extensionName, "logo") { - parser.swagger.Info.Extensions.Add(extensionName, valueJSON) - } else { - parser.swagger.AddExtension(extensionName, valueJSON) - } + if strings.Contains(extensionName, "logo") { + parser.swagger.Info.Extensions.Add(extensionName, valueJSON) + } else { + parser.swagger.AddExtension(extensionName, valueJSON) } } } @@ -466,7 +466,7 @@ func isGeneralAPIComment(comment *ast.CommentGroup) bool { return true } -func extractSecurityAttribute(context string, search []string, lines []string) (map[string]string, map[string]string, map[string]interface{}, error) { +func parseSecAttr(context string, search []string, lines []string) (map[string]string, map[string]string, map[string]interface{}, error) { attrMap := map[string]string{} scopes := map[string]string{} extensions := map[string]interface{}{} @@ -503,7 +503,7 @@ func extractSecurityAttribute(context string, search []string, lines []string) ( return attrMap, scopes, extensions, nil } -func securitySchemeOAuth2Application(tokenURL string, scopes map[string]string, +func secOAuth2Application(tokenURL string, scopes map[string]string, extensions map[string]interface{}) *spec.SecurityScheme { securityScheme := spec.OAuth2Application(tokenURL) securityScheme.VendorExtensible.Extensions = handleSecuritySchemaExtensions(extensions) @@ -514,7 +514,7 @@ func securitySchemeOAuth2Application(tokenURL string, scopes map[string]string, return securityScheme } -func securitySchemeOAuth2Implicit(authorizationURL string, scopes map[string]string, +func secOAuth2Implicit(authorizationURL string, scopes map[string]string, extensions map[string]interface{}) *spec.SecurityScheme { securityScheme := spec.OAuth2Implicit(authorizationURL) securityScheme.VendorExtensible.Extensions = handleSecuritySchemaExtensions(extensions) @@ -525,7 +525,7 @@ func securitySchemeOAuth2Implicit(authorizationURL string, scopes map[string]str return securityScheme } -func securitySchemeOAuth2Password(tokenURL string, scopes map[string]string, +func secOAuth2Password(tokenURL string, scopes map[string]string, extensions map[string]interface{}) *spec.SecurityScheme { securityScheme := spec.OAuth2Password(tokenURL) securityScheme.VendorExtensible.Extensions = handleSecuritySchemaExtensions(extensions) @@ -536,7 +536,7 @@ func securitySchemeOAuth2Password(tokenURL string, scopes map[string]string, return securityScheme } -func securitySchemeOAuth2AccessToken(authorizationURL, tokenURL string, +func secOAuth2AccessToken(authorizationURL, tokenURL string, scopes map[string]string, extensions map[string]interface{}) *spec.SecurityScheme { securityScheme := spec.OAuth2AccessToken(authorizationURL, tokenURL) securityScheme.VendorExtensible.Extensions = handleSecuritySchemaExtensions(extensions) @@ -613,39 +613,37 @@ func getSchemes(commentLine string) []string { func (parser *Parser) ParseRouterAPIInfo(fileName string, astFile *ast.File) error { for _, astDescription := range astFile.Decls { astDeclaration, ok := astDescription.(*ast.FuncDecl) - if ok { - if astDeclaration.Doc != nil && astDeclaration.Doc.List != nil { - // for per 'function' comment, create a new 'Operation' object - operation := NewOperation(parser, SetCodeExampleFilesDirectory(parser.codeExampleFilesDir)) - for _, comment := range astDeclaration.Doc.List { - err := operation.ParseComment(comment.Text, astFile) - if err != nil { - return fmt.Errorf("ParseComment error in file %s :%+v", fileName, err) - } + if ok && astDeclaration.Doc != nil && astDeclaration.Doc.List != nil { + // for per 'function' comment, create a new 'Operation' object + operation := NewOperation(parser, SetCodeExampleFilesDirectory(parser.codeExampleFilesDir)) + for _, comment := range astDeclaration.Doc.List { + err := operation.ParseComment(comment.Text, astFile) + if err != nil { + return fmt.Errorf("ParseComment error in file %s :%+v", fileName, err) } + } - for _, routeProperties := range operation.RouterProperties { - var pathItem spec.PathItem - var ok bool + for _, routeProperties := range operation.RouterProperties { + var pathItem spec.PathItem + var ok bool - pathItem, ok = parser.swagger.Paths.Paths[routeProperties.Path] - if !ok { - pathItem = spec.PathItem{} - } + pathItem, ok = parser.swagger.Paths.Paths[routeProperties.Path] + if !ok { + pathItem = spec.PathItem{} + } - // check if we already have a operation for this path and method - if hasRouteMethodOp(pathItem, routeProperties.HTTPMethod) { - err := fmt.Errorf("route %s %s is declared multiple times", routeProperties.HTTPMethod, routeProperties.Path) - if parser.Strict { - return err - } - Printf("warning: %s\n", err) + // check if we already have a operation for this path and method + if hasRouteMethodOp(pathItem, routeProperties.HTTPMethod) { + err := fmt.Errorf("route %s %s is declared multiple times", routeProperties.HTTPMethod, routeProperties.Path) + if parser.Strict { + return err } + Printf("warning: %s\n", err) + } - setRouteMethodOp(&pathItem, routeProperties.HTTPMethod, &operation.Operation) + setRouteMethodOp(&pathItem, routeProperties.HTTPMethod, &operation.Operation) - parser.swagger.Paths.Paths[routeProperties.Path] = pathItem - } + parser.swagger.Paths.Paths[routeProperties.Path] = pathItem } } } @@ -713,7 +711,8 @@ func (parser *Parser) getTypeSchema(typeName string, file *ast.File, ref bool) ( return PrimitiveSchema(TransToValidSchemeType(typeName)), nil } - if schemaType, err := convertFromSpecificToPrimitive(typeName); err == nil { + schemaType, err := convertFromSpecificToPrimitive(typeName) + if err == nil { return PrimitiveSchema(schemaType), nil } @@ -778,9 +777,11 @@ func (parser *Parser) renameSchema(name, pkgPath string) string { func (parser *Parser) getRefTypeSchema(typeSpecDef *TypeSpecDef, schema *Schema) *spec.Schema { _, ok := parser.outputSchemas[typeSpecDef] if !ok { - if existSchema, ok := parser.existSchemaNames[schema.Name]; ok { + existSchema, ok := parser.existSchemaNames[schema.Name] + if ok { // store the first one to be renamed after parsing over - if _, ok = parser.toBeRenamedSchemas[existSchema.Name]; !ok { + _, ok = parser.toBeRenamedSchemas[existSchema.Name] + if !ok { parser.toBeRenamedSchemas[existSchema.Name] = existSchema.PkgPath } // rename not the first one @@ -821,7 +822,8 @@ func (parser *Parser) ParseDefinition(typeSpecDef *TypeSpecDef) (*Schema, error) typeName := typeSpecDef.FullName() refTypeName := TypeDocName(typeName, typeSpecDef.TypeSpec) - if schema, ok := parser.parsedSchemas[typeSpecDef]; ok { + schema, ok := parser.parsedSchemas[typeSpecDef] + if ok { Println("Skipping '" + typeName + "', already parsed.") return schema, nil @@ -833,23 +835,25 @@ func (parser *Parser) ParseDefinition(typeSpecDef *TypeSpecDef) (*Schema, error) return &Schema{ Name: refTypeName, PkgPath: typeSpecDef.PkgPath, - Schema: PrimitiveSchema(OBJECT)}, + Schema: PrimitiveSchema(OBJECT), + }, ErrRecursiveParseStruct } parser.structStack = append(parser.structStack, typeSpecDef) Println("Generating " + typeName) - schema, err := parser.parseTypeExpr(typeSpecDef.File, typeSpecDef.TypeSpec.Type, false) + definition, err := parser.parseTypeExpr(typeSpecDef.File, typeSpecDef.TypeSpec.Type, false) if err != nil { return nil, err } - s := &Schema{Name: refTypeName, PkgPath: typeSpecDef.PkgPath, Schema: schema} + s := &Schema{Name: refTypeName, PkgPath: typeSpecDef.PkgPath, Schema: definition} parser.parsedSchemas[typeSpecDef] = s // update an empty schema as a result of recursion - if s2, ok := parser.outputSchemas[typeSpecDef]; ok { - parser.swagger.Definitions[s2.Name] = *schema + s2, ok := parser.outputSchemas[typeSpecDef] + if ok { + parser.swagger.Definitions[s2.Name] = *definition } return s, nil @@ -941,7 +945,8 @@ func (parser *Parser) parseStruct(file *ast.File, fields *ast.FieldList) (*spec. Type: []string{OBJECT}, Properties: properties, Required: required, - }}, nil + }, + }, nil } type structField struct { @@ -1090,7 +1095,8 @@ func (parser *Parser) getFieldName(field *ast.Field) (name string, schema *spec. if field.Tag != nil { // `json:"tag"` -> json:"tag" structTag := reflect.StructTag(strings.Replace(field.Tag.Value, "`", "", -1)) - if ignoreTag := structTag.Get("swaggerignore"); strings.EqualFold(ignoreTag, "true") { + ignoreTag := structTag.Get("swaggerignore") + if strings.EqualFold(ignoreTag, "true") { return "", nil, nil } @@ -1100,7 +1106,8 @@ func (parser *Parser) getFieldName(field *ast.Field) (name string, schema *spec. return "", nil, nil } - if typeTag := structTag.Get("swaggertype"); typeTag != "" { + typeTag := structTag.Get("swaggertype") + if typeTag != "" { parts := strings.Split(typeTag, ",") schema, err = BuildCustomSchema(parts) if err != nil { @@ -1150,10 +1157,8 @@ func (parser *Parser) parseFieldTag(field *ast.Field, types []string) (*structFi exampleTag := structTag.Get("example") if exampleTag != "" { - if strings.Contains(jsonTag, ",string") { - // then the example must be in string format - structField.exampleValue = exampleTag - } else { + structField.exampleValue = exampleTag + if !strings.Contains(jsonTag, ",string") { example, err := defineTypeOfExample(structField.schemaType, structField.arrayType, exampleTag) if err != nil { return nil, err diff --git a/parser_test.go b/parser_test.go index d2265b57b..6f16f9e35 100644 --- a/parser_test.go +++ b/parser_test.go @@ -2,6 +2,7 @@ package swag import ( "encoding/json" + "go/ast" goparser "go/parser" "go/token" "io/ioutil" @@ -19,23 +20,28 @@ const defaultParseDepth = 100 const mainAPIFile = "main.go" func TestNew(t *testing.T) { - swagMode = test New() } func TestSetMarkdownFileDirectory(t *testing.T) { + t.Parallel() + expected := "docs/markdown" p := New(SetMarkdownFileDirectory(expected)) assert.Equal(t, expected, p.markdownFileDir) } func TestSetCodeExamplesDirectory(t *testing.T) { + t.Parallel() + expected := "docs/examples" p := New(SetCodeExamplesDirectory(expected)) assert.Equal(t, expected, p.codeExampleFilesDir) } func TestSetStrict(t *testing.T) { + t.Parallel() + p := New() assert.Equal(t, false, p.Strict) @@ -44,6 +50,8 @@ func TestSetStrict(t *testing.T) { } func TestParser_ParseGeneralApiInfo(t *testing.T) { + t.Parallel() + expected := `{ "schemes": [ "http", @@ -141,6 +149,8 @@ func TestParser_ParseGeneralApiInfo(t *testing.T) { } func TestParser_ParseGeneralApiInfoTemplated(t *testing.T) { + t.Parallel() + expected := `{ "swagger": "2.0", "info": { @@ -222,8 +232,10 @@ func TestParser_ParseGeneralApiInfoTemplated(t *testing.T) { } func TestParser_ParseGeneralApiInfoExtensions(t *testing.T) { - // should be return an error because extension value is not a valid json - func() { + // should return an error because extension value is not a valid json + t.Run("Test invalid extension value", func(t *testing.T) { + t.Parallel() + expected := "annotation @x-google-endpoints need a valid json value" gopath := os.Getenv("GOPATH") assert.NotNil(t, gopath) @@ -232,10 +244,12 @@ func TestParser_ParseGeneralApiInfoExtensions(t *testing.T) { if assert.Error(t, err) { assert.Equal(t, expected, err.Error()) } - }() + }) + + // should return an error because extension don't have a value + t.Run("Test missing extension value", func(t *testing.T) { + t.Parallel() - // should be return an error because extension don't have a value - func() { expected := "annotation @x-google-endpoints need a value" gopath := os.Getenv("GOPATH") assert.NotNil(t, gopath) @@ -244,10 +258,12 @@ func TestParser_ParseGeneralApiInfoExtensions(t *testing.T) { if assert.Error(t, err) { assert.Equal(t, expected, err.Error()) } - }() + }) } func TestParser_ParseGeneralApiInfoWithOpsInSameFile(t *testing.T) { + t.Parallel() + expected := `{ "swagger": "2.0", "info": { @@ -271,6 +287,8 @@ func TestParser_ParseGeneralApiInfoWithOpsInSameFile(t *testing.T) { } func TestParser_ParseGeneralAPIInfoMarkdown(t *testing.T) { + t.Parallel() + p := New(SetMarkdownFileDirectory("testdata")) mainAPIFile := "testdata/markdown.go" err := p.ParseGeneralAPIInfo(mainAPIFile) @@ -302,27 +320,46 @@ func TestParser_ParseGeneralAPIInfoMarkdown(t *testing.T) { } func TestParser_ParseGeneralApiInfoFailed(t *testing.T) { + t.Parallel() + gopath := os.Getenv("GOPATH") assert.NotNil(t, gopath) p := New() assert.Error(t, p.ParseGeneralAPIInfo("testdata/noexist.go")) } +func TestParser_ParseGeneralAPIInfoCollectionFromat(t *testing.T) { + t.Parallel() + + parser := New() + assert.NoError(t, parseGeneralAPIInfo(parser, []string{ + "@query.collection.format csv", + })) + assert.Equal(t, parser.collectionFormatInQuery, "csv") + + assert.NoError(t, parseGeneralAPIInfo(parser, []string{ + "@query.collection.format tsv", + })) + assert.Equal(t, parser.collectionFormatInQuery, "tsv") +} + func TestParser_ParseGeneralAPITagDocs(t *testing.T) { + t.Parallel() + parser := New() - assert.Error(t, parseGeneralAPI(parser, []string{ + assert.Error(t, parseGeneralAPIInfo(parser, []string{ "@tag.name Test", "@tag.docs.description Best example documentation"})) parser = New() - err := parseGeneralAPI(parser, []string{ + err := parseGeneralAPIInfo(parser, []string{ "@tag.name test", "@tag.description A test Tag", "@tag.docs.url https://example.com", "@tag.docs.description Best example documentation"}) assert.NoError(t, err) - b, _ := json.MarshalIndent(parser.swagger.Tags, "", " ") + b, _ := json.MarshalIndent(parser.GetSwagger().Tags, "", " ") expected := `[ { "description": "A test Tag", @@ -338,108 +375,125 @@ func TestParser_ParseGeneralAPITagDocs(t *testing.T) { } func TestParser_ParseGeneralAPISecurity(t *testing.T) { - parser := New() - - assert.Error(t, parseGeneralAPI(parser, []string{ - "@securitydefinitions.apikey ApiKey"})) - - assert.Error(t, parseGeneralAPI(parser, []string{ - "@securitydefinitions.apikey ApiKey", - "@in header"})) - - assert.Error(t, parseGeneralAPI(parser, []string{ - "@securitydefinitions.apikey ApiKey", - "@name X-API-KEY"})) - - err := parseGeneralAPI(parser, []string{ - "@securitydefinitions.apikey ApiKey", - "@in header", - "@name X-API-KEY"}) - assert.NoError(t, err) - - b, _ := json.MarshalIndent(parser.swagger.SecurityDefinitions, "", " ") - expected := `{ + t.Run("ApiKey", func(t *testing.T) { + t.Parallel() + + parser := New() + assert.Error(t, parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.apikey ApiKey"})) + + assert.Error(t, parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.apikey ApiKey", + "@in header"})) + assert.Error(t, parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.apikey ApiKey", + "@name X-API-KEY"})) + + err := parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.apikey ApiKey", + "@in header", + "@name X-API-KEY"}) + assert.NoError(t, err) + + b, _ := json.MarshalIndent(parser.GetSwagger().SecurityDefinitions, "", " ") + expected := `{ "ApiKey": { "type": "apiKey", "name": "X-API-KEY", "in": "header" } }` - assert.Equal(t, expected, string(b)) - - parser = New() - assert.Error(t, parseGeneralAPI(parser, []string{ - "@securitydefinitions.oauth2.application OAuth2Application"})) - - err = parseGeneralAPI(parser, []string{ - "@securitydefinitions.oauth2.application OAuth2Application", - "@tokenUrl https://example.com/oauth/token"}) - assert.NoError(t, err) - b, _ = json.MarshalIndent(parser.swagger.SecurityDefinitions, "", " ") - expected = `{ + assert.Equal(t, expected, string(b)) + }) + + t.Run("OAuth2Application", func(t *testing.T) { + t.Parallel() + + parser := New() + assert.Error(t, parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.oauth2.application OAuth2Application"})) + + err := parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.oauth2.application OAuth2Application", + "@tokenUrl https://example.com/oauth/token"}) + assert.NoError(t, err) + b, _ := json.MarshalIndent(parser.GetSwagger().SecurityDefinitions, "", " ") + expected := `{ "OAuth2Application": { "type": "oauth2", "flow": "application", "tokenUrl": "https://example.com/oauth/token" } }` - assert.Equal(t, expected, string(b)) - - parser = New() - assert.Error(t, parseGeneralAPI(parser, []string{ - "@securitydefinitions.oauth2.implicit OAuth2Implicit"})) - - err = parseGeneralAPI(parser, []string{ - "@securitydefinitions.oauth2.implicit OAuth2Implicit", - "@authorizationurl https://example.com/oauth/authorize"}) - assert.NoError(t, err) - b, _ = json.MarshalIndent(parser.swagger.SecurityDefinitions, "", " ") - expected = `{ + assert.Equal(t, expected, string(b)) + }) + + t.Run("OAuth2Implicit", func(t *testing.T) { + t.Parallel() + + parser := New() + assert.Error(t, parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.oauth2.implicit OAuth2Implicit"})) + + err := parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.oauth2.implicit OAuth2Implicit", + "@authorizationurl https://example.com/oauth/authorize"}) + assert.NoError(t, err) + b, _ := json.MarshalIndent(parser.GetSwagger().SecurityDefinitions, "", " ") + expected := `{ "OAuth2Implicit": { "type": "oauth2", "flow": "implicit", "authorizationUrl": "https://example.com/oauth/authorize" } }` - assert.Equal(t, expected, string(b)) - - parser = New() - assert.Error(t, parseGeneralAPI(parser, []string{ - "@securitydefinitions.oauth2.password OAuth2Password"})) - - err = parseGeneralAPI(parser, []string{ - "@securitydefinitions.oauth2.password OAuth2Password", - "@tokenUrl https://example.com/oauth/token"}) - assert.NoError(t, err) - b, _ = json.MarshalIndent(parser.swagger.SecurityDefinitions, "", " ") - expected = `{ + assert.Equal(t, expected, string(b)) + }) + + t.Run("OAuth2Password", func(t *testing.T) { + t.Parallel() + + parser := New() + assert.Error(t, parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.oauth2.password OAuth2Password"})) + + err := parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.oauth2.password OAuth2Password", + "@tokenUrl https://example.com/oauth/token"}) + assert.NoError(t, err) + b, _ := json.MarshalIndent(parser.GetSwagger().SecurityDefinitions, "", " ") + expected := `{ "OAuth2Password": { "type": "oauth2", "flow": "password", "tokenUrl": "https://example.com/oauth/token" } }` - assert.Equal(t, expected, string(b)) - - parser = New() - assert.Error(t, parseGeneralAPI(parser, []string{ - "@securitydefinitions.oauth2.accessCode OAuth2AccessCode"})) - - assert.Error(t, parseGeneralAPI(parser, []string{ - "@securitydefinitions.oauth2.accessCode OAuth2AccessCode", - "@tokenUrl https://example.com/oauth/token"})) - - assert.Error(t, parseGeneralAPI(parser, []string{ - "@securitydefinitions.oauth2.accessCode OAuth2AccessCode", - "@authorizationurl https://example.com/oauth/authorize"})) - - err = parseGeneralAPI(parser, []string{ - "@securitydefinitions.oauth2.accessCode OAuth2AccessCode", - "@tokenUrl https://example.com/oauth/token", - "@authorizationurl https://example.com/oauth/authorize"}) - assert.NoError(t, err) - b, _ = json.MarshalIndent(parser.swagger.SecurityDefinitions, "", " ") - expected = `{ + assert.Equal(t, expected, string(b)) + }) + + t.Run("OAuth2AccessCode", func(t *testing.T) { + t.Parallel() + + parser := New() + assert.Error(t, parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.oauth2.accessCode OAuth2AccessCode"})) + + assert.Error(t, parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.oauth2.accessCode OAuth2AccessCode", + "@tokenUrl https://example.com/oauth/token"})) + + assert.Error(t, parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.oauth2.accessCode OAuth2AccessCode", + "@authorizationurl https://example.com/oauth/authorize"})) + + err := parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.oauth2.accessCode OAuth2AccessCode", + "@tokenUrl https://example.com/oauth/token", + "@authorizationurl https://example.com/oauth/authorize"}) + assert.NoError(t, err) + b, _ := json.MarshalIndent(parser.GetSwagger().SecurityDefinitions, "", " ") + expected := `{ "OAuth2AccessCode": { "type": "oauth2", "flow": "accessCode", @@ -447,17 +501,20 @@ func TestParser_ParseGeneralAPISecurity(t *testing.T) { "tokenUrl": "https://example.com/oauth/token" } }` - assert.Equal(t, expected, string(b)) + assert.Equal(t, expected, string(b)) - assert.Error(t, parseGeneralAPI(parser, []string{ - "@securitydefinitions.oauth2.accessCode OAuth2AccessCode", - "@tokenUrl https://example.com/oauth/token", - "@authorizationurl https://example.com/oauth/authorize", - "@scope.read,write Multiple scope"})) + assert.Error(t, parseGeneralAPIInfo(parser, []string{ + "@securitydefinitions.oauth2.accessCode OAuth2AccessCode", + "@tokenUrl https://example.com/oauth/token", + "@authorizationurl https://example.com/oauth/authorize", + "@scope.read,write Multiple scope"})) + }) } func TestGetAllGoFileInfo(t *testing.T) { + t.Parallel() + searchDir := "testdata/pet" p := New() @@ -468,6 +525,8 @@ func TestGetAllGoFileInfo(t *testing.T) { } func TestParser_ParseType(t *testing.T) { + t.Parallel() + searchDir := "testdata/simple/" p := New() @@ -483,12 +542,16 @@ func TestParser_ParseType(t *testing.T) { } func TestGetSchemes(t *testing.T) { + t.Parallel() + schemes := getSchemes("@schemes http https") expectedSchemes := []string{"http", "https"} assert.Equal(t, expectedSchemes, schemes) } func TestParseSimpleApi1(t *testing.T) { + t.Parallel() + expected, err := ioutil.ReadFile("testdata/simple/expected.json") assert.NoError(t, err) searchDir := "testdata/simple" @@ -502,6 +565,8 @@ func TestParseSimpleApi1(t *testing.T) { } func TestParseSimpleApi_ForSnakecase(t *testing.T) { + t.Parallel() + expected := `{ "swagger": "2.0", "info": { @@ -984,6 +1049,8 @@ func TestParseSimpleApi_ForSnakecase(t *testing.T) { } func TestParseSimpleApi_ForLowerCamelcase(t *testing.T) { + t.Parallel() + expected := `{ "swagger": "2.0", "info": { @@ -1438,6 +1505,8 @@ func TestParseSimpleApi_ForLowerCamelcase(t *testing.T) { } func TestParseStructComment(t *testing.T) { + t.Parallel() + expected := `{ "swagger": "2.0", "info": { @@ -1525,6 +1594,8 @@ func TestParseStructComment(t *testing.T) { } func TestParseNonExportedJSONFields(t *testing.T) { + t.Parallel() + expected := `{ "swagger": "2.0", "info": { @@ -1598,6 +1669,8 @@ func TestParseNonExportedJSONFields(t *testing.T) { } func TestParsePetApi(t *testing.T) { + t.Parallel() + expected := `{ "schemes": [ "http", @@ -1630,6 +1703,8 @@ func TestParsePetApi(t *testing.T) { } func TestParseModelAsTypeAlias(t *testing.T) { + t.Parallel() + expected := `{ "swagger": "2.0", "info": { @@ -1699,6 +1774,8 @@ func TestParseModelAsTypeAlias(t *testing.T) { } func TestParseComposition(t *testing.T) { + t.Parallel() + searchDir := "testdata/composition" p := New() err := p.ParseAPI(searchDir, mainAPIFile, defaultParseDepth) @@ -1714,6 +1791,8 @@ func TestParseComposition(t *testing.T) { } func TestParseImportAliases(t *testing.T) { + t.Parallel() + searchDir := "testdata/alias_import" p := New() err := p.ParseAPI(searchDir, mainAPIFile, defaultParseDepth) @@ -1728,6 +1807,8 @@ func TestParseImportAliases(t *testing.T) { } func TestParseNested(t *testing.T) { + t.Parallel() + searchDir := "testdata/nested" p := New() p.ParseDependency = true @@ -1742,6 +1823,8 @@ func TestParseNested(t *testing.T) { } func TestParseDuplicated(t *testing.T) { + t.Parallel() + searchDir := "testdata/duplicated" p := New() p.ParseDependency = true @@ -1750,6 +1833,8 @@ func TestParseDuplicated(t *testing.T) { } func TestParseDuplicatedOtherMethods(t *testing.T) { + t.Parallel() + searchDir := "testdata/duplicated2" p := New() p.ParseDependency = true @@ -1758,6 +1843,8 @@ func TestParseDuplicatedOtherMethods(t *testing.T) { } func TestParseConflictSchemaName(t *testing.T) { + t.Parallel() + searchDir := "testdata/conflict_name" p := New() p.ParseDependency = true @@ -1770,6 +1857,8 @@ func TestParseConflictSchemaName(t *testing.T) { } func TestParser_ParseStructArrayObject(t *testing.T) { + t.Parallel() + src := ` package api @@ -1838,6 +1927,8 @@ func Test(){ } func TestParser_ParseEmbededStruct(t *testing.T) { + t.Parallel() + src := ` package api @@ -1906,6 +1997,8 @@ type ResponseWrapper struct { } func TestParser_ParseStructPointerMembers(t *testing.T) { + t.Parallel() + src := ` package api @@ -1965,6 +2058,8 @@ func Test(){ } func TestParser_ParseStructMapMember(t *testing.T) { + t.Parallel() + src := ` package api @@ -2091,6 +2186,8 @@ func Test(){ } func TestParser_ParseRouterApiInfoErr(t *testing.T) { + t.Parallel() + src := ` package test @@ -2107,6 +2204,8 @@ func Test(){ } func TestParser_ParseRouterApiGet(t *testing.T) { + t.Parallel() + src := ` package test @@ -2130,6 +2229,8 @@ func Test(){ } func TestParser_ParseRouterApiPOST(t *testing.T) { + t.Parallel() + src := ` package test @@ -2153,6 +2254,8 @@ func Test(){ } func TestParser_ParseRouterApiDELETE(t *testing.T) { + t.Parallel() + src := ` package test @@ -2176,6 +2279,8 @@ func Test(){ } func TestParser_ParseRouterApiPUT(t *testing.T) { + t.Parallel() + src := ` package test @@ -2199,6 +2304,8 @@ func Test(){ } func TestParser_ParseRouterApiPATCH(t *testing.T) { + t.Parallel() + src := ` package test @@ -2222,6 +2329,8 @@ func Test(){ } func TestParser_ParseRouterApiHead(t *testing.T) { + t.Parallel() + src := ` package test @@ -2245,6 +2354,8 @@ func Test(){ } func TestParser_ParseRouterApiOptions(t *testing.T) { + t.Parallel() + src := ` package test @@ -2268,6 +2379,8 @@ func Test(){ } func TestParser_ParseRouterApiMultipleRoutesForSameFunction(t *testing.T) { + t.Parallel() + src := ` package test @@ -2297,6 +2410,8 @@ func Test(){ } func TestParser_ParseRouterApiMultiple(t *testing.T) { + t.Parallel() + src := ` package test @@ -2357,6 +2472,8 @@ func Test3(){ // } func TestParser_ParseRouterApiDuplicateRoute(t *testing.T) { + t.Parallel() + src := ` package test @@ -2380,6 +2497,8 @@ func Test2(){ } func TestApiParseTag(t *testing.T) { + t.Parallel() + searchDir := "testdata/tags" p := New(SetMarkdownFileDirectory(searchDir)) p.PropNamingStrategy = PascalCase @@ -2408,6 +2527,8 @@ func TestApiParseTag(t *testing.T) { } func TestApiParseTag_NonExistendTag(t *testing.T) { + t.Parallel() + searchDir := "testdata/tags_nonexistend_tag" p := New(SetMarkdownFileDirectory(searchDir)) p.PropNamingStrategy = PascalCase @@ -2416,6 +2537,8 @@ func TestApiParseTag_NonExistendTag(t *testing.T) { } func TestParseTagMarkdownDescription(t *testing.T) { + t.Parallel() + searchDir := "testdata/tags" p := New(SetMarkdownFileDirectory(searchDir)) p.PropNamingStrategy = PascalCase @@ -2435,6 +2558,8 @@ func TestParseTagMarkdownDescription(t *testing.T) { } func TestParseApiMarkdownDescription(t *testing.T) { + t.Parallel() + searchDir := "testdata/tags" p := New(SetMarkdownFileDirectory(searchDir)) p.PropNamingStrategy = PascalCase @@ -2449,6 +2574,8 @@ func TestParseApiMarkdownDescription(t *testing.T) { } func TestIgnoreInvalidPkg(t *testing.T) { + t.Parallel() + searchDir := "testdata/deps_having_invalid_pkg" p := New() if err := p.ParseAPI(searchDir, mainAPIFile, defaultParseDepth); err != nil { @@ -2457,6 +2584,8 @@ func TestIgnoreInvalidPkg(t *testing.T) { } func TestFixes432(t *testing.T) { + t.Parallel() + searchDir := "testdata/fixes-432" mainAPIFile := "cmd/main.go" @@ -2467,6 +2596,8 @@ func TestFixes432(t *testing.T) { } func TestParseOutsideDependencies(t *testing.T) { + t.Parallel() + searchDir := "testdata/pare_outside_dependencies" mainAPIFile := "cmd/main.go" @@ -2478,6 +2609,8 @@ func TestParseOutsideDependencies(t *testing.T) { } func TestParseStructParamCommentByQueryType(t *testing.T) { + t.Parallel() + src := ` package main @@ -2549,6 +2682,8 @@ func Fun() { } func TestParseRenamedStructDefinition(t *testing.T) { + t.Parallel() + src := ` package main @@ -2594,6 +2729,8 @@ func Fun() { } func TestPackagesDefinitions_CollectAstFileInit(t *testing.T) { + t.Parallel() + src := ` package main @@ -2617,6 +2754,8 @@ func Fun() { } func TestCollectAstFileMultipleTimes(t *testing.T) { + t.Parallel() + src := ` package main @@ -2640,6 +2779,8 @@ func Fun() { } func TestParseJSONFieldString(t *testing.T) { + t.Parallel() + expected := `{ "swagger": "2.0", "info": { @@ -2741,6 +2882,8 @@ func TestParseJSONFieldString(t *testing.T) { } func TestParseSwaggerignoreForEmbedded(t *testing.T) { + t.Parallel() + src := ` package main @@ -2784,63 +2927,369 @@ func Fun() { } func TestDefineTypeOfExample(t *testing.T) { - var example interface{} - var err error - example, err = defineTypeOfExample("string", "", "example") - assert.NoError(t, err) - assert.Equal(t, example.(string), "example") + t.Run("String type", func(t *testing.T) { + t.Parallel() - example, err = defineTypeOfExample("number", "", "12.34") - assert.NoError(t, err) - assert.Equal(t, example.(float64), 12.34) + example, err := defineTypeOfExample("string", "", "example") + assert.NoError(t, err) + assert.Equal(t, example.(string), "example") + }) - example, err = defineTypeOfExample("boolean", "", "true") - assert.NoError(t, err) - assert.Equal(t, example.(bool), true) + t.Run("Number type", func(t *testing.T) { + t.Parallel() - example, err = defineTypeOfExample("array", "", "one,two,three") - assert.Error(t, err) - assert.Nil(t, example) + example, err := defineTypeOfExample("number", "", "12.34") + assert.NoError(t, err) + assert.Equal(t, example.(float64), 12.34) - example, err = defineTypeOfExample("array", "string", "one,two,three") - assert.NoError(t, err) - arr := []string{} + _, err = defineTypeOfExample("number", "", "two") + assert.Error(t, err) + }) - for _, v := range example.([]interface{}) { - arr = append(arr, v.(string)) - } + t.Run("Integer type", func(t *testing.T) { + t.Parallel() - assert.Equal(t, arr, []string{"one", "two", "three"}) + example, err := defineTypeOfExample("integer", "", "12") + assert.NoError(t, err) + assert.Equal(t, example.(int), 12) - example, err = defineTypeOfExample("object", "", "key_one:one,key_two:two,key_three:three") - assert.Error(t, err) - assert.Nil(t, example) + _, err = defineTypeOfExample("integer", "", "two") + assert.Error(t, err) + }) - example, err = defineTypeOfExample("object", "string", "key_one,key_two,key_three") - assert.Error(t, err) - assert.Nil(t, example) + t.Run("Boolean type", func(t *testing.T) { + t.Parallel() - example, err = defineTypeOfExample("object", "oops", "key_one:one,key_two:two,key_three:three") - assert.Error(t, err) - assert.Nil(t, example) + example, err := defineTypeOfExample("boolean", "", "true") + assert.NoError(t, err) + assert.Equal(t, example.(bool), true) - example, err = defineTypeOfExample("object", "string", "key_one:one,key_two:two,key_three:three") - assert.NoError(t, err) - obj := map[string]string{} + _, err = defineTypeOfExample("boolean", "", "!true") + assert.Error(t, err) + }) - for k, v := range example.(map[string]interface{}) { - obj[k] = v.(string) - } + t.Run("Array type", func(t *testing.T) { + t.Parallel() - assert.Equal(t, obj, map[string]string{"key_one": "one", "key_two": "two", "key_three": "three"}) + example, err := defineTypeOfExample("array", "", "one,two,three") + assert.Error(t, err) + assert.Nil(t, example) - example, err = defineTypeOfExample("oops", "", "") - assert.Error(t, err) - assert.Nil(t, example) + example, err = defineTypeOfExample("array", "string", "one,two,three") + assert.NoError(t, err) + arr := []string{} + + for _, v := range example.([]interface{}) { + arr = append(arr, v.(string)) + } + + assert.Equal(t, arr, []string{"one", "two", "three"}) + }) + + t.Run("Object type", func(t *testing.T) { + t.Parallel() + + example, err := defineTypeOfExample("object", "", "key_one:one,key_two:two,key_three:three") + assert.Error(t, err) + assert.Nil(t, example) + + example, err = defineTypeOfExample("object", "string", "key_one,key_two,key_three") + assert.Error(t, err) + assert.Nil(t, example) + + example, err = defineTypeOfExample("object", "oops", "key_one:one,key_two:two,key_three:three") + assert.Error(t, err) + assert.Nil(t, example) + + example, err = defineTypeOfExample("object", "string", "key_one:one,key_two:two,key_three:three") + assert.NoError(t, err) + obj := map[string]string{} + + for k, v := range example.(map[string]interface{}) { + obj[k] = v.(string) + } + + assert.Equal(t, obj, map[string]string{"key_one": "one", "key_two": "two", "key_three": "three"}) + }) + + t.Run("Invalid type", func(t *testing.T) { + t.Parallel() + + example, err := defineTypeOfExample("oops", "", "") + assert.Error(t, err) + assert.Nil(t, example) + }) +} + +func TestParseFieldTag(t *testing.T) { + + t.Run("Example tag", func(t *testing.T) { + t.Parallel() + + parser := New() + + field, err := parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" example:"one"`, + }, + }, + []string{"string"}) + assert.NoError(t, err) + assert.Equal(t, &structField{ + schemaType: "string", + exampleValue: "one", + }, field) + + _, err = parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" example:"one"`, + }, + }, + []string{"float"}) + assert.Error(t, err) + }) + + t.Run("Format tag", func(t *testing.T) { + t.Parallel() + parser := New() + + field, err := parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" format:"csv"`, + }, + }, + []string{"string"}) + assert.NoError(t, err) + assert.Equal(t, &structField{ + schemaType: "string", + formatType: "csv", + }, field) + }) + + t.Run("Required tag", func(t *testing.T) { + t.Parallel() + parser := New() + + field, err := parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" binding:"required"`, + }, + }, + []string{"string"}) + assert.NoError(t, err) + assert.Equal(t, &structField{ + schemaType: "string", + isRequired: true, + }, field) + + field, err = parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" validate:"required"`, + }, + }, + []string{"string"}) + assert.NoError(t, err) + assert.Equal(t, &structField{ + schemaType: "string", + isRequired: true, + }, field) + + }) + + t.Run("Extensions tag", func(t *testing.T) { + + }) + + t.Run("Enums tag", func(t *testing.T) { + t.Parallel() + parser := New() + + field, err := parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" enums:"a,b,c"`, + }, + }, + []string{"string"}) + assert.NoError(t, err) + assert.Equal(t, &structField{ + schemaType: "string", + enums: []interface{}{"a", "b", "c"}, + }, field) + + _, err = parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" enums:"a,b,c"`, + }, + }, + []string{"float"}) + assert.Error(t, err) + }) + + t.Run("Default tag", func(t *testing.T) { + t.Parallel() + parser := New() + + field, err := parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" default:"pass"`, + }, + }, + []string{"string"}) + assert.NoError(t, err) + assert.Equal(t, &structField{ + schemaType: "string", + defaultValue: "pass", + }, field) + + _, err = parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" default:"pass"`, + }, + }, + []string{"float"}) + assert.Error(t, err) + }) + + t.Run("Numeric value", func(t *testing.T) { + t.Parallel() + parser := New() + + field, err := parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" maximum:"1"`, + }, + }, + []string{"integer"}) + assert.NoError(t, err) + max := float64(1) + assert.Equal(t, &structField{ + schemaType: "integer", + maximum: &max, + }, field) + + _, err = parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" maximum:"one"`, + }, + }, + []string{"integer"}) + assert.Error(t, err) + + field, err = parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" maximum:"1"`, + }, + }, + []string{"number"}) + assert.NoError(t, err) + max = float64(1) + assert.Equal(t, &structField{ + schemaType: "number", + maximum: &max, + }, field) + + _, err = parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" maximum:"one"`, + }, + }, + []string{"number"}) + assert.Error(t, err) + + field, err = parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" minimum:"1"`, + }, + }, + []string{"integer"}) + assert.NoError(t, err) + min := float64(1) + assert.Equal(t, &structField{ + schemaType: "integer", + minimum: &min, + }, field) + + _, err = parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" minimum:"one"`, + }, + }, + []string{"integer"}) + assert.Error(t, err) + + }) + + t.Run("String value", func(t *testing.T) { + t.Parallel() + parser := New() + + field, err := parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" maxLength:"1"`, + }, + }, + []string{"string"}) + assert.NoError(t, err) + max := int64(1) + assert.Equal(t, &structField{ + schemaType: "string", + maxLength: &max, + }, field) + + _, err = parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" maxLength:"one"`, + }, + }, + []string{"string"}) + assert.Error(t, err) + + field, err = parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" minLength:"1"`, + }, + }, + []string{"string"}) + assert.NoError(t, err) + min := int64(1) + assert.Equal(t, &structField{ + schemaType: "string", + minLength: &min, + }, field) + + _, err = parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" minLength:"one"`, + }, + }, + []string{"string"}) + assert.Error(t, err) + }) } func TestSetRouteMethodOp(t *testing.T) { + t.Parallel() + op := spec.NewOperation("dummy") // choosing to test each method explicitly instead of table driven to avoid reliance on helpers @@ -2875,6 +3324,8 @@ func TestSetRouteMethodOp(t *testing.T) { } func TestHasRouteMethodOp(t *testing.T) { + t.Parallel() + pathItem := spec.PathItem{} // assert that an invalid http method produces false @@ -2913,6 +3364,8 @@ func (fs *mockFS) IsDir() bool { } func TestParser_Skip(t *testing.T) { + t.Parallel() + parser := New() parser.ParseVendor = true diff --git a/schema_test.go b/schema_test.go index 3d684e5fb..dbb7b614c 100644 --- a/schema_test.go +++ b/schema_test.go @@ -9,6 +9,8 @@ import ( ) func TestValidDataType(t *testing.T) { + t.Parallel() + assert.NoError(t, CheckSchemaType(STRING)) assert.NoError(t, CheckSchemaType(NUMBER)) assert.NoError(t, CheckSchemaType(INTEGER)) @@ -20,6 +22,8 @@ func TestValidDataType(t *testing.T) { } func TestTransToValidSchemeType(t *testing.T) { + t.Parallel() + assert.Equal(t, TransToValidSchemeType("uint"), INTEGER) assert.Equal(t, TransToValidSchemeType("uint32"), INTEGER) assert.Equal(t, TransToValidSchemeType("uint64"), INTEGER) @@ -28,10 +32,13 @@ func TestTransToValidSchemeType(t *testing.T) { assert.Equal(t, TransToValidSchemeType("string"), STRING) // should accept any type, due to user defined types - TransToValidSchemeType("oops") + other := "oops" + assert.Equal(t, TransToValidSchemeType(other), other) } func TestTransToValidCollectionFormat(t *testing.T) { + t.Parallel() + assert.Equal(t, TransToValidCollectionFormat("csv"), "csv") assert.Equal(t, TransToValidCollectionFormat("multi"), "multi") assert.Equal(t, TransToValidCollectionFormat("pipes"), "pipes") @@ -43,6 +50,7 @@ func TestTransToValidCollectionFormat(t *testing.T) { } func TestIsGolangPrimitiveType(t *testing.T) { + t.Parallel() assert.Equal(t, IsGolangPrimitiveType("uint"), true) assert.Equal(t, IsGolangPrimitiveType("int"), true) @@ -64,6 +72,7 @@ func TestIsGolangPrimitiveType(t *testing.T) { } func TestIsSimplePrimitiveType(t *testing.T) { + t.Parallel() assert.Equal(t, IsSimplePrimitiveType("string"), true) assert.Equal(t, IsSimplePrimitiveType("number"), true) @@ -74,6 +83,8 @@ func TestIsSimplePrimitiveType(t *testing.T) { } func TestBuildCustomSchema(t *testing.T) { + t.Parallel() + var schema *spec.Schema var err error @@ -121,6 +132,8 @@ func TestBuildCustomSchema(t *testing.T) { } func TestIsNumericType(t *testing.T) { + t.Parallel() + assert.Equal(t, IsNumericType(INTEGER), true) assert.Equal(t, IsNumericType(NUMBER), true) @@ -128,6 +141,8 @@ func TestIsNumericType(t *testing.T) { } func TestTypeDocName(t *testing.T) { + t.Parallel() + expected := "a/package" assert.Equal(t, expected, TypeDocName(expected, nil))