From 59f53bc51a51bb65164f65f4f5d1f302fcacd7f8 Mon Sep 17 00:00:00 2001 From: Dan Chao Date: Mon, 2 Jun 2025 08:50:57 -0700 Subject: [PATCH] Make libpkl tests use AbstractServerTest * Move AbstractServerTest and its dependencies into pkl-commons-test * Make LibPklTest implement AbstractServerTest * Rename "NativeTest" -> "LibPklTest" * Rename "LibPklLibrary" -> "LibPklJNA" --- libpkl/src/main/c/pkl.h | 8 +- .../kotlin/org/pkl/libpkl/JNATestClient.kt | 112 --- .../libpkl/{LibPklLibrary.kt => LibPklJNA.kt} | 4 +- .../org/pkl/libpkl/LibPklMessageTransport.kt | 59 ++ .../kotlin/org/pkl/libpkl/LibPklTest.kt | 46 + .../pkl/libpkl/MessagePackDebugRenderer.kt | 107 --- .../kotlin/org/pkl/libpkl/NativeTest.kt | 873 ------------------ pkl-commons-test/gradle.lockfile | 9 + pkl-commons-test/pkl-commons-test.gradle.kts | 3 + .../commons/test}/MessagePackDebugRenderer.kt | 9 +- .../test}/server/AbstractServerTest.kt | 46 +- .../pkl/commons/test}/server/TestTransport.kt | 4 +- .../pkl/commons/test}/server/resource1.jar | Bin pkl-gradle/gradle.lockfile | 9 + pkl-parser/gradle.lockfile | 9 + .../pkl/server/BinaryEvaluatorSnippetTests.kt | 6 +- .../org/pkl/server/BinaryEvaluatorTest.kt | 3 +- .../kotlin/org/pkl/server/JvmServerTest.kt | 2 + .../kotlin/org/pkl/server/NativeServerTest.kt | 2 + 19 files changed, 196 insertions(+), 1115 deletions(-) delete mode 100644 libpkl/src/nativeTest/kotlin/org/pkl/libpkl/JNATestClient.kt rename libpkl/src/nativeTest/kotlin/org/pkl/libpkl/{LibPklLibrary.kt => LibPklJNA.kt} (90%) create mode 100644 libpkl/src/nativeTest/kotlin/org/pkl/libpkl/LibPklMessageTransport.kt create mode 100644 libpkl/src/nativeTest/kotlin/org/pkl/libpkl/LibPklTest.kt delete mode 100644 libpkl/src/nativeTest/kotlin/org/pkl/libpkl/MessagePackDebugRenderer.kt delete mode 100644 libpkl/src/nativeTest/kotlin/org/pkl/libpkl/NativeTest.kt rename {pkl-server/src/test/kotlin/org/pkl/server => pkl-commons-test/src/main/kotlin/org/pkl/commons/test}/MessagePackDebugRenderer.kt (94%) rename {pkl-server/src/test/kotlin/org/pkl => pkl-commons-test/src/main/kotlin/org/pkl/commons/test}/server/AbstractServerTest.kt (95%) rename {pkl-server/src/test/kotlin/org/pkl => pkl-commons-test/src/main/kotlin/org/pkl/commons/test}/server/TestTransport.kt (92%) rename {pkl-server/src/test/resources/org/pkl => pkl-commons-test/src/main/resources/org/pkl/commons/test}/server/resource1.jar (100%) diff --git a/libpkl/src/main/c/pkl.h b/libpkl/src/main/c/pkl.h index 4c2df64c6..347b165b9 100644 --- a/libpkl/src/main/c/pkl.h +++ b/libpkl/src/main/c/pkl.h @@ -20,19 +20,19 @@ * * @param length The length the message bytes * @param message The message itself - * @param payload User-defined data passed to pkl_init. + * @param userData User-defined data passed in from pkl_init. */ -typedef void (*PklMessageResponseHandler)(int length, char *message, void *payload); +typedef void (*PklMessageResponseHandler)(int length, char *message, void *userData); /** * Initialises and allocates a Pkl executor. * * @param handler The callback that gets called when a message is received from Pkl. - * @param payload User-defined data that gets passed to handler. + * @param userData User-defined data that gets passed to handler. * * @return -1 on failure, 0 on success. */ -int pkl_init(PklMessageResponseHandler handler, void *payload); +int pkl_init(PklMessageResponseHandler handler, void *userData); /** * Send a message to Pkl, providing the length and a pointer to the first byte. diff --git a/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/JNATestClient.kt b/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/JNATestClient.kt deleted file mode 100644 index 4167e9bfe..000000000 --- a/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/JNATestClient.kt +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.pkl.libpkl - -import com.sun.jna.Pointer -import java.io.ByteArrayOutputStream -import java.lang.AutoCloseable -import java.nio.file.Path -import java.util.concurrent.ArrayBlockingQueue -import java.util.concurrent.BlockingQueue -import org.assertj.core.api.Assertions.assertThat -import org.msgpack.core.MessagePack -import org.pkl.core.messaging.Message -import org.pkl.core.messaging.Messages.ModuleReaderSpec -import org.pkl.core.messaging.Messages.ResourceReaderSpec -import org.pkl.server.CreateEvaluatorRequest -import org.pkl.server.CreateEvaluatorResponse -import org.pkl.server.Http -import org.pkl.server.Project -import org.pkl.server.ServerMessagePackDecoder -import org.pkl.server.ServerMessagePackEncoder - -class JNATestClient : LibPklLibrary.PklMessageResponseHandler, Iterable, AutoCloseable { - val incoming: BlockingQueue = ArrayBlockingQueue(10) - - override fun invoke(length: Int, message: Pointer, userData: Pointer?) { - val receivedBytes: ByteArray = message.getByteArray(0, length) - val message = decode(receivedBytes) - assertThat(message).isInstanceOf(Message::class.java) - incoming.add(message!!) - } - - override fun close() = incoming.clear() - - override fun iterator(): Iterator = incoming.iterator() - - fun send(message: Message): Int = - // TODO: Propagate `handlerContext` through, and validate it. - encode(message).let { LibPklLibrary.INSTANCE.pkl_send_message(it.size, it) } - - inline fun receive(): T { - val message = incoming.take() - assertThat(message).isInstanceOf(T::class.java) - return message as T - } - - fun sendCreateEvaluatorRequest( - requestId: Long = 123, - resourceReaders: List = listOf(), - moduleReaders: List = listOf(), - modulePaths: List = listOf(), - project: Project? = null, - cacheDir: Path? = null, - http: Http? = null, - ): Long { - val message = - CreateEvaluatorRequest( - 123, - listOf(".*"), - listOf(".*"), - moduleReaders, - resourceReaders, - modulePaths, - mapOf(), - mapOf(), - null, - null, - cacheDir, - null, - project, - http, - null, - null, - ) - - send(message) - - val response = receive() - assertThat(response.requestId()).isEqualTo(requestId) - assertThat(response.evaluatorId).isNotNull - assertThat(response.error).isNull() - - return response.evaluatorId!! - } - - private fun encode(message: Message): ByteArray { - ByteArrayOutputStream().use { os -> - val packer = MessagePack.newDefaultPacker(os) - val encoder = ServerMessagePackEncoder(packer) - encoder.encode(message) - return os.toByteArray() - } - } - - private fun decode(receivedBytes: ByteArray): Message? { - val unpacker = MessagePack.newDefaultUnpacker(receivedBytes) - return ServerMessagePackDecoder(unpacker).decode() - } -} diff --git a/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/LibPklLibrary.kt b/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/LibPklJNA.kt similarity index 90% rename from libpkl/src/nativeTest/kotlin/org/pkl/libpkl/LibPklLibrary.kt rename to libpkl/src/nativeTest/kotlin/org/pkl/libpkl/LibPklJNA.kt index 5a29c2ce3..0e426c035 100644 --- a/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/LibPklLibrary.kt +++ b/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/LibPklJNA.kt @@ -21,9 +21,9 @@ import com.sun.jna.Native import com.sun.jna.Pointer @Suppress("FunctionName") -interface LibPklLibrary : Library { +interface LibPklJNA : Library { companion object { - val INSTANCE: LibPklLibrary = Native.load("pkl", LibPklLibrary::class.java) + val INSTANCE: LibPklJNA = Native.load("pkl", LibPklJNA::class.java) } interface PklMessageResponseHandler : Callback { diff --git a/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/LibPklMessageTransport.kt b/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/LibPklMessageTransport.kt new file mode 100644 index 000000000..578872453 --- /dev/null +++ b/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/LibPklMessageTransport.kt @@ -0,0 +1,59 @@ +/* + * Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pkl.libpkl + +import com.sun.jna.Pointer +import org.assertj.core.api.Assertions.assertThat +import org.msgpack.core.MessagePack +import org.pkl.core.messaging.Message +import org.pkl.core.messaging.MessageTransports +import org.pkl.server.ServerMessagePackDecoder +import org.pkl.server.ServerMessagePackEncoder + +class LibPklMessageTransport : MessageTransports.AbstractMessageTransport({}) { + private val messageResponseHandler: LibPklJNA.PklMessageResponseHandler = + object : LibPklJNA.PklMessageResponseHandler { + override fun invoke(length: Int, message: Pointer, userData: Pointer?) { + val message = decode(message.getByteArray(0, length)) + accept(message) + } + } + + override fun doStart() { + assertThat(LibPklJNA.INSTANCE.pkl_init(messageResponseHandler, Pointer.NULL)).isEqualTo(0) + } + + override fun doClose() { + assertThat(LibPklJNA.INSTANCE.pkl_close()).isEqualTo(0) + } + + override fun doSend(message: Message) { + val bytes = encode(message) + LibPklJNA.INSTANCE.pkl_send_message(bytes.size, bytes) + } + + private fun encode(message: Message): ByteArray { + val packer = MessagePack.newDefaultBufferPacker() + val encoder = ServerMessagePackEncoder(packer) + encoder.encode(message) + return packer.toByteArray() + } + + private fun decode(receivedBytes: ByteArray): Message { + val unpacker = MessagePack.newDefaultUnpacker(receivedBytes) + return ServerMessagePackDecoder(unpacker).decode()!! + } +} diff --git a/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/LibPklTest.kt b/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/LibPklTest.kt new file mode 100644 index 000000000..c9a3fad63 --- /dev/null +++ b/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/LibPklTest.kt @@ -0,0 +1,46 @@ +/* + * Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pkl.libpkl + +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.pkl.commons.test.server.AbstractServerTest +import org.pkl.commons.test.server.TestTransport + +/** + * Tests libpkl bindings by using JNA (see [LibPklJNA] and [LibPklMessageTransport]). + * + * To run these tests in IntelliJ, add + * `-Djna.library.path=$ProjectFileDir$/libpkl/build/native-libs/-` to the run + * configuration. + * + * You can modify the IntelliJ JUnit configuration template so that this flag gets added + * automatically. See https://www.jetbrains.com/help/idea/run-debug-configuration.html#templates for + * more details. + */ +class LibPklTest : AbstractServerTest() { + override lateinit var client: TestTransport + + @BeforeEach + fun beforeEach() { + client = TestTransport(LibPklMessageTransport()).also { it.start() } + } + + @AfterEach + fun afterEach() { + client.close() + } +} diff --git a/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/MessagePackDebugRenderer.kt b/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/MessagePackDebugRenderer.kt deleted file mode 100644 index 8d4d01d4e..000000000 --- a/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/MessagePackDebugRenderer.kt +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.pkl.libpkl - -import java.lang.IllegalStateException -import org.msgpack.core.MessagePack -import org.msgpack.core.MessageUnpacker -import org.msgpack.value.ValueType -import org.pkl.core.util.yaml.YamlEmitter - -/** Renders MessagePack structures in YAML. */ -class MessagePackDebugRenderer(bytes: ByteArray) { - private val unpacker: MessageUnpacker = MessagePack.newDefaultUnpacker(bytes) - private val currIndent = StringBuilder("") - private val sb = StringBuilder() - private val indent = " " - private val yamlEmitter = YamlEmitter.create(sb, "1.2", indent) - - private fun incIndent() { - currIndent.append(indent) - } - - private fun decIndent() { - currIndent.setLength(currIndent.length - indent.length) - } - - private fun newline() { - sb.append("\n") - sb.append(currIndent) - } - - private fun renderKey() { - val mf = unpacker.nextFormat - when (mf.valueType!!) { - ValueType.STRING -> yamlEmitter.emit(unpacker.unpackString(), currIndent, true) - ValueType.MAP, - ValueType.ARRAY -> { - sb.append("? ") - incIndent() - renderValue() - decIndent() - newline() - } - else -> renderValue() - } - sb.append(": ") - } - - private fun renderValue() { - val mf = unpacker.nextFormat - when (mf.valueType!!) { - ValueType.INTEGER, - ValueType.FLOAT, - ValueType.BOOLEAN, - ValueType.NIL -> sb.append(unpacker.unpackValue().toJson()) - ValueType.STRING -> yamlEmitter.emit(unpacker.unpackString(), currIndent, false) - ValueType.ARRAY -> { - val size = unpacker.unpackArrayHeader() - if (size == 0) { - sb.append("[]") - return - } - for (i in 0 until size) { - newline() - sb.append("- ") - incIndent() - renderValue() - decIndent() - } - } - ValueType.MAP -> { - val size = unpacker.unpackMapHeader() - if (size == 0) { - sb.append("{}") - return - } - for (i in 0 until size) { - newline() - renderKey() - incIndent() - renderValue() - decIndent() - } - } - ValueType.BINARY, - ValueType.EXTENSION -> throw IllegalStateException("Unexpected value type ${mf.valueType}") - } - } - - val output: String by lazy { - renderValue() - sb.toString().removePrefix("\n") - } -} diff --git a/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/NativeTest.kt b/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/NativeTest.kt deleted file mode 100644 index 557d38764..000000000 --- a/libpkl/src/nativeTest/kotlin/org/pkl/libpkl/NativeTest.kt +++ /dev/null @@ -1,873 +0,0 @@ -/* - * Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.pkl.libpkl - -import com.sun.jna.Pointer -import java.net.URI -import java.nio.file.Path -import kotlin.io.path.createDirectories -import kotlin.io.path.writeText -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.io.TempDir -import org.msgpack.core.MessagePack -import org.pkl.commons.test.PackageServer -import org.pkl.core.messaging.Messages.ListModulesRequest -import org.pkl.core.messaging.Messages.ListModulesResponse -import org.pkl.core.messaging.Messages.ListResourcesRequest -import org.pkl.core.messaging.Messages.ListResourcesResponse -import org.pkl.core.messaging.Messages.ModuleReaderSpec -import org.pkl.core.messaging.Messages.ReadModuleRequest -import org.pkl.core.messaging.Messages.ReadModuleResponse -import org.pkl.core.messaging.Messages.ReadResourceRequest -import org.pkl.core.messaging.Messages.ReadResourceResponse -import org.pkl.core.messaging.Messages.ResourceReaderSpec -import org.pkl.core.module.PathElement -import org.pkl.server.* - -// To run this test in IntelliJ, add -// `-Djna.library.path=$ProjectFileDir$/libpkl/build/libs/-` to the -// run configuration. -// -// You can modify the IntelliJ JUnit configuration template so that this flag gets added -// automatically. -// See https://www.jetbrains.com/help/idea/run-debug-configuration.html#templates for more details. -/** - * Binds to the native library using JNA. - * - * @see JNATestClient - * @see LibPklLibrary - */ -class NativeTest { - companion object { - lateinit var client: JNATestClient - } - - @BeforeEach - fun beforeEach() { - client = JNATestClient() - assertThat(LibPklLibrary.INSTANCE.pkl_init(client, Pointer.NULL)).isEqualTo(0) - } - - @AfterEach - fun afterEach() { - client.close() - assertThat(LibPklLibrary.INSTANCE.pkl_close()).isEqualTo(0) - } - - @Test - fun `create evaluator, receive message, and close evaluator`() { - val evaluatorId = client.sendCreateEvaluatorRequest() - - client.send(EvaluateRequest(1, evaluatorId, URI("repl:text"), """foo = 1""", null)) - val response = client.receive() - assertThat(response.evaluatorId).isEqualTo(evaluatorId) - - assertThat(client.send(CloseEvaluator(evaluatorId))).isEqualTo(0) - assertThat(client).hasSize(0) - } - - @Test - fun `evaluate module`() { - val evaluatorId = client.sendCreateEvaluatorRequest() - val requestId = 234L - - client.send( - EvaluateRequest( - requestId, - evaluatorId, - URI("repl:text"), - """ - foo { - bar = "bar" - } - """ - .trimIndent(), - null, - ) - ) - - val response = client.receive() - assertThat(response.error).isNull() - assertThat(response.result).isNotNull - assertThat(response.requestId()).isEqualTo(requestId) - - val unpacker = MessagePack.newDefaultUnpacker(response.result) - val value = unpacker.unpackValue() - assertThat(value.isArrayValue) - } - - @Test - fun `trace logs`() { - val evaluatorId = client.sendCreateEvaluatorRequest() - - client.send( - EvaluateRequest( - 1, - evaluatorId, - URI("repl:text"), - """ - foo = trace(1 + 2 + 3) - """ - .trimIndent(), - null, - ) - ) - - val response = client.receive() - assertThat(response.level).isEqualTo(0) - assertThat(response.message).isEqualTo("1 + 2 + 3 = 6") - - // client.receive() - } - - @Test - fun `warn logs`() { - val evaluatorId = client.sendCreateEvaluatorRequest() - - client.send( - EvaluateRequest( - 1, - evaluatorId, - URI("repl:text"), - """ - @Deprecated { message = "use bar instead" } - function foo() = 5 - - result = foo() - """ - .trimIndent(), - null, - ) - ) - - val response = client.receive() - assertThat(response.level).isEqualTo(1) - assertThat(response.message).contains("use bar instead") - - client.receive() - } - - @Test - fun `read resource`() { - val reader = ResourceReaderSpec("bahumbug", true, false) - val evaluatorId = client.sendCreateEvaluatorRequest(resourceReaders = listOf(reader)) - - client.send( - EvaluateRequest( - 1, - evaluatorId, - URI("repl:text"), - """res = read("bahumbug:/foo.pkl").text""", - "res", - ) - ) - - val readResourceMsg = client.receive() - assertThat(readResourceMsg.uri.toString()).isEqualTo("bahumbug:/foo.pkl") - assertThat(readResourceMsg.evaluatorId).isEqualTo(evaluatorId) - - client.send( - ReadResourceResponse( - readResourceMsg.requestId, - evaluatorId, - "my bahumbug".toByteArray(), - null, - ) - ) - - val evaluateResponse = client.receive() - assertThat(evaluateResponse.error).isNull() - - val unpacker = MessagePack.newDefaultUnpacker(evaluateResponse.result) - val value = unpacker.unpackValue() - assertThat(value.asStringValue().asString()).isEqualTo("my bahumbug") - } - - @Test - fun `read resource error`() { - val reader = ResourceReaderSpec("bahumbug", true, false) - val evaluatorId = client.sendCreateEvaluatorRequest(resourceReaders = listOf(reader)) - - client.send( - EvaluateRequest( - 1, - evaluatorId, - URI("repl:text"), - """res = read("bahumbug:/foo.txt").text""", - "res", - ) - ) - - val readResourceMsg = client.receive() - - client.send( - ReadResourceResponse( - readResourceMsg.requestId, - evaluatorId, - byteArrayOf(), - "cannot read my bahumbug", - ) - ) - - val evaluateResponse = client.receive() - assertThat(evaluateResponse.error).contains("bahumbug:/foo.txt") - assertThat(evaluateResponse.error).doesNotContain("org.pkl.core.PklBugException") - } - - @Test - fun `glob resource`() { - val reader = ResourceReaderSpec("bird", true, true) - val evaluatorId = client.sendCreateEvaluatorRequest(resourceReaders = listOf(reader)) - client.send( - EvaluateRequest( - 1, - evaluatorId, - URI("repl:text"), - """ - res = read*("bird:/**.txt").keys - """ - .trimIndent(), - "res", - ) - ) - val listResourcesRequest = client.receive() - assertThat(listResourcesRequest.uri.toString()).isEqualTo("bird:/") - client.send( - ListResourcesResponse( - listResourcesRequest.requestId, - listResourcesRequest.evaluatorId, - listOf(PathElement("foo.txt", false), PathElement("subdir", true)), - null, - ) - ) - val listResourcesRequest2 = client.receive() - assertThat(listResourcesRequest2.uri.toString()).isEqualTo("bird:/subdir/") - client.send( - ListResourcesResponse( - listResourcesRequest2.requestId, - listResourcesRequest2.evaluatorId, - listOf(PathElement("bar.txt", false)), - null, - ) - ) - val evaluateResponse = client.receive() - assertThat(evaluateResponse.result?.debugYaml) - .isEqualTo( - """ - - 6 - - - - bird:/foo.txt - - bird:/subdir/bar.txt - """ - .trimIndent() - ) - } - - @Test - fun `glob resources -- null pathElements and null error`() { - val reader = ResourceReaderSpec("bird", true, true) - val evaluatorId = client.sendCreateEvaluatorRequest(resourceReaders = listOf(reader)) - client.send( - EvaluateRequest( - 1, - evaluatorId, - URI("repl:text"), - """ - res = read*("bird:/**.txt").keys - """ - .trimIndent(), - "res", - ) - ) - val listResourcesRequest = client.receive() - client.send( - ListResourcesResponse( - listResourcesRequest.requestId, - listResourcesRequest.evaluatorId, - null, - null, - ) - ) - val evaluateResponse = client.receive() - assertThat(evaluateResponse.result?.debugYaml) - .isEqualTo( - """ - - 6 - - [] - """ - .trimIndent() - ) - } - - @Test - fun `glob resource error`() { - val reader = ResourceReaderSpec("bird", true, true) - val evaluatorId = client.sendCreateEvaluatorRequest(resourceReaders = listOf(reader)) - client.send( - EvaluateRequest( - 1, - evaluatorId, - URI("repl:text"), - """ - res = read*("bird:/**.txt").keys - """ - .trimIndent(), - "res", - ) - ) - val listResourcesRequest = client.receive() - assertThat(listResourcesRequest.uri.toString()).isEqualTo("bird:/") - client.send( - ListResourcesResponse( - listResourcesRequest.requestId, - listResourcesRequest.evaluatorId, - null, - "didnt work", - ) - ) - val evaluateResponse = client.receive() - assertThat(evaluateResponse.error) - .isEqualTo( - """ - –– Pkl Error –– - I/O error resolving glob pattern `bird:/**.txt`. - IOException: didnt work - - 1 | res = read*("bird:/**.txt").keys - ^^^^^^^^^^^^^^^^^^^^^ - at text#res (repl:text) - - 1 | res - ^^^ - at (repl:text) - - """ - .trimIndent() - ) - } - - @Test - fun `read module`() { - val reader = ModuleReaderSpec("bird", true, true, false) - val evaluatorId = client.sendCreateEvaluatorRequest(moduleReaders = listOf(reader)) - - client.send( - EvaluateRequest( - 1, - evaluatorId, - URI("repl:text"), - """res = import("bird:/pigeon.pkl").value""", - "res", - ) - ) - - val readModuleMsg = client.receive() - assertThat(readModuleMsg.uri.toString()).isEqualTo("bird:/pigeon.pkl") - assertThat(readModuleMsg.evaluatorId).isEqualTo(evaluatorId) - - client.send(ReadModuleResponse(readModuleMsg.requestId, evaluatorId, "value = 5", null)) - - val evaluateResponse = client.receive() - assertThat(evaluateResponse.error).isNull() - val unpacker = MessagePack.newDefaultUnpacker(evaluateResponse.result) - val value = unpacker.unpackValue() - assertThat(value.asIntegerValue().asInt()).isEqualTo(5) - } - - @Test - fun `read module -- null contents and null error`() { - val reader = ModuleReaderSpec("bird", true, true, false) - val evaluatorId = client.sendCreateEvaluatorRequest(moduleReaders = listOf(reader)) - - client.send( - EvaluateRequest( - requestId = 1, - evaluatorId = evaluatorId, - moduleUri = URI("repl:text"), - moduleText = """res = import("bird:/pigeon.pkl")""", - expr = "res", - ) - ) - - val readModuleMsg = client.receive() - assertThat(readModuleMsg.uri.toString()).isEqualTo("bird:/pigeon.pkl") - assertThat(readModuleMsg.evaluatorId).isEqualTo(evaluatorId) - - client.send(ReadModuleResponse(readModuleMsg.requestId, evaluatorId, null, null)) - - val evaluateResponse = client.receive() - assertThat(evaluateResponse.error).isNull() - val unpacker = MessagePack.newDefaultUnpacker(evaluateResponse.result) - val value = unpacker.unpackValue().asArrayValue().list() - assertThat(value[0].asIntegerValue().asLong()).isEqualTo(0x1) - assertThat(value[1].asStringValue().asString()).isEqualTo("pigeon") - assertThat(value[3].asArrayValue().list()).isEmpty() - } - - @Test - fun `read module error`() { - val reader = ModuleReaderSpec("bird", true, true, false) - val evaluatorId = client.sendCreateEvaluatorRequest(moduleReaders = listOf(reader)) - - client.send( - EvaluateRequest( - 1, - evaluatorId, - URI("repl:text"), - """res = import("bird:/pigeon.pkl").value""", - "res", - ) - ) - - val readModuleMsg = client.receive() - assertThat(readModuleMsg.uri.toString()).isEqualTo("bird:/pigeon.pkl") - assertThat(readModuleMsg.evaluatorId).isEqualTo(evaluatorId) - - client.send( - ReadModuleResponse(readModuleMsg.requestId, evaluatorId, null, "Don't know where Pigeon is") - ) - - val evaluateResponse = client.receive() - assertThat(evaluateResponse.error).contains("Don't know where Pigeon is") - } - - @Test - fun `glob module`() { - val reader = ModuleReaderSpec("bird", true, true, true) - val evaluatorId = client.sendCreateEvaluatorRequest(moduleReaders = listOf(reader)) - - client.send( - EvaluateRequest( - 1, - evaluatorId, - URI("repl:text"), - """res = import*("bird:/**.pkl").keys""", - "res", - ) - ) - - val listModulesMsg = client.receive() - assertThat(listModulesMsg.uri.scheme).isEqualTo("bird") - assertThat(listModulesMsg.uri.path).isEqualTo("/") - client.send( - ListModulesResponse( - listModulesMsg.requestId, - evaluatorId, - listOf( - PathElement("birds", true), - PathElement("majesticBirds", true), - PathElement("Person.pkl", false), - ), - null, - ) - ) - val listModulesMsg2 = client.receive() - assertThat(listModulesMsg2.uri.scheme).isEqualTo("bird") - assertThat(listModulesMsg2.uri.path).isEqualTo("/birds/") - client.send( - ListModulesResponse( - listModulesMsg2.requestId, - listModulesMsg2.evaluatorId, - listOf(PathElement("pigeon.pkl", false), PathElement("parrot.pkl", false)), - null, - ) - ) - val listModulesMsg3 = client.receive() - assertThat(listModulesMsg3.uri.scheme).isEqualTo("bird") - assertThat(listModulesMsg3.uri.path).isEqualTo("/majesticBirds/") - client.send( - ListModulesResponse( - listModulesMsg3.requestId, - listModulesMsg3.evaluatorId, - listOf(PathElement("barnOwl.pkl", false), PathElement("elfOwl.pkl", false)), - null, - ) - ) - - val evaluateResponse = client.receive() - assertThat(evaluateResponse.result?.debugRendering) - .isEqualTo( - """ - - 6 - - - - bird:/Person.pkl - - bird:/birds/parrot.pkl - - bird:/birds/pigeon.pkl - - bird:/majesticBirds/barnOwl.pkl - - bird:/majesticBirds/elfOwl.pkl - """ - .trimIndent() - ) - } - - @Test - fun `glob module -- null pathElements and null error`() { - val reader = ModuleReaderSpec("bird", true, true, true) - val evaluatorId = client.sendCreateEvaluatorRequest(moduleReaders = listOf(reader)) - - client.send( - EvaluateRequest( - 1, - evaluatorId, - URI("repl:text"), - """res = import*("bird:/**.pkl").keys""", - "res", - ) - ) - val listModulesMsg = client.receive() - client.send(ListModulesResponse(listModulesMsg.requestId, evaluatorId, null, null)) - - val evaluateResponse = client.receive() - assertThat(evaluateResponse.result?.debugRendering) - .isEqualTo( - """ - - 6 - - [] - """ - .trimIndent() - ) - } - - @Test - fun `glob module error`() { - val reader = ModuleReaderSpec("bird", true, true, true) - val evaluatorId = client.sendCreateEvaluatorRequest(moduleReaders = listOf(reader)) - - client.send( - EvaluateRequest( - 1, - evaluatorId, - URI("repl:text"), - """res = import*("bird:/**.pkl").keys""", - "res", - ) - ) - - val listModulesMsg = client.receive() - assertThat(listModulesMsg.uri.scheme).isEqualTo("bird") - assertThat(listModulesMsg.uri.path).isEqualTo("/") - client.send(ListModulesResponse(listModulesMsg.requestId, evaluatorId, null, "nope")) - val evaluateResponse = client.receive() - assertThat(evaluateResponse.error) - .isEqualTo( - """ - –– Pkl Error –– - I/O error resolving glob pattern `bird:/**.pkl`. - IOException: nope - - 1 | res = import*("bird:/**.pkl").keys - ^^^^^^^^^^^^^^^^^^^^^^^ - at text#res (repl:text) - - 1 | res - ^^^ - at (repl:text) - - """ - .trimIndent() - ) - } - - @Test - fun `import triple-dot path`() { - val reader = ModuleReaderSpec("bird", true, true, true) - val evaluatorId = client.sendCreateEvaluatorRequest(moduleReaders = listOf(reader)) - - client.send( - EvaluateRequest( - 1, - evaluatorId, - URI("bird:/foo/bar/baz.pkl"), - """ - import ".../buz.pkl" - - res = buz.res - """ - .trimIndent(), - "res", - ) - ) - val readModuleRequest = client.receive() - assertThat(readModuleRequest.uri).isEqualTo(URI("bird:/foo/buz.pkl")) - client.send( - ReadModuleResponse( - readModuleRequest.requestId, - readModuleRequest.evaluatorId, - null, - "not here", - ) - ) - - val readModuleRequest2 = client.receive() - assertThat(readModuleRequest2.uri).isEqualTo(URI("bird:/buz.pkl")) - client.send( - ReadModuleResponse( - readModuleRequest2.requestId, - readModuleRequest2.evaluatorId, - "res = 1", - null, - ) - ) - - val evaluatorResponse = client.receive() - assertThat(evaluatorResponse.result?.debugYaml).isEqualTo("1") - } - - @Test - fun `evaluate error`() { - val evaluatorId = client.sendCreateEvaluatorRequest() - - client.send(EvaluateRequest(1, evaluatorId, URI("repl:text"), """foo = 1""", "foo as String")) - - val evaluateResponse = client.receive() - assertThat(evaluateResponse.requestId()).isEqualTo(1) - assertThat(evaluateResponse.error).contains("Expected value of type") - } - - @Test - fun `evaluate client-provided module reader`() { - val reader = ModuleReaderSpec("bird", true, false, false) - val evaluatorId = client.sendCreateEvaluatorRequest(moduleReaders = listOf(reader)) - - client.send(EvaluateRequest(1, evaluatorId, URI("bird:/pigeon.pkl"), null, "output.text")) - - val readModuleRequest = client.receive() - assertThat(readModuleRequest.uri.toString()).isEqualTo("bird:/pigeon.pkl") - - client.send( - ReadModuleResponse( - readModuleRequest.requestId, - evaluatorId, - """ - firstName = "Pigeon" - lastName = "Bird" - fullName = firstName + " " + lastName - """ - .trimIndent(), - null, - ) - ) - - val evaluateResponse = client.receive() - assertThat(evaluateResponse.result).isNotNull - assertThat(evaluateResponse.result?.debugYaml) - .isEqualTo( - """ - | - firstName = "Pigeon" - lastName = "Bird" - fullName = "Pigeon Bird" - """ - .trimIndent() - ) - } - - @Test - fun `concurrent evaluations`() { - val reader = ModuleReaderSpec("bird", true, false, false) - val evaluatorId = client.sendCreateEvaluatorRequest(moduleReaders = listOf(reader)) - client.send(EvaluateRequest(1, evaluatorId, URI("bird:/pigeon.pkl"), null, "output.text")) - - client.send(EvaluateRequest(2, evaluatorId, URI("bird:/parrot.pkl"), null, "output.text")) - - // evaluation is single-threaded; `parrot.pkl` gets evaluated after `pigeon.pkl` completes. - val response11 = client.receive() - assertThat(response11.uri.toString()).isEqualTo("bird:/pigeon.pkl") - - client.send( - ReadModuleResponse( - response11.requestId, - evaluatorId, - """ - firstName = "Pigeon" - lastName = "Bird" - fullName = firstName + " " + lastName - """ - .trimIndent(), - null, - ) - ) - - val response12 = client.receive() - assertThat(response12.result).isNotNull - assertThat(response12.result?.debugYaml) - .isEqualTo( - """ - | - firstName = "Pigeon" - lastName = "Bird" - fullName = "Pigeon Bird" - """ - .trimIndent() - ) - - val response21 = client.receive() - assertThat(response21.uri.toString()).isEqualTo("bird:/parrot.pkl") - - client.send( - ReadModuleResponse( - response21.requestId, - evaluatorId, - """ - firstName = "Parrot" - lastName = "Bird" - fullName = firstName + " " + lastName - """ - .trimIndent(), - null, - ) - ) - - val response22 = client.receive() - assertThat(response22.result).isNotNull - assertThat(response22.result?.debugYaml) - .isEqualTo( - """ - | - firstName = "Parrot" - lastName = "Bird" - fullName = "Parrot Bird" - """ - .trimIndent() - ) - } - - @Test - fun `evaluate with project dependencies`(@TempDir tempDir: Path) { - val cacheDir = tempDir.resolve("cache").createDirectories() - PackageServer.populateCacheDir(cacheDir) - val libDir = tempDir.resolve("lib/").createDirectories() - libDir - .resolve("lib.pkl") - .writeText( - """ - text = "This is from lib" - """ - .trimIndent() - ) - libDir - .resolve("PklProject") - .writeText( - """ - amends "pkl:Project" - - package { - name = "lib" - baseUri = "package://localhost:0/lib" - version = "5.0.0" - packageZipUrl = "https://localhost:0/lib.zip" - } - """ - .trimIndent() - ) - val projectDir = tempDir.resolve("proj/").createDirectories() - val module = projectDir.resolve("mod.pkl") - module.writeText( - """ - import "@birds/Bird.pkl" - import "@lib/lib.pkl" - - res: Bird = new { - name = "Birdie" - favoriteFruit { name = "dragonfruit" } - } - - libContents = lib - """ - .trimIndent() - ) - val dollar = '$' - projectDir - .resolve("PklProject.deps.json") - .writeText( - """ - { - "schemaVersion": 1, - "resolvedDependencies": { - "package://localhost:0/birds@0": { - "type": "remote", - "uri": "projectpackage://localhost:0/birds@0.5.0", - "checksums": { - "sha256": "${dollar}skipChecksumVerification" - } - }, - "package://localhost:0/fruit@1": { - "type": "remote", - "uri": "projectpackage://localhost:0/fruit@1.0.5", - "checksums": { - "sha256": "${dollar}skipChecksumVerification" - } - }, - "package://localhost:0/lib@5": { - "type": "local", - "uri": "projectpackage://localhost:0/lib@5.0.0", - "path": "../lib" - } - } - } - - """ - .trimIndent() - ) - val evaluatorId = - client.sendCreateEvaluatorRequest( - cacheDir = cacheDir, - project = - Project( - projectDir.resolve("PklProject").toUri(), - null, - mapOf( - "birds" to RemoteDependency(URI("package://localhost:0/birds@0.5.0"), null), - "lib" to - Project( - libDir.toUri().resolve("PklProject"), - URI("package://localhost:0/lib@5.0.0"), - emptyMap(), - ), - ), - ), - ) - client.send(EvaluateRequest(1, evaluatorId, module.toUri(), null, "output.text")) - val resp2 = client.receive() - assertThat(resp2.error).isNull() - assertThat(resp2.result).isNotNull() - assertThat(resp2.result?.debugRendering?.trim()) - .isEqualTo( - """ - | - res { - name = "Birdie" - favoriteFruit { - name = "dragonfruit" - } - } - libContents { - text = "This is from lib" - } - """ - .trimIndent() - ) - } - - private val ByteArray.debugYaml - get() = MessagePackDebugRenderer(this).output.trimIndent() - - private val ByteArray.debugRendering: String - get() = MessagePackDebugRenderer(this).output -} diff --git a/pkl-commons-test/gradle.lockfile b/pkl-commons-test/gradle.lockfile index 65d733216..4b36e46ac 100644 --- a/pkl-commons-test/gradle.lockfile +++ b/pkl-commons-test/gradle.lockfile @@ -4,6 +4,12 @@ net.bytebuddy:byte-buddy:1.15.11=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.apiguardian:apiguardian-api:1.1.2=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,testCompileClasspath,testImplementationDependenciesMetadata,testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.assertj:assertj-core:3.27.3=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.polyglot:polyglot:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=runtimeClasspath,testRuntimeClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath @@ -39,6 +45,9 @@ org.junit.platform:junit-platform-engine:1.8.2=testJdk17RuntimeClasspath org.junit.platform:junit-platform-launcher:1.8.2=testJdk17RuntimeClasspath org.junit:junit-bom:5.11.4=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata org.junit:junit-bom:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath +org.msgpack:msgpack-core:0.9.8=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.opentest4j:opentest4j:1.2.0=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath org.opentest4j:opentest4j:1.3.0=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata +org.organicdesign:Paguro:3.10.3=runtimeClasspath,testRuntimeClasspath +org.snakeyaml:snakeyaml-engine:2.9=runtimeClasspath,testRuntimeClasspath empty=annotationProcessor,compileOnlyDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,runtimeOnlyDependenciesMetadata,sourcesJar,testAnnotationProcessor,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testIntransitiveDependenciesMetadata,testJdk17AnnotationProcessor,testJdk17ApiDependenciesMetadata,testJdk17CompileOnlyDependenciesMetadata,testJdk17IntransitiveDependenciesMetadata,testJdk17KotlinScriptDefExtensions,testKotlinScriptDef,testKotlinScriptDefExtensions diff --git a/pkl-commons-test/pkl-commons-test.gradle.kts b/pkl-commons-test/pkl-commons-test.gradle.kts index 7c51898bb..bce04a1e2 100644 --- a/pkl-commons-test/pkl-commons-test.gradle.kts +++ b/pkl-commons-test/pkl-commons-test.gradle.kts @@ -27,7 +27,10 @@ dependencies { api(libs.junitEngine) api(libs.junitParams) api(projects.pklCommons) // for convenience + implementation(projects.pklCore) + implementation(projects.pklServer) implementation(libs.assertj) + implementation(libs.msgpack) } /** diff --git a/pkl-server/src/test/kotlin/org/pkl/server/MessagePackDebugRenderer.kt b/pkl-commons-test/src/main/kotlin/org/pkl/commons/test/MessagePackDebugRenderer.kt similarity index 94% rename from pkl-server/src/test/kotlin/org/pkl/server/MessagePackDebugRenderer.kt rename to pkl-commons-test/src/main/kotlin/org/pkl/commons/test/MessagePackDebugRenderer.kt index 71e7f7156..87d7362d2 100644 --- a/pkl-server/src/test/kotlin/org/pkl/server/MessagePackDebugRenderer.kt +++ b/pkl-commons-test/src/main/kotlin/org/pkl/commons/test/MessagePackDebugRenderer.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.pkl.server +package org.pkl.commons.test import java.lang.IllegalStateException import org.msgpack.core.MessagePack @@ -73,7 +73,7 @@ class MessagePackDebugRenderer(bytes: ByteArray) { sb.append("[]") return } - for (i in 0 until size) { + repeat(size) { newline() sb.append("- ") incIndent() @@ -87,7 +87,7 @@ class MessagePackDebugRenderer(bytes: ByteArray) { sb.append("{}") return } - for (i in 0 until size) { + repeat(size) { newline() renderKey() incIndent() @@ -105,3 +105,6 @@ class MessagePackDebugRenderer(bytes: ByteArray) { sb.toString().removePrefix("\n") } } + +val ByteArray.msgpackDebugRendering: String + get() = MessagePackDebugRenderer(this).output diff --git a/pkl-server/src/test/kotlin/org/pkl/server/AbstractServerTest.kt b/pkl-commons-test/src/main/kotlin/org/pkl/commons/test/server/AbstractServerTest.kt similarity index 95% rename from pkl-server/src/test/kotlin/org/pkl/server/AbstractServerTest.kt rename to pkl-commons-test/src/main/kotlin/org/pkl/commons/test/server/AbstractServerTest.kt index 21a5c3206..334b42f50 100644 --- a/pkl-server/src/test/kotlin/org/pkl/server/AbstractServerTest.kt +++ b/pkl-commons-test/src/main/kotlin/org/pkl/commons/test/server/AbstractServerTest.kt @@ -13,12 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.pkl.server +package org.pkl.commons.test.server import java.net.URI import java.nio.file.Path +import java.util.concurrent.AbstractExecutorService import java.util.concurrent.ExecutorService import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit import kotlin.io.path.createDirectories import kotlin.io.path.outputStream import kotlin.io.path.writeText @@ -29,17 +31,46 @@ import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.io.TempDir import org.msgpack.core.MessagePack +import org.pkl.commons.test.MessagePackDebugRenderer import org.pkl.commons.test.PackageServer +import org.pkl.commons.test.msgpackDebugRendering import org.pkl.core.messaging.Messages.* import org.pkl.core.module.PathElement +import org.pkl.server.* +@Suppress("FunctionName") abstract class AbstractServerTest { companion object { - /** Set to `true` to bypass messagepack serialization when running [JvmServerTest]. */ - internal const val USE_DIRECT_TRANSPORT = false + /** Set to `true` to bypass messagepack serialization when running JvmServerTest. */ + const val USE_DIRECT_TRANSPORT = false lateinit var executor: ExecutorService + fun createDirectExecutor(): ExecutorService = + object : AbstractExecutorService() { + override fun execute(command: Runnable) { + command.run() + } + + override fun shutdown() {} + + override fun shutdownNow(): MutableList { + throw UnsupportedOperationException("shutdownNow") + } + + override fun isShutdown(): Boolean { + throw UnsupportedOperationException("isShutdown") + } + + override fun isTerminated(): Boolean { + throw UnsupportedOperationException("isTerminated") + } + + override fun awaitTermination(timeout: Long, unit: TimeUnit): Boolean { + throw UnsupportedOperationException("awaitTermination") + } + } + @BeforeAll @JvmStatic fun beforeAll() { @@ -521,7 +552,7 @@ abstract class AbstractServerTest { ) val evaluateResponse = client.receive() - assertThat(evaluateResponse.result?.debugRendering) + assertThat(evaluateResponse.result?.msgpackDebugRendering) .isEqualTo( """ - 6 @@ -554,7 +585,7 @@ abstract class AbstractServerTest { client.send(ListModulesResponse(listModulesMsg.requestId, evaluatorId, null, null)) val evaluateResponse = client.receive() - assertThat(evaluateResponse.result?.debugRendering) + assertThat(evaluateResponse.result?.msgpackDebugRendering) .isEqualTo( """ - 6 @@ -608,7 +639,8 @@ abstract class AbstractServerTest { fun `read and evaluate module path from jar`(@TempDir tempDir: Path) { val jarFile = tempDir.resolve("resource1.jar") jarFile.outputStream().use { outStream -> - javaClass.getResourceAsStream("resource1.jar")!!.use { inStream -> + javaClass.getResourceAsStream("/org/pkl/commons/test/server/resource1.jar")!!.use { inStream + -> inStream.copyTo(outStream) } } @@ -913,7 +945,7 @@ abstract class AbstractServerTest { val resp2 = client.receive() assertThat(resp2.error).isNull() assertThat(resp2.result).isNotNull() - assertThat(resp2.result?.debugRendering?.trim()) + assertThat(resp2.result?.msgpackDebugRendering?.trim()) .isEqualTo( """ | diff --git a/pkl-server/src/test/kotlin/org/pkl/server/TestTransport.kt b/pkl-commons-test/src/main/kotlin/org/pkl/commons/test/server/TestTransport.kt similarity index 92% rename from pkl-server/src/test/kotlin/org/pkl/server/TestTransport.kt rename to pkl-commons-test/src/main/kotlin/org/pkl/commons/test/server/TestTransport.kt index 5782c335e..4a2237b80 100644 --- a/pkl-server/src/test/kotlin/org/pkl/server/TestTransport.kt +++ b/pkl-commons-test/src/main/kotlin/org/pkl/commons/test/server/TestTransport.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.pkl.server +package org.pkl.commons.test.server import java.util.concurrent.ArrayBlockingQueue import java.util.concurrent.BlockingQueue diff --git a/pkl-server/src/test/resources/org/pkl/server/resource1.jar b/pkl-commons-test/src/main/resources/org/pkl/commons/test/server/resource1.jar similarity index 100% rename from pkl-server/src/test/resources/org/pkl/server/resource1.jar rename to pkl-commons-test/src/main/resources/org/pkl/commons/test/server/resource1.jar diff --git a/pkl-gradle/gradle.lockfile b/pkl-gradle/gradle.lockfile index 6a0085eb3..3c2c2d528 100644 --- a/pkl-gradle/gradle.lockfile +++ b/pkl-gradle/gradle.lockfile @@ -14,6 +14,12 @@ com.github.ajalt.mordant:mordant:3.0.1=compileClasspath,compileOnlyDependenciesM net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.assertj:assertj-core:3.27.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.polyglot:polyglot:24.1.2=testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=testRuntimeClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath @@ -49,6 +55,9 @@ org.junit.platform:junit-platform-engine:1.8.2=testJdk17RuntimeClasspath org.junit.platform:junit-platform-launcher:1.8.2=testJdk17RuntimeClasspath org.junit:junit-bom:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata org.junit:junit-bom:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath +org.msgpack:msgpack-core:0.9.8=testRuntimeClasspath org.opentest4j:opentest4j:1.2.0=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata +org.organicdesign:Paguro:3.10.3=testRuntimeClasspath +org.snakeyaml:snakeyaml-engine:2.9=testRuntimeClasspath empty=annotationProcessor,apiDependenciesMetadata,implementationDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,runtimeClasspath,runtimeOnlyDependenciesMetadata,signatures,sourcesJar,testAnnotationProcessor,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testIntransitiveDependenciesMetadata,testJdk17AnnotationProcessor,testJdk17ApiDependenciesMetadata,testJdk17CompileOnlyDependenciesMetadata,testJdk17IntransitiveDependenciesMetadata,testJdk17KotlinScriptDefExtensions,testKotlinScriptDef,testKotlinScriptDefExtensions diff --git a/pkl-parser/gradle.lockfile b/pkl-parser/gradle.lockfile index 6364ddd8c..fe45acb02 100644 --- a/pkl-parser/gradle.lockfile +++ b/pkl-parser/gradle.lockfile @@ -11,6 +11,12 @@ org.antlr:ST4:4.3=antlr org.antlr:antlr-runtime:3.5.2=antlr org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata org.assertj:assertj-core:3.27.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.polyglot:polyglot:24.1.2=testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=testRuntimeClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath @@ -46,6 +52,9 @@ org.junit.platform:junit-platform-engine:1.8.2=testJdk17RuntimeClasspath org.junit.platform:junit-platform-launcher:1.8.2=testJdk17RuntimeClasspath org.junit:junit-bom:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata org.junit:junit-bom:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath +org.msgpack:msgpack-core:0.9.8=testRuntimeClasspath org.opentest4j:opentest4j:1.2.0=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.organicdesign:Paguro:3.10.3=testRuntimeClasspath +org.snakeyaml:snakeyaml-engine:2.9=testRuntimeClasspath empty=annotationProcessor,apiDependenciesMetadata,generatorAnnotationProcessor,generatorApiDependenciesMetadata,generatorCompileClasspath,generatorCompileOnlyDependenciesMetadata,generatorImplementationDependenciesMetadata,generatorIntransitiveDependenciesMetadata,generatorKotlinScriptDefExtensions,generatorRuntimeClasspath,implementationDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDefExtensions,runtimeClasspath,sourcesJar,testAnnotationProcessor,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testIntransitiveDependenciesMetadata,testJdk17AnnotationProcessor,testJdk17ApiDependenciesMetadata,testJdk17CompileOnlyDependenciesMetadata,testJdk17IntransitiveDependenciesMetadata,testJdk17KotlinScriptDefExtensions,testKotlinScriptDefExtensions diff --git a/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorSnippetTests.kt b/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorSnippetTests.kt index e8bfc77f9..e8f20b1c5 100644 --- a/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorSnippetTests.kt +++ b/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorSnippetTests.kt @@ -20,6 +20,7 @@ import kotlin.Pair import kotlin.reflect.KClass import org.junit.platform.commons.annotation.Testable import org.pkl.commons.test.InputOutputTestEngine +import org.pkl.commons.test.msgpackDebugRendering import org.pkl.core.* import org.pkl.core.http.HttpClient import org.pkl.core.module.ModuleKeyFactories @@ -63,9 +64,6 @@ class BinaryEvaluatorSnippetTestEngine : InputOutputTestEngine() { override fun generateOutputFor(inputFile: Path): Pair { val bytes = evaluator.evaluate(ModuleSource.path(inputFile), null) - return true to bytes.debugRendering.stripFilePaths() + return true to bytes.msgpackDebugRendering.stripFilePaths() } } - -val ByteArray.debugRendering: String - get() = MessagePackDebugRenderer(this).output diff --git a/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorTest.kt b/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorTest.kt index fa0bbcbcb..796c02c15 100644 --- a/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorTest.kt +++ b/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorTest.kt @@ -20,6 +20,7 @@ import java.util.regex.Pattern import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import org.pkl.commons.test.msgpackDebugRendering import org.pkl.core.* import org.pkl.core.http.HttpClient import org.pkl.core.module.ModuleKeyFactories @@ -53,7 +54,7 @@ class BinaryEvaluatorTest { @Test fun `evaluate whole module`() { val bytes = evaluate("foo = 1", null) - assertThat(bytes.debugRendering) + assertThat(bytes.msgpackDebugRendering) .isEqualTo( """ - 1 diff --git a/pkl-server/src/test/kotlin/org/pkl/server/JvmServerTest.kt b/pkl-server/src/test/kotlin/org/pkl/server/JvmServerTest.kt index 84dbf6369..8681ba746 100644 --- a/pkl-server/src/test/kotlin/org/pkl/server/JvmServerTest.kt +++ b/pkl-server/src/test/kotlin/org/pkl/server/JvmServerTest.kt @@ -19,6 +19,8 @@ import java.io.PipedInputStream import java.io.PipedOutputStream import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach +import org.pkl.commons.test.server.AbstractServerTest +import org.pkl.commons.test.server.TestTransport import org.pkl.core.messaging.MessageTransport import org.pkl.core.messaging.MessageTransports import org.pkl.core.util.Pair diff --git a/pkl-server/src/test/kotlin/org/pkl/server/NativeServerTest.kt b/pkl-server/src/test/kotlin/org/pkl/server/NativeServerTest.kt index c34c28625..08be09535 100644 --- a/pkl-server/src/test/kotlin/org/pkl/server/NativeServerTest.kt +++ b/pkl-server/src/test/kotlin/org/pkl/server/NativeServerTest.kt @@ -18,6 +18,8 @@ package org.pkl.server import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach import org.pkl.commons.test.PklExecutablePaths +import org.pkl.commons.test.server.AbstractServerTest +import org.pkl.commons.test.server.TestTransport import org.pkl.core.messaging.MessageTransports class NativeServerTest : AbstractServerTest() {