diff --git a/integration/actions.go b/integration/actions.go index a3b4e7688..e2136d381 100644 --- a/integration/actions.go +++ b/integration/actions.go @@ -57,17 +57,33 @@ func GitInit() Action { func CopyModule(module string) Action { return Chain( CopyDir(module, module), - func(t testing.TB, ic TestContext) { - root := filepath.Join(ic.workDir, module) - // TODO: Load the module configuration from the module itself and use that to determine the language-specific stuff. - if _, err := os.Stat(filepath.Join(root, "go.mod")); err == nil { - err := ftlexec.Command(ic, log.Debug, root, "go", "mod", "edit", "-replace", "github.com/TBD54566975/ftl="+ic.RootDir).RunBuffered(ic) - assert.NoError(t, err) - } - }, + editGoMod(module), + ) +} + +// Copy a module from the testdata directory to the working directory +// This will always use the specified language regardless of the language under test +// +// Ensures that any language-specific local modifications are made correctly, +// such as Go module file replace directives for FTL. +func CopyModuleWithLanguage(module string, language string) Action { + return Chain( + CopyDir(filepath.Join("..", language, module), module), + editGoMod(module), ) } +func editGoMod(module string) func(t testing.TB, ic TestContext) { + return func(t testing.TB, ic TestContext) { + root := filepath.Join(ic.workDir, module) + // TODO: Load the module configuration from the module itself and use that to determine the language-specific stuff. + if _, err := os.Stat(filepath.Join(root, "go.mod")); err == nil { + err := ftlexec.Command(ic, log.Debug, root, "go", "mod", "edit", "-replace", "github.com/TBD54566975/ftl="+ic.RootDir).RunBuffered(ic) + assert.NoError(t, err) + } + } +} + // SetEnv sets an environment variable for the duration of the test. // // Note that the FTL controller will already be running. diff --git a/jvm-runtime/ftl-runtime/kotlin/deployment/src/main/java/xyz/block/ftl/kotlin/deployment/KotlinCodeGenerator.java b/jvm-runtime/ftl-runtime/kotlin/deployment/src/main/java/xyz/block/ftl/kotlin/deployment/KotlinCodeGenerator.java index 32baba3a0..a06d7d2fa 100644 --- a/jvm-runtime/ftl-runtime/kotlin/deployment/src/main/java/xyz/block/ftl/kotlin/deployment/KotlinCodeGenerator.java +++ b/jvm-runtime/ftl-runtime/kotlin/deployment/src/main/java/xyz/block/ftl/kotlin/deployment/KotlinCodeGenerator.java @@ -212,7 +212,7 @@ private TypeName toKotlinTypeName(Type type, Map typeAliasMap) { } else if (type.hasBool()) { return new ClassName("kotlin", "Boolean"); } else if (type.hasFloat()) { - return new ClassName("kotlin", "Boolean"); + return new ClassName("kotlin", "Double"); } else if (type.hasBytes()) { return new ClassName("kotlin", "ByteArray"); } else if (type.hasAny()) { diff --git a/jvm-runtime/jvm_integration_test.go b/jvm-runtime/jvm_integration_test.go index f2f3cb899..5828c4ab2 100644 --- a/jvm-runtime/jvm_integration_test.go +++ b/jvm-runtime/jvm_integration_test.go @@ -14,7 +14,7 @@ import ( "github.com/alecthomas/repr" ) -func TestJavaToGoCall(t *testing.T) { +func TestJVMToGoCall(t *testing.T) { exampleObject := TestObject{ IntField: 43, @@ -105,11 +105,11 @@ func TestJavaToGoCall(t *testing.T) { //tests = append(tests, PairedPrefixVerbTest("nilvalue", "optionalTestObjectOptionalFieldsVerb", ftl.None[any]())...) in.Run(t, - in.WithLanguages("java"), - in.CopyModule("gomodule"), - in.CopyModule("javamodule"), + in.WithLanguages("kotlin", "java"), + in.CopyModuleWithLanguage("gomodule", "go"), + in.CopyModule("passthrough"), in.Deploy("gomodule"), - in.Deploy("javamodule"), + in.Deploy("passthrough"), in.SubTests(tests...), ) } @@ -121,8 +121,8 @@ func PairedTest(name string, testFunc func(module string) in.Action) []in.SubTes Action: testFunc("gomodule"), }, { - Name: name + "-Java", - Action: testFunc("javamodule"), + Name: name + "-jvm", + Action: testFunc("passthrough"), }, } } diff --git a/jvm-runtime/testdata/java/gomodule/ftl.toml b/jvm-runtime/testdata/go/gomodule/ftl.toml similarity index 100% rename from jvm-runtime/testdata/java/gomodule/ftl.toml rename to jvm-runtime/testdata/go/gomodule/ftl.toml diff --git a/jvm-runtime/testdata/java/gomodule/go.mod b/jvm-runtime/testdata/go/gomodule/go.mod similarity index 100% rename from jvm-runtime/testdata/java/gomodule/go.mod rename to jvm-runtime/testdata/go/gomodule/go.mod diff --git a/jvm-runtime/testdata/java/gomodule/go.sum b/jvm-runtime/testdata/go/gomodule/go.sum similarity index 100% rename from jvm-runtime/testdata/java/gomodule/go.sum rename to jvm-runtime/testdata/go/gomodule/go.sum diff --git a/jvm-runtime/testdata/java/gomodule/server.go b/jvm-runtime/testdata/go/gomodule/server.go similarity index 100% rename from jvm-runtime/testdata/java/gomodule/server.go rename to jvm-runtime/testdata/go/gomodule/server.go diff --git a/jvm-runtime/testdata/java/javamodule/ftl.toml b/jvm-runtime/testdata/java/javamodule/ftl.toml deleted file mode 100644 index 864288fa7..000000000 --- a/jvm-runtime/testdata/java/javamodule/ftl.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "echoclient" -language = "java" diff --git a/jvm-runtime/testdata/java/passthrough/ftl.toml b/jvm-runtime/testdata/java/passthrough/ftl.toml new file mode 100644 index 000000000..e0f36e3a5 --- /dev/null +++ b/jvm-runtime/testdata/java/passthrough/ftl.toml @@ -0,0 +1,2 @@ +module = "passthrough" +language = "java" diff --git a/jvm-runtime/testdata/java/javamodule/pom.xml b/jvm-runtime/testdata/java/passthrough/pom.xml similarity index 92% rename from jvm-runtime/testdata/java/javamodule/pom.xml rename to jvm-runtime/testdata/java/passthrough/pom.xml index a8e23d687..29b323fd3 100644 --- a/jvm-runtime/testdata/java/javamodule/pom.xml +++ b/jvm-runtime/testdata/java/passthrough/pom.xml @@ -2,7 +2,7 @@ 4.0.0 xyz.block.ftl.examples - javamodule + passthrough 1.0-SNAPSHOT diff --git a/jvm-runtime/testdata/java/javamodule/src/main/java/xyz/block/ftl/java/test/TestInvokeGo.java b/jvm-runtime/testdata/java/passthrough/src/main/java/xyz/block/ftl/test/TestInvokeGoFromJava.java similarity index 98% rename from jvm-runtime/testdata/java/javamodule/src/main/java/xyz/block/ftl/java/test/TestInvokeGo.java rename to jvm-runtime/testdata/java/passthrough/src/main/java/xyz/block/ftl/test/TestInvokeGoFromJava.java index 00529e476..65a757356 100644 --- a/jvm-runtime/testdata/java/javamodule/src/main/java/xyz/block/ftl/java/test/TestInvokeGo.java +++ b/jvm-runtime/testdata/java/passthrough/src/main/java/xyz/block/ftl/test/TestInvokeGoFromJava.java @@ -1,4 +1,4 @@ -package xyz.block.ftl.java.test; +package xyz.block.ftl.test; import java.time.ZonedDateTime; import java.util.List; @@ -35,7 +35,7 @@ import xyz.block.ftl.Export; import xyz.block.ftl.Verb; -public class TestInvokeGo { +public class TestInvokeGoFromJava { @Export @Verb diff --git a/jvm-runtime/testdata/kotlin/passthrough/ftl.toml b/jvm-runtime/testdata/kotlin/passthrough/ftl.toml new file mode 100644 index 000000000..cedde0422 --- /dev/null +++ b/jvm-runtime/testdata/kotlin/passthrough/ftl.toml @@ -0,0 +1,2 @@ +module = "passthrough" +language = "kotlin" diff --git a/jvm-runtime/testdata/kotlin/passthrough/pom.xml b/jvm-runtime/testdata/kotlin/passthrough/pom.xml new file mode 100644 index 000000000..c641ddb2c --- /dev/null +++ b/jvm-runtime/testdata/kotlin/passthrough/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + xyz.block.ftl.examples + passthrough + 1.0-SNAPSHOT + + + xyz.block.ftl + ftl-build-parent-kotlin + 1.0-SNAPSHOT + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.0 + + + generate-sources + + add-source + + + + ${project.build.directory}/generated-sources/ftl-clients + + + + + + + + diff --git a/jvm-runtime/testdata/kotlin/passthrough/src/main/kotlin/xyz/block/ftl/test/TestInvokeGoFromKotlin.kt b/jvm-runtime/testdata/kotlin/passthrough/src/main/kotlin/xyz/block/ftl/test/TestInvokeGoFromKotlin.kt new file mode 100644 index 000000000..f783ebc8a --- /dev/null +++ b/jvm-runtime/testdata/kotlin/passthrough/src/main/kotlin/xyz/block/ftl/test/TestInvokeGoFromKotlin.kt @@ -0,0 +1,157 @@ +package xyz.block.ftl.test + +import ftl.gomodule.* +import xyz.block.ftl.Export +import xyz.block.ftl.Verb +import java.time.ZonedDateTime + +@Export +@Verb +fun emptyVerb(emptyVerbClient: EmptyVerbClient) { + emptyVerbClient.call() +} + +@Export +@Verb +fun sinkVerb(input: String, sinkVerbClient: SinkVerbClient) { + sinkVerbClient.call(input) +} + +@Export +@Verb +fun sourceVerb(sourceVerbClient: SourceVerbClient): String { + return sourceVerbClient.call() +} + +@Export +@Verb +fun errorEmptyVerb(client: ErrorEmptyVerbClient) { + client.call() +} + +@Export +@Verb +fun intVerb(payload: Long, client: IntVerbClient): Long { + return client.call(payload) +} + +@Export +@Verb +fun floatVerb(payload: Double, client: FloatVerbClient): Double { + return client.call(payload) +} + +@Export +@Verb +fun stringVerb(payload: String, client: StringVerbClient): String { + return client.call(payload) +} + +@Export +@Verb +fun bytesVerb(payload: ByteArray, client: BytesVerbClient): ByteArray { + return client.call(payload) +} + +@Export +@Verb +fun boolVerb(payload: Boolean, client: BoolVerbClient): Boolean { + return client.call(payload) +} + +@Export +@Verb +fun stringArrayVerb(payload: List, client: StringArrayVerbClient): List { + return client.call(payload) +} + +@Export +@Verb +fun stringMapVerb(payload: Map, client: StringMapVerbClient): Map { + return client.call(payload) +} + +@Export +@Verb +fun timeVerb(instant: ZonedDateTime, client: TimeVerbClient): ZonedDateTime { + return client.call(instant) +} + +@Export +@Verb +fun testObjectVerb(payload: TestObject, client: TestObjectVerbClient): TestObject { + return client.call(payload) +} + +@Export +@Verb +fun testObjectOptionalFieldsVerb( + payload: TestObjectOptionalFields, + client: TestObjectOptionalFieldsVerbClient +): TestObjectOptionalFields { + return client.call(payload) +} + +// now the same again but with option return / input types +@Export +@Verb +fun optionalIntVerb(payload: Long, client: OptionalIntVerbClient): Long { + return client.call(payload) +} + +@Export +@Verb +fun optionalFloatVerb(payload: Double, client: OptionalFloatVerbClient): Double { + return client.call(payload) +} + +@Export +@Verb +fun optionalStringVerb(payload: String, client: OptionalStringVerbClient): String { + return client.call(payload) +} + +@Export +@Verb +fun optionalBytesVerb(payload: ByteArray?, client: OptionalBytesVerbClient): ByteArray { + return client.call(payload!!) +} + +@Export +@Verb +fun optionalBoolVerb(payload: Boolean, client: OptionalBoolVerbClient): Boolean { + return client.call(payload) +} + +@Export +@Verb +fun optionalStringArrayVerb(payload: List, client: OptionalStringArrayVerbClient): List { + return client.call(payload) +} + +@Export +@Verb +fun optionalStringMapVerb(payload: Map, client: OptionalStringMapVerbClient): Map { + return client.call(payload) +} + +@Export +@Verb +fun optionalTimeVerb(instant: ZonedDateTime?, client: OptionalTimeVerbClient): ZonedDateTime { + return client.call(instant!!) +} + +@Export +@Verb +fun optionalTestObjectVerb(payload: TestObject?, client: OptionalTestObjectVerbClient): TestObject { + return client.call(payload!!) +} + +@Export +@Verb +fun optionalTestObjectOptionalFieldsVerb( + payload: TestObjectOptionalFields?, + client: OptionalTestObjectOptionalFieldsVerbClient +): TestObjectOptionalFields { + return client.call(payload!!) +}