Skip to content

Commit

Permalink
feat: extract type by node + add schema fuzz test (#2138)
Browse files Browse the repository at this point in the history
this change also allows us to support `type Foo = external.Bar` aliases
  • Loading branch information
worstell authored Jul 24, 2024
1 parent 7483d86 commit 4275025
Show file tree
Hide file tree
Showing 20 changed files with 1,086 additions and 359 deletions.
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

0 comments on commit 4275025

Please sign in to comment.