From 3c0a5aa4a51047a1f5ac7c423cc1a48a424e36bd Mon Sep 17 00:00:00 2001 From: Matt Toohey Date: Wed, 14 May 2025 12:04:53 +1000 Subject: [PATCH 1/2] test: ingress tests should include kotlin - add enum decls to kotlin test module - fix unit test failures --- backend/ingress/ingress_integration_test.go | 8 +- .../testdata/kotlin/httpingress/ftl.toml | 2 + .../testdata/kotlin/httpingress/pom.xml | 14 ++ .../main/kotlin/ftl/httpingress/ArrayType.kt | 5 + .../kotlin/ftl/httpingress/DeleteRequest.kt | 5 + .../kotlin/ftl/httpingress/DeleteResponse.kt | 4 + .../main/kotlin/ftl/httpingress/GetRequest.kt | 6 + .../kotlin/ftl/httpingress/GetResponse.kt | 6 + .../main/kotlin/ftl/httpingress/HelloVerb.kt | 9 ++ .../src/main/kotlin/ftl/httpingress/Nested.kt | 8 + .../kotlin/ftl/httpingress/PostRequest.kt | 9 ++ .../kotlin/ftl/httpingress/PostResponse.kt | 5 + .../main/kotlin/ftl/httpingress/PutRequest.kt | 5 + .../kotlin/ftl/httpingress/PutResponse.kt | 5 + .../ftl/httpingress/QueryParamRequest.kt | 7 + .../main/kotlin/ftl/httpingress/TestHTTP.kt | 144 ++++++++++++++++++ .../src/main/resources/application.properties | 0 17 files changed, 238 insertions(+), 4 deletions(-) create mode 100644 backend/ingress/testdata/kotlin/httpingress/ftl.toml create mode 100644 backend/ingress/testdata/kotlin/httpingress/pom.xml create mode 100644 backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/ArrayType.kt create mode 100644 backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/DeleteRequest.kt create mode 100644 backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/DeleteResponse.kt create mode 100644 backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/GetRequest.kt create mode 100644 backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/GetResponse.kt create mode 100644 backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/HelloVerb.kt create mode 100644 backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/Nested.kt create mode 100644 backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PostRequest.kt create mode 100644 backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PostResponse.kt create mode 100644 backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PutRequest.kt create mode 100644 backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PutResponse.kt create mode 100644 backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/QueryParamRequest.kt create mode 100644 backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/TestHTTP.kt create mode 100644 backend/ingress/testdata/kotlin/httpingress/src/main/resources/application.properties diff --git a/backend/ingress/ingress_integration_test.go b/backend/ingress/ingress_integration_test.go index d78873935a..cfb9b9c8de 100644 --- a/backend/ingress/ingress_integration_test.go +++ b/backend/ingress/ingress_integration_test.go @@ -16,7 +16,7 @@ import ( func TestHttpIngress(t *testing.T) { in.Run(t, - in.WithLanguages("go", "java"), + in.WithLanguages("go", "java", "kotlin"), in.CopyModule("httpingress"), in.Deploy("httpingress"), in.SubTests( @@ -132,7 +132,7 @@ func TestHttpIngress(t *testing.T) { assert.Equal(t, nil, resp.Headers["Access-Control-Allow-Headers"]) })}, ), - in.IfLanguage("go", in.SubTests( + in.IfLanguages(in.SubTests( // Double, Int etc work in java with JSON encoding, but test/plain is not implemented yet in.SubTest{Name: "PostInt", Action: in.HttpCall(http.MethodPost, "/int", nil, []byte("1234"), func(t testing.TB, resp *in.HTTPResponse) { assert.Equal(t, 200, resp.Status) @@ -172,10 +172,10 @@ func TestHttpIngress(t *testing.T) { in.SubTest{Name: "TestExtraFieldLenient", Action: in.HttpCall(http.MethodPost, "/lenient", nil, in.JsonData(t, in.Obj{"user_id": 123, "postId": 345, "extra": "blah"}), func(t testing.TB, resp *in.HTTPResponse) { assert.Equal(t, 201, resp.Status) })}, - )), + ), "go", "kotlin"), in.IfLanguage("java", in.SubTests( - // Double, Int etc work in java with JSON encoding, but test/plain is not implemented yet + // Double, Int etc work in java with JSON encoding, but text/plain is not implemented yet in.SubTest{Name: "JavaVerbClient", Action: in.HttpCall(http.MethodGet, "/client", nil, nil, func(t testing.TB, resp *in.HTTPResponse) { assert.Equal(t, 200, resp.Status) assert.Equal(t, []byte("Hello"), resp.BodyBytes) diff --git a/backend/ingress/testdata/kotlin/httpingress/ftl.toml b/backend/ingress/testdata/kotlin/httpingress/ftl.toml new file mode 100644 index 0000000000..81d85fc28b --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/ftl.toml @@ -0,0 +1,2 @@ +module = "httpingress" +language = "kotlin" diff --git a/backend/ingress/testdata/kotlin/httpingress/pom.xml b/backend/ingress/testdata/kotlin/httpingress/pom.xml new file mode 100644 index 0000000000..c2e710df59 --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + ftl.httpingress + httpingress + 1.0-SNAPSHOT + + + xyz.block.ftl + ftl-build-parent-kotlin + 1.0-SNAPSHOT + + + diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/ArrayType.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/ArrayType.kt new file mode 100644 index 0000000000..4252874788 --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/ArrayType.kt @@ -0,0 +1,5 @@ +package ftl.httpingress; + +data class ArrayType( + val item: String +) \ No newline at end of file diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/DeleteRequest.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/DeleteRequest.kt new file mode 100644 index 0000000000..e384ee73d5 --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/DeleteRequest.kt @@ -0,0 +1,5 @@ +package ftl.httpingress; + +data class DeleteRequest( + val userId: String +) diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/DeleteResponse.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/DeleteResponse.kt new file mode 100644 index 0000000000..6741a7803e --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/DeleteResponse.kt @@ -0,0 +1,4 @@ +package ftl.httpingress; + +class DeleteResponse { +} diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/GetRequest.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/GetRequest.kt new file mode 100644 index 0000000000..218cfc1941 --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/GetRequest.kt @@ -0,0 +1,6 @@ +package ftl.httpingress; + +data class GetRequest( + val userId: String, + val postId: String +) diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/GetResponse.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/GetResponse.kt new file mode 100644 index 0000000000..8f25b90d37 --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/GetResponse.kt @@ -0,0 +1,6 @@ +package ftl.httpingress; + +data class GetResponse( + val nested: Nested, + val msg: String +) diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/HelloVerb.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/HelloVerb.kt new file mode 100644 index 0000000000..64fdcf9ad8 --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/HelloVerb.kt @@ -0,0 +1,9 @@ +package ftl.httpingress; + +import xyz.block.ftl.SourceVerb +import xyz.block.ftl.Verb + +@Verb +fun hello(): String { + return "Hello" +} diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/Nested.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/Nested.kt new file mode 100644 index 0000000000..b6a99bb582 --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/Nested.kt @@ -0,0 +1,8 @@ +package ftl.httpingress; + +import com.fasterxml.jackson.annotation.JsonAlias; + +data class Nested( + @JsonAlias("good_stuff") + val goodStuff: String +) diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PostRequest.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PostRequest.kt new file mode 100644 index 0000000000..b146c7eff9 --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PostRequest.kt @@ -0,0 +1,9 @@ +package ftl.httpingress; + +import com.fasterxml.jackson.annotation.JsonAlias; + +data class PostRequest( + @JsonAlias("user_id") + val userId: Long, + val postId: Long +) diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PostResponse.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PostResponse.kt new file mode 100644 index 0000000000..ef3924dafa --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PostResponse.kt @@ -0,0 +1,5 @@ +package ftl.httpingress; + +data class PostResponse( + val success: Boolean, +) \ No newline at end of file diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PutRequest.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PutRequest.kt new file mode 100644 index 0000000000..a3477fd108 --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PutRequest.kt @@ -0,0 +1,5 @@ +package ftl.httpingress; + +data class PutRequest( + val postId: String +) \ No newline at end of file diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PutResponse.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PutResponse.kt new file mode 100644 index 0000000000..82e0ea1315 --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PutResponse.kt @@ -0,0 +1,5 @@ +package ftl.httpingress; + +class PutResponse { + +} \ No newline at end of file diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/QueryParamRequest.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/QueryParamRequest.kt new file mode 100644 index 0000000000..a761332e37 --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/QueryParamRequest.kt @@ -0,0 +1,7 @@ +package ftl.httpingress; + +import org.jetbrains.annotations.Nullable; + +data class QueryParamRequest( + val foo:String? +) diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/TestHTTP.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/TestHTTP.kt new file mode 100644 index 0000000000..e23cdbdd29 --- /dev/null +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/TestHTTP.kt @@ -0,0 +1,144 @@ +package ftl.httpingress; + +import java.util.List; + +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +import org.jboss.resteasy.reactive.ResponseHeader; +import org.jboss.resteasy.reactive.ResponseStatus; +import org.jboss.resteasy.reactive.RestPath; +import org.jboss.resteasy.reactive.RestQuery; + +@Path("/") +class TestHTTP { + + @GET + @Path("/users/{userId}/posts/{postId}") + @ResponseHeader(name = "Get", value = ["Header from FTL"]) + fun get( + @RestPath userId:Long, + @RestPath postId:Long + ): GetResponse { + return GetResponse( + nested = Nested( + goodStuff = "This is good stuff" + ), + msg = String.format("UserID: %s, PostID: %s", userId, postId), + ) + } + + @GET + @Path("/getquery") + @ResponseHeader(name = "Get", value = ["Header from FTL"]) + fun getquery(@RestQuery userId:Long, @RestQuery postId:Long): GetResponse { + return GetResponse( + msg = String.format("UserID: %s, PostID: %s", userId, postId), + nested = Nested( + goodStuff = "This is good stuff" + ), + ) + } + + @POST + @Path("/users") + @ResponseStatus(201) + @ResponseHeader(name = "Post", value = ["Header from FTL"]) + fun post(req: PostRequest): PostResponse { + return PostResponse(success = true) + } + + @PUT + @Path("/users/{userId}") + @ResponseHeader(name = "Put", value = ["Header from FTL"]) + fun put(req:PutRequest): PutResponse { + return PutResponse(); + } + + @DELETE + @Path("/users/{userId}") + @ResponseHeader(name = "Delete", value = ["Header from FTL"]) + @ResponseStatus(200) + fun delete(@RestPath userId:String): DeleteResponse { + System.out.println("delete"); + return DeleteResponse(); + } + + @GET + @Path("/queryparams") + fun query(@RestQuery foo:String): String { + if (foo == null) { + return "No value"; + } + return foo; + } + + @GET + @Path("/html") + @Produces("text/html; charset=utf-8") + fun html() : String { + return "

HTML Page From FTL 🚀!

"; + } + + @POST + @Path("/bytes") + fun bytes(b: ByteArray): ByteArray { + return b; + } + + @GET + @Path("/empty") + @ResponseStatus(200) + fun empty() { + } + + @POST + @Path("/string") + fun string(value:String): String { + return value; + } + + @POST + @Path("/int") + @Produces(MediaType.APPLICATION_JSON) + fun intMethod(value:Int): Int { + return value; + } + + @POST + @Path("/float") + @Produces(MediaType.APPLICATION_JSON) + fun floatVerb(value:Float): Float { + return value; + } + + @POST + @Path("/bool") + @Produces(MediaType.APPLICATION_JSON) + fun bool(value:Boolean): Boolean { + return value; + } + + @GET + @Path("/error") + fun error():String { + throw RuntimeException("Error from FTL"); + } + + @POST + @Path("/array/string") + fun arrayString(array:List): List { + return array; + } + + @POST + @Path("/array/data") + fun arrayData(array:List): List { + return array; + } +} diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/resources/application.properties b/backend/ingress/testdata/kotlin/httpingress/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 From 9cf118ed07bba578822ad267303c1afda52c9680 Mon Sep 17 00:00:00 2001 From: Stuart Douglas Date: Thu, 15 May 2025 15:22:47 +1000 Subject: [PATCH 2/2] test fixes --- .../httpingress/src/main/kotlin/ftl/httpingress/Nested.kt | 2 +- .../httpingress/src/main/kotlin/ftl/httpingress/PostRequest.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/Nested.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/Nested.kt index b6a99bb582..87677ff8d7 100644 --- a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/Nested.kt +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/Nested.kt @@ -3,6 +3,6 @@ package ftl.httpingress; import com.fasterxml.jackson.annotation.JsonAlias; data class Nested( - @JsonAlias("good_stuff") + @field:JsonAlias("good_stuff") val goodStuff: String ) diff --git a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PostRequest.kt b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PostRequest.kt index b146c7eff9..ff6bbace6a 100644 --- a/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PostRequest.kt +++ b/backend/ingress/testdata/kotlin/httpingress/src/main/kotlin/ftl/httpingress/PostRequest.kt @@ -3,7 +3,7 @@ package ftl.httpingress; import com.fasterxml.jackson.annotation.JsonAlias; data class PostRequest( - @JsonAlias("user_id") + @field:JsonAlias("user_id") val userId: Long, val postId: Long )