Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: extract type by node + add schema fuzz test #2138

Merged
merged 1 commit into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ examples/**/go.work
examples/**/go.work.sum
testdata/**/go.work
testdata/**/go.work.sum
go-runtime/schema/testdata/test/test.go

# Leaving old _ftl for now to avoid old stuff getting checked in
**/testdata/**/_ftl
Expand Down
7 changes: 6 additions & 1 deletion backend/schema/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,12 @@ func ValidateModule(module *Module) error {
})

merr = cleanErrors(merr)
SortModuleDecls(module)
return errors.Join(merr...)
}

// SortModuleDecls sorts the declarations in a module.
func SortModuleDecls(module *Module) {
sort.SliceStable(module.Decls, func(i, j int) bool {
iDecl := module.Decls[i]
jDecl := module.Decls[j]
Expand All @@ -382,7 +388,6 @@ func ValidateModule(module *Module) error {
}
return iPriority < jPriority
})
return errors.Join(merr...)
}

// getDeclSortingPriority (used for schema sorting) is pulled out into it's own switch so the Go sumtype check will fail
Expand Down
2 changes: 1 addition & 1 deletion buildengine/build_go_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ func TestExternalType(t *testing.T) {
}
testBuild(t, bctx, "", "unsupported external type", []assertion{
assertBuildProtoErrors(
`unsupported external type "time.Month"; see FTL docs on using external types: tbd54566975.github.io/ftl/docs/reference/externaltypes/`,
`unsupported type "time.Month" for field "Month"`,
`unsupported external type "time.Month"; see FTL docs on using external types: tbd54566975.github.io/ftl/docs/reference/externaltypes/`,
`unsupported response type "ftl/external.ExternalResponse"`,
),
})
Expand Down
103 changes: 56 additions & 47 deletions go-runtime/compile/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,57 +193,66 @@ func TestExtractModuleSchemaTwo(t *testing.T) {
}
actual := schema.Normalise(r.Module)
expected := `module two {
typealias ExternalAlias Any
+typemap kotlin "com.foo.bar.NonFTLType"
+typemap go "github.com/TBD54566975/ftl/go-runtime/compile/testdata.lib.NonFTLType"

typealias TransitiveAlias Any
+typemap go "github.com/TBD54566975/ftl/go-runtime/compile/testdata.lib.NonFTLType"

export enum TwoEnum: String {
Blue = "Blue"
Green = "Green"
Red = "Red"
}
typealias ExplicitAliasAlias Any
+typemap kotlin "com.foo.bar.NonFTLType"
+typemap go "github.com/TBD54566975/ftl/go-runtime/compile/testdata.lib.NonFTLType"

export enum TypeEnum {
Exported two.Exported
List [String]
Scalar String
WithoutDirective two.WithoutDirective
}
typealias ExplicitAliasType Any
+typemap kotlin "com.foo.bar.NonFTLType"
+typemap go "github.com/TBD54566975/ftl/go-runtime/compile/testdata.lib.NonFTLType"

export data Exported {
}
typealias TransitiveAliasAlias Any
+typemap go "github.com/TBD54566975/ftl/go-runtime/compile/testdata.lib.NonFTLType"

data NonFtlField {
field two.ExternalAlias
transitive two.TransitiveAlias
}
typealias TransitiveAliasType Any
+typemap go "github.com/TBD54566975/ftl/go-runtime/compile/testdata.lib.NonFTLType"

export data Payload<T> {
body T
}
export enum TwoEnum: String {
Blue = "Blue"
Green = "Green"
Red = "Red"
}

export data User {
name String
}
export enum TypeEnum {
Exported two.Exported
List [String]
Scalar String
WithoutDirective two.WithoutDirective
}

export data UserResponse {
user two.User
}
export data Exported {
}

export data WithoutDirective {
}
data NonFtlField {
explicitType two.ExplicitAliasType
explicitAlias two.ExplicitAliasAlias
transitiveType two.TransitiveAliasType
transitiveAlias two.TransitiveAliasAlias
}

export verb callsTwo(two.Payload<String>) two.Payload<String>
+calls two.two
export data Payload<T> {
body T
}

export verb returnsUser(Unit) two.UserResponse
export data User {
name String
}

export verb two(two.Payload<String>) two.Payload<String>
}
`
export data UserResponse {
user two.User
}

export data WithoutDirective {
}

