Validate parameter types in method signature
This commit is contained in:
parent
26feb0e0e3
commit
f799a284b1
7 changed files with 587 additions and 488 deletions
|
@ -2,7 +2,7 @@ coverage:
|
|||
status:
|
||||
project:
|
||||
default:
|
||||
target: 65%
|
||||
target: 70%
|
||||
threshold: 5%
|
||||
patch:
|
||||
default:
|
||||
|
|
|
@ -13,15 +13,20 @@ import (
|
|||
|
||||
// GenerateMongoRepository generates mongodb repository
|
||||
func GenerateMongoRepository(packageName string, structModel code.Struct, intf code.Interface) (string, error) {
|
||||
repositorySpec, err := spec.ParseRepositoryInterface(structModel, intf)
|
||||
if err != nil {
|
||||
return "", err
|
||||
var methodSpecs []spec.MethodSpec
|
||||
for _, method := range intf.Methods {
|
||||
methodSpec, err := spec.ParseInterfaceMethod(structModel, method)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
methodSpecs = append(methodSpecs, methodSpec)
|
||||
}
|
||||
|
||||
generator := mongoRepositoryGenerator{
|
||||
PackageName: packageName,
|
||||
StructModel: structModel,
|
||||
RepositorySpec: repositorySpec,
|
||||
PackageName: packageName,
|
||||
StructModel: structModel,
|
||||
InterfaceName: intf.Name,
|
||||
MethodSpecs: methodSpecs,
|
||||
}
|
||||
|
||||
output, err := generator.Generate()
|
||||
|
@ -33,9 +38,10 @@ func GenerateMongoRepository(packageName string, structModel code.Struct, intf c
|
|||
}
|
||||
|
||||
type mongoRepositoryGenerator struct {
|
||||
PackageName string
|
||||
StructModel code.Struct
|
||||
RepositorySpec spec.RepositorySpec
|
||||
PackageName string
|
||||
StructModel code.Struct
|
||||
InterfaceName string
|
||||
MethodSpecs []spec.MethodSpec
|
||||
}
|
||||
|
||||
func (g mongoRepositoryGenerator) Generate() (string, error) {
|
||||
|
@ -44,7 +50,7 @@ func (g mongoRepositoryGenerator) Generate() (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
for _, method := range g.RepositorySpec.Methods {
|
||||
for _, method := range g.MethodSpecs {
|
||||
if err := g.generateMethod(buffer, method); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -66,7 +72,7 @@ func (g mongoRepositoryGenerator) generateBaseContent(buffer *bytes.Buffer) erro
|
|||
|
||||
tmplData := mongoBaseTemplateData{
|
||||
PackageName: g.PackageName,
|
||||
InterfaceName: g.RepositorySpec.InterfaceName,
|
||||
InterfaceName: g.InterfaceName,
|
||||
StructName: g.structName(),
|
||||
}
|
||||
|
||||
|
@ -167,5 +173,5 @@ func (g mongoRepositoryGenerator) generateFindImplementation(operation spec.Find
|
|||
}
|
||||
|
||||
func (g mongoRepositoryGenerator) structName() string {
|
||||
return g.RepositorySpec.InterfaceName + "Mongo"
|
||||
return g.InterfaceName + "Mongo"
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ func TestGenerateMongoRepository(t *testing.T) {
|
|||
Name: "FindByGenderNot",
|
||||
Params: []code.Param{
|
||||
{Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Name: "gender", Type: code.SimpleType("int")},
|
||||
{Name: "gender", Type: code.SimpleType("Gender")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
|
@ -220,7 +220,7 @@ func (r *UserRepositoryMongo) FindByIDAndUsername(ctx context.Context, arg0 prim
|
|||
return &entity, nil
|
||||
}
|
||||
|
||||
func (r *UserRepositoryMongo) FindByGenderNot(ctx context.Context, arg0 int) ([]*UserModel, error) {
|
||||
func (r *UserRepositoryMongo) FindByGenderNot(ctx context.Context, arg0 Gender) ([]*UserModel, error) {
|
||||
cursor, err := r.collection.Find(ctx, bson.M{
|
||||
"gender": bson.M{"$ne": arg0},
|
||||
})
|
||||
|
|
35
internal/spec/errors.go
Normal file
35
internal/spec/errors.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package spec
|
||||
|
||||
// ParsingError is an error from parsing interface methods
|
||||
type ParsingError string
|
||||
|
||||
func (err ParsingError) Error() string {
|
||||
switch err {
|
||||
case UnknownOperationError:
|
||||
return "unknown operation"
|
||||
case UnsupportedNameError:
|
||||
return "method name is not supported"
|
||||
case InvalidQueryError:
|
||||
return "invalid query"
|
||||
case InvalidParamError:
|
||||
return "parameters do not match the query"
|
||||
case UnsupportedReturnError:
|
||||
return "this type of return is not supported"
|
||||
case ContextParamRequiredError:
|
||||
return "context parameter is required"
|
||||
case StructFieldNotFoundError:
|
||||
return "struct field not found"
|
||||
}
|
||||
return string(err)
|
||||
}
|
||||
|
||||
// parsing error constants
|
||||
const (
|
||||
UnknownOperationError ParsingError = "ERROR_UNKNOWN_OPERATION"
|
||||
UnsupportedNameError ParsingError = "ERROR_UNSUPPORTED"
|
||||
InvalidQueryError ParsingError = "ERROR_INVALID_QUERY"
|
||||
InvalidParamError ParsingError = "ERROR_INVALID_PARAM"
|
||||
UnsupportedReturnError ParsingError = "ERROR_INVALID_RETURN"
|
||||
ContextParamRequiredError ParsingError = "ERROR_CONTEXT_PARAM_REQUIRED"
|
||||
StructFieldNotFoundError ParsingError = "ERROR_STRUCT_FIELD_NOT_FOUND"
|
||||
)
|
|
@ -15,12 +15,6 @@ const (
|
|||
QueryModeMany QueryMode = "MANY"
|
||||
)
|
||||
|
||||
// RepositorySpec is a specification generated from the repository interface
|
||||
type RepositorySpec struct {
|
||||
InterfaceName string
|
||||
Methods []MethodSpec
|
||||
}
|
||||
|
||||
// MethodSpec is a method specification inside repository specification
|
||||
type MethodSpec struct {
|
||||
Name string
|
||||
|
|
|
@ -1,59 +1,40 @@
|
|||
package spec
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/fatih/camelcase"
|
||||
"github.com/sunboyy/repogen/internal/code"
|
||||
)
|
||||
|
||||
// ParseRepositoryInterface returns repository spec from declared repository interface
|
||||
func ParseRepositoryInterface(structModel code.Struct, intf code.Interface) (RepositorySpec, error) {
|
||||
parser := repositoryInterfaceParser{
|
||||
// ParseInterfaceMethod returns repository method spec from declared interface method
|
||||
func ParseInterfaceMethod(structModel code.Struct, method code.Method) (MethodSpec, error) {
|
||||
parser := interfaceMethodParser{
|
||||
StructModel: structModel,
|
||||
Interface: intf,
|
||||
Method: method,
|
||||
}
|
||||
|
||||
return parser.Parse()
|
||||
}
|
||||
|
||||
type repositoryInterfaceParser struct {
|
||||
type interfaceMethodParser struct {
|
||||
StructModel code.Struct
|
||||
Interface code.Interface
|
||||
Method code.Method
|
||||
}
|
||||
|
||||
func (p repositoryInterfaceParser) Parse() (RepositorySpec, error) {
|
||||
repositorySpec := RepositorySpec{
|
||||
InterfaceName: p.Interface.Name,
|
||||
}
|
||||
|
||||
for _, method := range p.Interface.Methods {
|
||||
methodSpec, err := p.parseMethod(method)
|
||||
if err != nil {
|
||||
return RepositorySpec{}, err
|
||||
}
|
||||
repositorySpec.Methods = append(repositorySpec.Methods, methodSpec)
|
||||
}
|
||||
|
||||
return repositorySpec, nil
|
||||
}
|
||||
|
||||
func (p repositoryInterfaceParser) parseMethod(method code.Method) (MethodSpec, error) {
|
||||
methodNameTokens := camelcase.Split(method.Name)
|
||||
func (p interfaceMethodParser) Parse() (MethodSpec, error) {
|
||||
methodNameTokens := camelcase.Split(p.Method.Name)
|
||||
switch methodNameTokens[0] {
|
||||
case "Find":
|
||||
return p.parseFindMethod(method, methodNameTokens[1:])
|
||||
return p.parseFindMethod(methodNameTokens[1:])
|
||||
}
|
||||
return MethodSpec{}, errors.New("method name not supported")
|
||||
return MethodSpec{}, UnknownOperationError
|
||||
}
|
||||
|
||||
func (p repositoryInterfaceParser) parseFindMethod(method code.Method, tokens []string) (MethodSpec, error) {
|
||||
func (p interfaceMethodParser) parseFindMethod(tokens []string) (MethodSpec, error) {
|
||||
if len(tokens) == 0 {
|
||||
return MethodSpec{}, errors.New("method name not supported")
|
||||
return MethodSpec{}, UnsupportedNameError
|
||||
}
|
||||
|
||||
mode, err := p.extractFindReturns(method.Returns)
|
||||
mode, err := p.extractFindReturns(p.Method.Returns)
|
||||
if err != nil {
|
||||
return MethodSpec{}, err
|
||||
}
|
||||
|
@ -63,14 +44,14 @@ func (p repositoryInterfaceParser) parseFindMethod(method code.Method, tokens []
|
|||
return MethodSpec{}, err
|
||||
}
|
||||
|
||||
if querySpec.NumberOfArguments()+1 != len(method.Params) {
|
||||
return MethodSpec{}, errors.New("method parameter not supported")
|
||||
if err := p.validateMethodSignature(querySpec); err != nil {
|
||||
return MethodSpec{}, err
|
||||
}
|
||||
|
||||
return MethodSpec{
|
||||
Name: method.Name,
|
||||
Params: method.Params,
|
||||
Returns: method.Returns,
|
||||
Name: p.Method.Name,
|
||||
Params: p.Method.Params,
|
||||
Returns: p.Method.Returns,
|
||||
Operation: FindOperation{
|
||||
Mode: mode,
|
||||
Query: querySpec,
|
||||
|
@ -78,13 +59,13 @@ func (p repositoryInterfaceParser) parseFindMethod(method code.Method, tokens []
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (p repositoryInterfaceParser) extractFindReturns(returns []code.Type) (QueryMode, error) {
|
||||
func (p interfaceMethodParser) extractFindReturns(returns []code.Type) (QueryMode, error) {
|
||||
if len(returns) != 2 {
|
||||
return "", errors.New("method return not supported")
|
||||
return "", UnsupportedReturnError
|
||||
}
|
||||
|
||||
if returns[1] != code.SimpleType("error") {
|
||||
return "", errors.New("method return not supported")
|
||||
return "", UnsupportedReturnError
|
||||
}
|
||||
|
||||
pointerType, ok := returns[0].(code.PointerType)
|
||||
|
@ -93,7 +74,7 @@ func (p repositoryInterfaceParser) extractFindReturns(returns []code.Type) (Quer
|
|||
if simpleType == code.SimpleType(p.StructModel.Name) {
|
||||
return QueryModeOne, nil
|
||||
}
|
||||
return "", fmt.Errorf("invalid return type %s", pointerType.Code())
|
||||
return "", UnsupportedReturnError
|
||||
}
|
||||
|
||||
arrayType, ok := returns[0].(code.ArrayType)
|
||||
|
@ -104,16 +85,16 @@ func (p repositoryInterfaceParser) extractFindReturns(returns []code.Type) (Quer
|
|||
if simpleType == code.SimpleType(p.StructModel.Name) {
|
||||
return QueryModeMany, nil
|
||||
}
|
||||
return "", fmt.Errorf("invalid return type %s", pointerType.Code())
|
||||
return "", UnsupportedReturnError
|
||||
}
|
||||
}
|
||||
|
||||
return "", errors.New("method return not supported")
|
||||
return "", UnsupportedReturnError
|
||||
}
|
||||
|
||||
func (p repositoryInterfaceParser) parseQuery(tokens []string) (QuerySpec, error) {
|
||||
func (p interfaceMethodParser) parseQuery(tokens []string) (QuerySpec, error) {
|
||||
if len(tokens) == 0 {
|
||||
return QuerySpec{}, errors.New("method name not supported")
|
||||
return QuerySpec{}, InvalidQueryError
|
||||
}
|
||||
|
||||
if len(tokens) == 1 && tokens[0] == "All" {
|
||||
|
@ -128,7 +109,7 @@ func (p repositoryInterfaceParser) parseQuery(tokens []string) (QuerySpec, error
|
|||
}
|
||||
|
||||
if tokens[0] == "And" || tokens[0] == "Or" {
|
||||
return QuerySpec{}, errors.New("method name not supported")
|
||||
return QuerySpec{}, InvalidQueryError
|
||||
}
|
||||
|
||||
var operator Operator
|
||||
|
@ -137,6 +118,8 @@ func (p repositoryInterfaceParser) parseQuery(tokens []string) (QuerySpec, error
|
|||
for _, token := range tokens {
|
||||
if token != "And" && token != "Or" {
|
||||
aggregatedToken = append(aggregatedToken, token)
|
||||
} else if len(aggregatedToken) == 0 {
|
||||
return QuerySpec{}, InvalidQueryError
|
||||
} else if token == "And" && operator != OperatorOr {
|
||||
operator = OperatorAnd
|
||||
predicates = append(predicates, aggregatedToken.ToPredicate())
|
||||
|
@ -146,13 +129,40 @@ func (p repositoryInterfaceParser) parseQuery(tokens []string) (QuerySpec, error
|
|||
predicates = append(predicates, aggregatedToken.ToPredicate())
|
||||
aggregatedToken = predicateToken{}
|
||||
} else {
|
||||
return QuerySpec{}, errors.New("method name contains ambiguous query")
|
||||
return QuerySpec{}, InvalidQueryError
|
||||
}
|
||||
}
|
||||
if len(aggregatedToken) == 0 {
|
||||
return QuerySpec{}, errors.New("method name not supported")
|
||||
return QuerySpec{}, InvalidQueryError
|
||||
}
|
||||
predicates = append(predicates, aggregatedToken.ToPredicate())
|
||||
|
||||
return QuerySpec{Operator: operator, Predicates: predicates}, nil
|
||||
}
|
||||
|
||||
func (p interfaceMethodParser) validateMethodSignature(querySpec QuerySpec) error {
|
||||
contextType := code.ExternalType{PackageAlias: "context", Name: "Context"}
|
||||
if len(p.Method.Params) == 0 || p.Method.Params[0].Type != contextType {
|
||||
return ContextParamRequiredError
|
||||
}
|
||||
|
||||
if querySpec.NumberOfArguments()+1 != len(p.Method.Params) {
|
||||
return InvalidParamError
|
||||
}
|
||||
|
||||
currentParamIndex := 1
|
||||
for _, predicate := range querySpec.Predicates {
|
||||
structField, ok := p.StructModel.Fields.ByName(predicate.Field)
|
||||
if !ok {
|
||||
return StructFieldNotFoundError
|
||||
}
|
||||
|
||||
if structField.Type != p.Method.Params[currentParamIndex].Type {
|
||||
return InvalidParamError
|
||||
}
|
||||
|
||||
currentParamIndex++
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -8,224 +8,191 @@ import (
|
|||
"github.com/sunboyy/repogen/internal/spec"
|
||||
)
|
||||
|
||||
type TestCase struct {
|
||||
Name string
|
||||
Interface code.Interface
|
||||
ExpectedOutput spec.RepositorySpec
|
||||
}
|
||||
|
||||
func TestParseRepositoryInterface(t *testing.T) {
|
||||
testTable := []TestCase{
|
||||
var structModel = code.Struct{
|
||||
Name: "UserModel",
|
||||
Fields: code.StructFields{
|
||||
{
|
||||
Name: "interface spec",
|
||||
Interface: code.Interface{
|
||||
Name: "UserRepository",
|
||||
},
|
||||
ExpectedOutput: spec.RepositorySpec{
|
||||
InterfaceName: "UserRepository",
|
||||
},
|
||||
Name: "ID",
|
||||
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
||||
},
|
||||
{
|
||||
Name: "PhoneNumber",
|
||||
Type: code.SimpleType("string"),
|
||||
},
|
||||
{
|
||||
Name: "Gender",
|
||||
Type: code.SimpleType("Gender"),
|
||||
},
|
||||
{
|
||||
Name: "City",
|
||||
Type: code.SimpleType("string"),
|
||||
},
|
||||
{
|
||||
Name: "Age",
|
||||
Type: code.SimpleType("int"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
type ParseInterfaceMethodTestCase struct {
|
||||
Name string
|
||||
Method code.Method
|
||||
ExpectedOutput spec.MethodSpec
|
||||
}
|
||||
|
||||
func TestParseInterfaceMethod(t *testing.T) {
|
||||
testTable := []ParseInterfaceMethodTestCase{
|
||||
{
|
||||
Name: "FindOneByArg method",
|
||||
Interface: code.Interface{
|
||||
Name: "UserRepository",
|
||||
Methods: []code.Method{
|
||||
{
|
||||
Name: "FindOneByID",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
Method: code.Method{
|
||||
Name: "FindOneByID",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.RepositorySpec{
|
||||
InterfaceName: "UserRepository",
|
||||
Methods: []spec.MethodSpec{
|
||||
{
|
||||
Name: "FindOneByID",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeOne,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "ID", Comparator: spec.ComparatorEqual},
|
||||
}},
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.MethodSpec{
|
||||
Name: "FindOneByID",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeOne,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "ID", Comparator: spec.ComparatorEqual},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "FindOneByMultiWordArg method",
|
||||
Interface: code.Interface{
|
||||
Name: "UserRepository",
|
||||
Methods: []code.Method{
|
||||
{
|
||||
Name: "FindOneByPhoneNumber",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
Method: code.Method{
|
||||
Name: "FindOneByPhoneNumber",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.RepositorySpec{
|
||||
InterfaceName: "UserRepository",
|
||||
Methods: []spec.MethodSpec{
|
||||
{
|
||||
Name: "FindOneByPhoneNumber",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeOne,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "PhoneNumber", Comparator: spec.ComparatorEqual},
|
||||
}},
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.MethodSpec{
|
||||
Name: "FindOneByPhoneNumber",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeOne,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "PhoneNumber", Comparator: spec.ComparatorEqual},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "FindByArg method",
|
||||
Interface: code.Interface{
|
||||
Name: "UserRepository",
|
||||
Methods: []code.Method{
|
||||
{
|
||||
Name: "FindByCity",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
Method: code.Method{
|
||||
Name: "FindByCity",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.RepositorySpec{
|
||||
InterfaceName: "UserRepository",
|
||||
Methods: []spec.MethodSpec{
|
||||
{
|
||||
Name: "FindByCity",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "City", Comparator: spec.ComparatorEqual},
|
||||
}},
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.MethodSpec{
|
||||
Name: "FindByCity",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "City", Comparator: spec.ComparatorEqual},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "FindAll method",
|
||||
Interface: code.Interface{
|
||||
Name: "UserRepository",
|
||||
Methods: []code.Method{
|
||||
{
|
||||
Name: "FindAll",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
Method: code.Method{
|
||||
Name: "FindAll",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.RepositorySpec{
|
||||
InterfaceName: "UserRepository",
|
||||
Methods: []spec.MethodSpec{
|
||||
{
|
||||
Name: "FindAll",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.MethodSpec{
|
||||
Name: "FindAll",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "FindByArgAndArg method",
|
||||
Interface: code.Interface{
|
||||
Name: "UserRepository",
|
||||
Methods: []code.Method{
|
||||
{
|
||||
Name: "FindByCityAndGender",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
{Type: code.SimpleType("Gender")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
Method: code.Method{
|
||||
Name: "FindByCityAndGender",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
{Type: code.SimpleType("Gender")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.RepositorySpec{
|
||||
InterfaceName: "UserRepository",
|
||||
Methods: []spec.MethodSpec{
|
||||
{
|
||||
Name: "FindByCityAndGender",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
{Type: code.SimpleType("Gender")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{
|
||||
Operator: spec.OperatorAnd,
|
||||
Predicates: []spec.Predicate{
|
||||
{Field: "City", Comparator: spec.ComparatorEqual},
|
||||
{Field: "Gender", Comparator: spec.ComparatorEqual},
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.MethodSpec{
|
||||
Name: "FindByCityAndGender",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
{Type: code.SimpleType("Gender")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{
|
||||
Operator: spec.OperatorAnd,
|
||||
Predicates: []spec.Predicate{
|
||||
{Field: "City", Comparator: spec.ComparatorEqual},
|
||||
{Field: "Gender", Comparator: spec.ComparatorEqual},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -233,46 +200,36 @@ func TestParseRepositoryInterface(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Name: "FindByArgOrArg method",
|
||||
Interface: code.Interface{
|
||||
Name: "UserRepository",
|
||||
Methods: []code.Method{
|
||||
{
|
||||
Name: "FindByCityOrGender",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
{Type: code.SimpleType("Gender")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
Method: code.Method{
|
||||
Name: "FindByCityOrGender",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
{Type: code.SimpleType("Gender")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.RepositorySpec{
|
||||
InterfaceName: "UserRepository",
|
||||
Methods: []spec.MethodSpec{
|
||||
{
|
||||
Name: "FindByCityOrGender",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
{Type: code.SimpleType("Gender")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{
|
||||
Operator: spec.OperatorOr,
|
||||
Predicates: []spec.Predicate{
|
||||
{Field: "City", Comparator: spec.ComparatorEqual},
|
||||
{Field: "Gender", Comparator: spec.ComparatorEqual},
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.MethodSpec{
|
||||
Name: "FindByCityOrGender",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
{Type: code.SimpleType("Gender")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{
|
||||
Operator: spec.OperatorOr,
|
||||
Predicates: []spec.Predicate{
|
||||
{Field: "City", Comparator: spec.ComparatorEqual},
|
||||
{Field: "Gender", Comparator: spec.ComparatorEqual},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -280,240 +237,164 @@ func TestParseRepositoryInterface(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Name: "FindByArgNot method",
|
||||
Interface: code.Interface{
|
||||
Name: "UserRepository",
|
||||
Methods: []code.Method{
|
||||
{
|
||||
Name: "FindByCityNot",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
Method: code.Method{
|
||||
Name: "FindByCityNot",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.RepositorySpec{
|
||||
InterfaceName: "UserRepository",
|
||||
Methods: []spec.MethodSpec{
|
||||
{
|
||||
Name: "FindByCityNot",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "City", Comparator: spec.ComparatorNot},
|
||||
}},
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.MethodSpec{
|
||||
Name: "FindByCityNot",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "City", Comparator: spec.ComparatorNot},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "FindByArgLessThan method",
|
||||
Interface: code.Interface{
|
||||
Name: "UserRepository",
|
||||
Methods: []code.Method{
|
||||
{
|
||||
Name: "FindByAgeLessThan",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
Method: code.Method{
|
||||
Name: "FindByAgeLessThan",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("int")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.RepositorySpec{
|
||||
InterfaceName: "UserRepository",
|
||||
Methods: []spec.MethodSpec{
|
||||
{
|
||||
Name: "FindByAgeLessThan",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "Age", Comparator: spec.ComparatorLessThan},
|
||||
}},
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.MethodSpec{
|
||||
Name: "FindByAgeLessThan",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("int")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "Age", Comparator: spec.ComparatorLessThan},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "FindByArgLessThanEqual method",
|
||||
Interface: code.Interface{
|
||||
Name: "UserRepository",
|
||||
Methods: []code.Method{
|
||||
{
|
||||
Name: "FindByAgeLessThanEqual",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
Method: code.Method{
|
||||
Name: "FindByAgeLessThanEqual",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("int")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.RepositorySpec{
|
||||
InterfaceName: "UserRepository",
|
||||
Methods: []spec.MethodSpec{
|
||||
{
|
||||
Name: "FindByAgeLessThanEqual",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "Age", Comparator: spec.ComparatorLessThanEqual},
|
||||
}},
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.MethodSpec{
|
||||
Name: "FindByAgeLessThanEqual",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("int")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "Age", Comparator: spec.ComparatorLessThanEqual},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "FindByArgGreaterThan method",
|
||||
Interface: code.Interface{
|
||||
Name: "UserRepository",
|
||||
Methods: []code.Method{
|
||||
{
|
||||
Name: "FindByAgeGreaterThan",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
Method: code.Method{
|
||||
Name: "FindByAgeGreaterThan",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("int")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.RepositorySpec{
|
||||
InterfaceName: "UserRepository",
|
||||
Methods: []spec.MethodSpec{
|
||||
{
|
||||
Name: "FindByAgeGreaterThan",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "Age", Comparator: spec.ComparatorGreaterThan},
|
||||
}},
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.MethodSpec{
|
||||
Name: "FindByAgeGreaterThan",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("int")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "Age", Comparator: spec.ComparatorGreaterThan},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "FindByArgGreaterThanEqual method",
|
||||
Interface: code.Interface{
|
||||
Name: "UserRepository",
|
||||
Methods: []code.Method{
|
||||
{
|
||||
Name: "FindByAgeGreaterThanEqual",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
Method: code.Method{
|
||||
Name: "FindByAgeGreaterThanEqual",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("int")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.RepositorySpec{
|
||||
InterfaceName: "UserRepository",
|
||||
Methods: []spec.MethodSpec{
|
||||
{
|
||||
Name: "FindByAgeGreaterThanEqual",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "Age", Comparator: spec.ComparatorGreaterThanEqual},
|
||||
}},
|
||||
},
|
||||
},
|
||||
ExpectedOutput: spec.MethodSpec{
|
||||
Name: "FindByAgeGreaterThanEqual",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("int")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
Operation: spec.FindOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||
{Field: "Age", Comparator: spec.ComparatorGreaterThanEqual},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
structModel := code.Struct{
|
||||
Name: "UserModel",
|
||||
Fields: code.StructFields{
|
||||
{
|
||||
Name: "ID",
|
||||
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
||||
},
|
||||
{
|
||||
Name: "PhoneNumber",
|
||||
Type: code.SimpleType("string"),
|
||||
},
|
||||
{
|
||||
Name: "Gender",
|
||||
Type: code.SimpleType("Gender"),
|
||||
},
|
||||
{
|
||||
Name: "City",
|
||||
Type: code.SimpleType("string"),
|
||||
},
|
||||
{
|
||||
Name: "Age",
|
||||
Type: code.SimpleType("int"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testTable {
|
||||
t.Run(testCase.Name, func(t *testing.T) {
|
||||
actualSpec, err := spec.ParseRepositoryInterface(structModel, testCase.Interface)
|
||||
actualSpec, err := spec.ParseInterfaceMethod(structModel, testCase.Method)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Error = %s", err)
|
||||
|
@ -524,3 +405,176 @@ func TestParseRepositoryInterface(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
type ParseInterfaceMethodInvalidTestCase struct {
|
||||
Name string
|
||||
Method code.Method
|
||||
ExpectedError error
|
||||
}
|
||||
|
||||
func TestParseInterfaceMethodInvalid(t *testing.T) {
|
||||
testTable := []ParseInterfaceMethodInvalidTestCase{
|
||||
{
|
||||
Name: "unknown operation",
|
||||
Method: code.Method{
|
||||
Name: "SearchByID",
|
||||
},
|
||||
ExpectedError: spec.UnknownOperationError,
|
||||
},
|
||||
{
|
||||
Name: "unsupported find method name",
|
||||
Method: code.Method{
|
||||
Name: "Find",
|
||||
},
|
||||
ExpectedError: spec.UnsupportedNameError,
|
||||
},
|
||||
{
|
||||
Name: "invalid number of returns",
|
||||
Method: code.Method{
|
||||
Name: "FindOneByID",
|
||||
Returns: []code.Type{
|
||||
code.SimpleType("UserModel"),
|
||||
code.SimpleType("int"),
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.UnsupportedReturnError,
|
||||
},
|
||||
{
|
||||
Name: "unsupported return values from find method",
|
||||
Method: code.Method{
|
||||
Name: "FindOneByID",
|
||||
Returns: []code.Type{
|
||||
code.SimpleType("UserModel"),
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.UnsupportedReturnError,
|
||||
},
|
||||
{
|
||||
Name: "error return not provided",
|
||||
Method: code.Method{
|
||||
Name: "FindOneByID",
|
||||
Returns: []code.Type{
|
||||
code.SimpleType("UserModel"),
|
||||
code.SimpleType("int"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.UnsupportedReturnError,
|
||||
},
|
||||
{
|
||||
Name: "misplaced operator token (leftmost)",
|
||||
Method: code.Method{
|
||||
Name: "FindByAndGender",
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.InvalidQueryError,
|
||||
},
|
||||
{
|
||||
Name: "misplaced operator token (rightmost)",
|
||||
Method: code.Method{
|
||||
Name: "FindByGenderAnd",
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.InvalidQueryError,
|
||||
},
|
||||
{
|
||||
Name: "misplaced operator token (double operator)",
|
||||
Method: code.Method{
|
||||
Name: "FindByGenderAndAndCity",
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.InvalidQueryError,
|
||||
},
|
||||
{
|
||||
Name: "ambiguous query",
|
||||
Method: code.Method{
|
||||
Name: "FindByGenderAndCityOrAge",
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.InvalidQueryError,
|
||||
},
|
||||
{
|
||||
Name: "no context parameter",
|
||||
Method: code.Method{
|
||||
Name: "FindByGender",
|
||||
Params: []code.Param{
|
||||
{Type: code.SimpleType("Gender")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.ContextParamRequiredError,
|
||||
},
|
||||
{
|
||||
Name: "mismatched number of parameters",
|
||||
Method: code.Method{
|
||||
Name: "FindByCountry",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.InvalidParamError,
|
||||
},
|
||||
{
|
||||
Name: "struct field not found",
|
||||
Method: code.Method{
|
||||
Name: "FindByCountry",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.StructFieldNotFoundError,
|
||||
},
|
||||
{
|
||||
Name: "mismatched method parameter type",
|
||||
Method: code.Method{
|
||||
Name: "FindByGender",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("string")},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.InvalidParamError,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testTable {
|
||||
t.Run(testCase.Name, func(t *testing.T) {
|
||||
_, err := spec.ParseInterfaceMethod(structModel, testCase.Method)
|
||||
|
||||
if err != testCase.ExpectedError {
|
||||
t.Errorf("\nExpected = %v\nReceived = %v", testCase.ExpectedError, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue