From 633119bf9e7274af0a281f114d68390bd19bef19 Mon Sep 17 00:00:00 2001 From: Alexander Sysoev Date: Fri, 22 Nov 2024 17:18:33 +0100 Subject: [PATCH 1/2] Added test for non-serializable params --- .../kotlinx/rpc/krpc/test/KrpcTestService.kt | 9 +++ .../rpc/krpc/test/KrpcTestServiceBackend.kt | 11 ++++ .../rpc/krpc/test/KrpcTransportTestBase.kt | 58 +++++++++++++++++++ .../rpc/krpc/test/LocalTransportTest.kt | 12 +++- 4 files changed, 87 insertions(+), 3 deletions(-) diff --git a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestService.kt b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestService.kt index ec522edbc..5623164d7 100644 --- a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestService.kt +++ b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestService.kt @@ -9,6 +9,10 @@ import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.rpc.RemoteService import kotlinx.rpc.annotations.Rpc +import kotlinx.serialization.Contextual +import kotlinx.serialization.Serializable +import java.time.LocalDate +import java.time.LocalDateTime @Suppress("detekt.TooManyFunctions") @Rpc @@ -28,6 +32,11 @@ interface KrpcTestService : RemoteService { suspend fun nullable(arg1: String?): TestClass? suspend fun variance(arg2: TestList, arg3: TestList2<*>): TestList? + suspend fun nonSerializableClass(localDate: @Contextual LocalDate): LocalDate + suspend fun nonSerializableClassWithSerializer( + localDateTime: @Serializable(LocalDateTimeSerializer::class) LocalDateTime, + ): @Serializable(LocalDateTimeSerializer::class) LocalDateTime + suspend fun incomingStreamSyncCollect(arg1: Flow): Int suspend fun incomingStreamAsyncCollect(arg1: Flow): Int suspend fun outgoingStream(): Flow diff --git a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.kt b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.kt index 8be81217a..505a9336e 100644 --- a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.kt +++ b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.kt @@ -7,6 +7,9 @@ package kotlinx.rpc.krpc.test import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import kotlinx.serialization.Serializable +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter import kotlin.coroutines.CoroutineContext import kotlin.coroutines.resumeWithException import kotlin.test.assertEquals @@ -79,6 +82,14 @@ class KrpcTestServiceBackend(override val coroutineContext: CoroutineContext) : return TestList(3) } + override suspend fun nonSerializableClass(localDate: LocalDate): LocalDate { + return localDate.plusDays(1) + } + + override suspend fun nonSerializableClassWithSerializer(localDateTime: LocalDateTime): String { + return localDateTime.plusDays(1).format(DateTimeFormatter.ISO_DATE_TIME) + } + override suspend fun incomingStreamSyncCollect(arg1: Flow): Int { return arg1.count() } diff --git a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTransportTestBase.kt b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTransportTestBase.kt index 7041ea813..6398bc34a 100644 --- a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTransportTestBase.kt +++ b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTransportTestBase.kt @@ -18,16 +18,60 @@ import kotlinx.rpc.krpc.server.KrpcServer import kotlinx.rpc.krpc.streamScoped import kotlinx.rpc.registerService import kotlinx.rpc.withService +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.modules.SerializersModule import org.junit.Assert.assertEquals import org.junit.Rule import org.junit.rules.Timeout +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter import java.util.concurrent.Semaphore import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicBoolean import kotlin.coroutines.cancellation.CancellationException import kotlin.test.* +internal object LocalDateSerializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDate", PrimitiveKind.STRING) + + override fun serialize( + encoder: Encoder, + value: LocalDate, + ) { + encoder.encodeString(value.format(DateTimeFormatter.ISO_DATE)) + } + + override fun deserialize(decoder: Decoder): LocalDate { + return LocalDate.parse(decoder.decodeString(), DateTimeFormatter.ISO_DATE) + } +} + +internal object LocalDateTimeSerializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) + + override fun serialize( + encoder: Encoder, + value: LocalDateTime, + ) { + encoder.encodeString(value.format(DateTimeFormatter.ISO_DATE_TIME)) + } + + override fun deserialize(decoder: Decoder): LocalDateTime { + return LocalDateTime.parse(decoder.decodeString(), DateTimeFormatter.ISO_DATE_TIME) + } +} + abstract class KrpcTransportTestBase { + protected val serializersModule = SerializersModule { + contextual(LocalDate::class) { LocalDateSerializer } + } + protected abstract val serializationConfig: KrpcSerialFormatConfiguration.() -> Unit private val serverConfig by lazy { @@ -112,6 +156,20 @@ abstract class KrpcTransportTestBase { } } + @Test + @Ignore // todo will fix in next PR + fun nonSerializableParameter() { + runBlocking { + val localDate = LocalDate.of(2001, 8, 23) + val resultDate = client.nonSerializableClass(localDate) + assertEquals(localDate.plusDays(1), resultDate) + + val localDateTime = LocalDateTime.of(2001, 8, 23, 0, 0) + val resultDateTime = client.nonSerializableClassWithSerializer(localDateTime) + assertEquals(localDateTime.plusDays(1).format(DateTimeFormatter.ISO_DATE_TIME), resultDateTime) + } + } + @Test fun doubleGenericReturnType() { val result = runBlocking { client.doubleGenericReturnType() } diff --git a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/LocalTransportTest.kt b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/LocalTransportTest.kt index b5b73247e..02e8c1cd3 100644 --- a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/LocalTransportTest.kt +++ b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/LocalTransportTest.kt @@ -23,14 +23,18 @@ abstract class LocalTransportTest : KrpcTransportTestBase() { class JsonLocalTransportTest : LocalTransportTest() { override val serializationConfig: KrpcSerialFormatConfiguration.() -> Unit = { - json() + json { + serializersModule = this@JsonLocalTransportTest.serializersModule + } } } class CborLocalTransportTest : LocalTransportTest() { @OptIn(ExperimentalSerializationApi::class) override val serializationConfig: KrpcSerialFormatConfiguration.() -> Unit = { - cbor() + cbor { + serializersModule = this@CborLocalTransportTest.serializersModule + } } } @@ -38,7 +42,9 @@ class CborLocalTransportTest : LocalTransportTest() { class ProtoBufLocalTransportTest : LocalTransportTest() { @OptIn(ExperimentalSerializationApi::class) override val serializationConfig: KrpcSerialFormatConfiguration.() -> Unit = { - protobuf() + protobuf { + serializersModule = this@ProtoBufLocalTransportTest.serializersModule + } } // 'null' is not supported in ProtoBuf From 5a7f18c9cc0bc5614b436420e0066c90295cc5ae Mon Sep 17 00:00:00 2001 From: Alexander Sysoev Date: Fri, 22 Nov 2024 18:07:19 +0100 Subject: [PATCH 2/2] Update labels workflow --- .github/workflows/labels.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml index 641c28f3c..ae3f49608 100644 --- a/.github/workflows/labels.yml +++ b/.github/workflows/labels.yml @@ -15,10 +15,10 @@ jobs: check-labels: name: Check labels runs-on: ubuntu-latest - if: ${{ github.event.pull_request.draft == false && !contains(github.event.pull_request.labels.*.name, 'release') && !contains(github.event.pull_request.labels.*.name, 'feature') && !contains(github.event.pull_request.labels.*.name, 'bug') && !contains(github.event.pull_request.labels.*.name, 'breaking') && !contains(github.event.pull_request.labels.*.name, 'infra') && !contains(github.event.pull_request.labels.*.name, 'docs') && !contains(github.event.pull_request.labels.*.name, 'deprecation') && !contains(github.event.pull_request.labels.*.name, 'dependencies') }} + if: ${{ github.event.pull_request.draft == false && !contains(github.event.pull_request.labels.*.name, 'release') && !contains(github.event.pull_request.labels.*.name, 'feature') && !contains(github.event.pull_request.labels.*.name, 'bug') && !contains(github.event.pull_request.labels.*.name, 'breaking') && !contains(github.event.pull_request.labels.*.name, 'infra') && !contains(github.event.pull_request.labels.*.name, 'docs') && !contains(github.event.pull_request.labels.*.name, 'deprecation') && !contains(github.event.pull_request.labels.*.name, 'dependencies') && !contains(github.event.pull_request.labels.*.name, 'housekeeping') }} steps: - name: Fail build after no labels present run: | echo "Pull request does not contain any required labels" - echo "Please use at least one of 'feature', 'bug', 'breaking', 'infra', 'docs', 'deprecation', 'release' or 'dependencies' labels" + echo "Please use at least one of 'feature', 'bug', 'breaking', 'infra', 'docs', 'deprecation', 'release', 'housekeeping' or 'dependencies' labels" exit 1