export verb callsTwo(two.Payload<String>) two.Payload<String>
+calls two.two

export verb returnsUser(Unit) two.UserResponse

export verb two(two.Payload<String>) two.Payload<String>
}
`
assert.Equal(t, normaliseString(expected), normaliseString(actual.String()))
}

Expand Down Expand Up @@ -536,7 +545,7 @@ func TestErrorReporting(t *testing.T) {
`25:2-10: unsupported type "error" for field "BadParam"`,
`28:2-17: unsupported type "uint64" for field "AnotherBadParam"`,
`31:3-3: unexpected directive "ftl:export" attached for verb, did you mean to use '//ftl:verb export' instead?`,
`37:36-36: unsupported request type "ftl/failing.Request"`,
`37:40-40: unsupported request type "ftl/failing.Request"`,
`37:50-50: unsupported response type "ftl/failing.Response"`,
`38:16-29: call first argument must be a function but is an unresolved reference to lib.OtherFunc`,
`38:16-29: call first argument must be a function in an ftl module`,
Expand All @@ -551,12 +560,12 @@ func TestErrorReporting(t *testing.T) {
`60:1-2: first parameter must be context.Context`,
`60:18-18: unsupported response type "ftl/failing.Response"`,
`65:1-2: must have at most two results (<type>, error)`,
`65:41-41: unsupported request type "ftl/failing.Request"`,
`65:45-45: unsupported request type "ftl/failing.Request"`,
`70:1-2: must at least return an error`,
`70:36-36: unsupported request type "ftl/failing.Request"`,
`74:35-35: unsupported request type "ftl/failing.Request"`,
`70:40-40: unsupported request type "ftl/failing.Request"`,
`74:39-39: unsupported request type "ftl/failing.Request"`,
`74:48-48: must return an error but is ftl/failing.Response`,
`79:41-41: unsupported request type "ftl/failing.Request"`,
`79:45-45: unsupported request type "ftl/failing.Request"`,
`79:63-63: must return an error but is string`,
`79:63-63: second result must not be ftl.Unit`,
// `86:1-2: duplicate declaration of "WrongResponse" at 79:6`, TODO: fix this
Expand All @@ -580,8 +589,8 @@ func TestErrorReporting(t *testing.T) {
// failing/child/child.go
expectedChild := []string{
`9:2-6: unsupported type "uint64" for field "Body"`,
`14:2-2: unsupported external type "github.com/TBD54566975/ftl/go-runtime/compile/testdata.lib.NonFTLType"; see FTL docs on using external types: tbd54566975.github.io/ftl/docs/reference/externaltypes/`,
`14:2-7: unsupported type "github.com/TBD54566975/ftl/go-runtime/compile/testdata.NonFTLType" for field "Field"`,
`14:8-8: unsupported external type "github.com/TBD54566975/ftl/go-runtime/compile/testdata.NonFTLType"; see FTL docs on using external types: tbd54566975.github.io/ftl/docs/reference/externaltypes/`,
`19:6-41: declared type github.com/blah.lib.NonFTLType in typemap does not match native type github.com/TBD54566975/ftl/go-runtime/compile/testdata.lib.NonFTLType`,
`24:6-6: multiple Go type mappings found for "ftl/failing/child.MultipleMappings"`,
`34:2-13: enum variant "SameVariant" conflicts with existing enum variant of "EnumVariantConflictParent" at "196:2"`,
Expand Down
16 changes: 12 additions & 4 deletions go-runtime/compile/testdata/go/two/two.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,20 @@ func ReturnsUser(ctx context.Context) (UserResponse, error) {

//ftl:data
type NonFTLField struct {
Field ExternalAlias
Transitive TransitiveAlias
ExplicitType ExplicitAliasType
ExplicitAlias ExplicitAliasAlias
TransitiveType TransitiveAliasType
TransitiveAlias TransitiveAliasAlias
}

//ftl:typealias
//ftl:typemap kotlin "com.foo.bar.NonFTLType"
type ExternalAlias lib.NonFTLType
type ExplicitAliasType lib.NonFTLType

type TransitiveAlias lib.NonFTLType
//ftl:typealias
//ftl:typemap kotlin "com.foo.bar.NonFTLType"
type ExplicitAliasAlias = lib.NonFTLType

type TransitiveAliasType lib.NonFTLType

type TransitiveAliasAlias = lib.NonFTLType
Loading
Loading