mirror of
https://github.com/apple/pkl.git
synced 2026-01-11 22:30:54 +01:00
Run spotless apply
This commit is contained in:
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* Copyright © 2024 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.
|
||||
*/
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.LinkOption
|
||||
|
||||
@@ -17,8 +32,7 @@ val pklHistoricalDistributions: Configuration by configurations.creating
|
||||
// (Pkl distributions used by EmbeddedExecutor are isolated via class loaders.)
|
||||
dependencies {
|
||||
pklDistributionCurrent(project(":pkl-config-java", "fatJar"))
|
||||
@Suppress("UnstableApiUsage")
|
||||
pklHistoricalDistributions(libs.pklConfigJavaAll025)
|
||||
@Suppress("UnstableApiUsage") pklHistoricalDistributions(libs.pklConfigJavaAll025)
|
||||
|
||||
implementation(libs.slf4jApi)
|
||||
|
||||
@@ -28,67 +42,60 @@ dependencies {
|
||||
}
|
||||
|
||||
// TODO why is this needed? Without this, we get error:
|
||||
// `Entry org/pkl/executor/EmbeddedExecutor.java is a duplicate but no duplicate handling strategy has been set.`
|
||||
// `Entry org/pkl/executor/EmbeddedExecutor.java is a duplicate but no duplicate handling strategy
|
||||
// has been set.`
|
||||
// However, we do not have multiple of these Java files.
|
||||
tasks.named<Jar>("sourcesJar") {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
}
|
||||
tasks.named<Jar>("sourcesJar") { duplicatesStrategy = DuplicatesStrategy.EXCLUDE }
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
named<MavenPublication>("library") {
|
||||
pom {
|
||||
url.set("https://github.com/apple/pkl/tree/main/pkl-executor")
|
||||
description.set("""
|
||||
description.set(
|
||||
"""
|
||||
Library for executing Pkl code in a sandboxed environment.
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir("src/main/java")
|
||||
}
|
||||
}
|
||||
}
|
||||
sourceSets { main { java { srcDir("src/main/java") } } }
|
||||
|
||||
val prepareHistoricalDistributions by tasks.registering {
|
||||
val outputDir = layout.buildDirectory.dir("pklHistoricalDistributions")
|
||||
inputs.files(pklHistoricalDistributions.files())
|
||||
outputs.dir(outputDir)
|
||||
doLast {
|
||||
val distributionDir = outputDir.get().asFile.toPath()
|
||||
.also(Files::createDirectories)
|
||||
for (file in pklHistoricalDistributions.files) {
|
||||
val target = distributionDir.resolve(file.name)
|
||||
// Create normal files on Windows, symlink on macOS/linux (need admin priveleges to create
|
||||
// symlinks on Windows)
|
||||
if (buildInfo.os.isWindows) {
|
||||
if (!Files.isRegularFile(target, LinkOption.NOFOLLOW_LINKS)) {
|
||||
if (Files.exists(target)) {
|
||||
Files.delete(target)
|
||||
val prepareHistoricalDistributions by
|
||||
tasks.registering {
|
||||
val outputDir = layout.buildDirectory.dir("pklHistoricalDistributions")
|
||||
inputs.files(pklHistoricalDistributions.files())
|
||||
outputs.dir(outputDir)
|
||||
doLast {
|
||||
val distributionDir = outputDir.get().asFile.toPath().also(Files::createDirectories)
|
||||
for (file in pklHistoricalDistributions.files) {
|
||||
val target = distributionDir.resolve(file.name)
|
||||
// Create normal files on Windows, symlink on macOS/linux (need admin priveleges to create
|
||||
// symlinks on Windows)
|
||||
if (buildInfo.os.isWindows) {
|
||||
if (!Files.isRegularFile(target, LinkOption.NOFOLLOW_LINKS)) {
|
||||
if (Files.exists(target)) {
|
||||
Files.delete(target)
|
||||
}
|
||||
Files.copy(file.toPath(), target)
|
||||
}
|
||||
Files.copy(file.toPath(), target)
|
||||
}
|
||||
} else {
|
||||
if (!Files.isSymbolicLink(target)) {
|
||||
if (Files.exists(target)) {
|
||||
Files.delete(target)
|
||||
} else {
|
||||
if (!Files.isSymbolicLink(target)) {
|
||||
if (Files.exists(target)) {
|
||||
Files.delete(target)
|
||||
}
|
||||
Files.createSymbolicLink(target, file.toPath())
|
||||
}
|
||||
Files.createSymbolicLink(target, file.toPath())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val prepareTest by tasks.registering {
|
||||
dependsOn(pklDistributionCurrent, prepareHistoricalDistributions)
|
||||
}
|
||||
val prepareTest by
|
||||
tasks.registering { dependsOn(pklDistributionCurrent, prepareHistoricalDistributions) }
|
||||
|
||||
tasks.test {
|
||||
dependsOn(prepareTest)
|
||||
}
|
||||
tasks.test { dependsOn(prepareTest) }
|
||||
|
||||
@@ -1,8 +1,28 @@
|
||||
/**
|
||||
* Copyright © 2024 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.executor
|
||||
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.time.Duration
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.exists
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.AfterAll
|
||||
import org.junit.jupiter.api.Disabled
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import org.junit.jupiter.api.condition.DisabledOnOs
|
||||
@@ -15,17 +35,11 @@ import org.pkl.commons.test.FilteringClassLoader
|
||||
import org.pkl.commons.test.PackageServer
|
||||
import org.pkl.commons.toPath
|
||||
import org.pkl.core.Release
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.time.Duration
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.exists
|
||||
|
||||
class EmbeddedExecutorTest {
|
||||
/**
|
||||
* An executor that uses a particular combination of ExecutorSpiOptions version,
|
||||
* pkl-executor version, and Pkl distribution version.
|
||||
* An executor that uses a particular combination of ExecutorSpiOptions version, pkl-executor
|
||||
* version, and Pkl distribution version.
|
||||
*/
|
||||
class TestExecutor(
|
||||
private val executor: Executor,
|
||||
@@ -33,12 +47,11 @@ class EmbeddedExecutorTest {
|
||||
private val name: String
|
||||
) {
|
||||
fun evaluatePath(modulePath: Path, optionSpec: ExecutorOptions.Builder.() -> Unit): String {
|
||||
val options = ExecutorOptions.builder()
|
||||
.apply(optionSpec)
|
||||
.spiOptionsVersion(spiOptionsVersion)
|
||||
.build()
|
||||
val options =
|
||||
ExecutorOptions.builder().apply(optionSpec).spiOptionsVersion(spiOptionsVersion).build()
|
||||
return executor.evaluatePath(modulePath, options)
|
||||
}
|
||||
|
||||
override fun toString(): String = name
|
||||
}
|
||||
|
||||
@@ -50,19 +63,17 @@ class EmbeddedExecutorTest {
|
||||
|
||||
// This context has a pkl-executor version that is lower than the distribution version.
|
||||
TestExecutor(executor1_2.value, 1, "SpiOptions1, Executor1, Distribution2"),
|
||||
|
||||
TestExecutor(executor2_1.value, 1, "SpiOptions1, Executor2, Distribution1"),
|
||||
TestExecutor(executor2_1.value, 2, "SpiOptions2, Executor2, Distribution1"),
|
||||
|
||||
TestExecutor(executor2_2.value, 1, "SpiOptions1, Executor2, Distribution2"),
|
||||
TestExecutor(executor2_2.value, 2, "SpiOptions2, Executor2, Distribution2")
|
||||
)
|
||||
}
|
||||
|
||||
private val currentExecutor: TestExecutor by lazy {
|
||||
TestExecutor(executor2_2.value, -1, "currentExecutor")
|
||||
private val currentExecutor: TestExecutor by lazy {
|
||||
TestExecutor(executor2_2.value, -1, "currentExecutor")
|
||||
}
|
||||
|
||||
|
||||
// A pkl-executor library that supports ExecutorSpiOptions up to v1
|
||||
// and a Pkl distribution that supports ExecutorSpiOptions up to v1.
|
||||
private val executor1_1: Lazy<Executor> = lazy {
|
||||
@@ -86,10 +97,8 @@ class EmbeddedExecutorTest {
|
||||
private val executor2_2: Lazy<Executor> = lazy {
|
||||
EmbeddedExecutor(listOf(pklDistribution2), pklExecutorClassLoader2)
|
||||
}
|
||||
|
||||
private val allExecutors by lazy {
|
||||
listOf(executor1_1, executor1_2, executor2_1, executor2_2)
|
||||
}
|
||||
|
||||
private val allExecutors by lazy { listOf(executor1_1, executor1_2, executor2_1, executor2_2) }
|
||||
|
||||
// a pkl-executor class loader that supports ExecutorSpiOptions up to v1
|
||||
private val pklExecutorClassLoader1: ClassLoader by lazy {
|
||||
@@ -102,7 +111,7 @@ class EmbeddedExecutorTest {
|
||||
private val pklExecutorClassLoader2: ClassLoader by lazy {
|
||||
EmbeddedExecutor::class.java.classLoader
|
||||
}
|
||||
|
||||
|
||||
@AfterAll
|
||||
@JvmStatic
|
||||
fun afterAll() {
|
||||
@@ -114,127 +123,144 @@ class EmbeddedExecutorTest {
|
||||
// a Pkl distribution that supports ExecutorSpiOptions up to v1
|
||||
private val pklDistribution1: Path by lazy {
|
||||
FileTestUtils.rootProjectDir
|
||||
.resolve("pkl-executor/build/pklHistoricalDistributions/pkl-config-java-all-0.25.0.jar").apply {
|
||||
if (!exists()) missingTestFixture()
|
||||
}
|
||||
.resolve("pkl-executor/build/pklHistoricalDistributions/pkl-config-java-all-0.25.0.jar")
|
||||
.apply { if (!exists()) missingTestFixture() }
|
||||
}
|
||||
|
||||
// a Pkl distribution that supports ExecutorSpiOptions up to v2
|
||||
private val pklDistribution2: Path by lazy {
|
||||
FileTestUtils.rootProjectDir
|
||||
.resolve("pkl-config-java/build/libs/pkl-config-java-all-" +
|
||||
"${Release.current().version().withBuild(null).toString().replaceFirst("dev", "SNAPSHOT")}.jar").apply {
|
||||
if (!exists()) missingTestFixture()
|
||||
}
|
||||
.resolve(
|
||||
"pkl-config-java/build/libs/pkl-config-java-all-" +
|
||||
"${Release.current().version().withBuild(null).toString().replaceFirst("dev", "SNAPSHOT")}.jar"
|
||||
)
|
||||
.apply { if (!exists()) missingTestFixture() }
|
||||
}
|
||||
|
||||
|
||||
private fun missingTestFixture(): Nothing =
|
||||
throw AssertionError("Missing test fixture. " +
|
||||
"To fix this problem, run `./gradlew :pkl-executor:prepareTest`.")
|
||||
throw AssertionError(
|
||||
"Missing test fixture. " + "To fix this problem, run `./gradlew :pkl-executor:prepareTest`."
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun extractMinPklVersion() {
|
||||
assertThat(
|
||||
EmbeddedExecutor.extractMinPklVersion(
|
||||
"""
|
||||
EmbeddedExecutor.extractMinPklVersion(
|
||||
"""
|
||||
@ModuleInfo { minPklVersion = "1.2.3" }
|
||||
""".trimIndent()
|
||||
)
|
||||
).isEqualTo(Version.parse("1.2.3"))
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
)
|
||||
.isEqualTo(Version.parse("1.2.3"))
|
||||
|
||||
assertThat(
|
||||
EmbeddedExecutor.extractMinPklVersion(
|
||||
"""
|
||||
EmbeddedExecutor.extractMinPklVersion(
|
||||
"""
|
||||
@ModuleInfo{minPklVersion="1.2.3"}
|
||||
""".trimIndent()
|
||||
)
|
||||
).isEqualTo(Version.parse("1.2.3"))
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
)
|
||||
.isEqualTo(Version.parse("1.2.3"))
|
||||
|
||||
assertThat(
|
||||
EmbeddedExecutor.extractMinPklVersion(
|
||||
"""
|
||||
EmbeddedExecutor.extractMinPklVersion(
|
||||
"""
|
||||
@ModuleInfo { minPklVersion = "1.2.3" }
|
||||
""".trimIndent()
|
||||
)
|
||||
).isEqualTo(Version.parse("1.2.3"))
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
)
|
||||
.isEqualTo(Version.parse("1.2.3"))
|
||||
|
||||
assertThat(
|
||||
EmbeddedExecutor.extractMinPklVersion(
|
||||
"""
|
||||
EmbeddedExecutor.extractMinPklVersion(
|
||||
"""
|
||||
@ModuleInfo {
|
||||
minPklVersion = "1.2.3"
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
).isEqualTo(Version.parse("1.2.3"))
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
)
|
||||
.isEqualTo(Version.parse("1.2.3"))
|
||||
|
||||
assertThat(
|
||||
EmbeddedExecutor.extractMinPklVersion(
|
||||
"""
|
||||
EmbeddedExecutor.extractMinPklVersion(
|
||||
"""
|
||||
@ModuleInfo {
|
||||
author = "foo@bar.apple.com"
|
||||
minPklVersion = "1.2.3"
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
).isEqualTo(Version.parse("1.2.3"))
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
)
|
||||
.isEqualTo(Version.parse("1.2.3"))
|
||||
|
||||
assertThat(
|
||||
EmbeddedExecutor.extractMinPklVersion(
|
||||
"""
|
||||
EmbeddedExecutor.extractMinPklVersion(
|
||||
"""
|
||||
@ModuleInfo {
|
||||
minPklVersion = "1.2.3"
|
||||
author = "foo@bar.apple.com"
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
).isEqualTo(Version.parse("1.2.3"))
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
)
|
||||
.isEqualTo(Version.parse("1.2.3"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `create embedded executor with non-existing Pkl distribution`() {
|
||||
val e = assertThrows<IllegalArgumentException> {
|
||||
val e =
|
||||
assertThrows<IllegalArgumentException> {
|
||||
Executors.embedded(listOf("/non/existing".toPath()))
|
||||
}
|
||||
}
|
||||
|
||||
val sep = File.separatorChar
|
||||
assertThat(e.message)
|
||||
.contains("Cannot find Jar file")
|
||||
.contains("${sep}non${sep}existing")
|
||||
assertThat(e.message).contains("Cannot find Jar file").contains("${sep}non${sep}existing")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `create embedded executor with invalid Pkl distribution that is not a Jar file`(@TempDir tempDir: Path) {
|
||||
fun `create embedded executor with invalid Pkl distribution that is not a Jar file`(
|
||||
@TempDir tempDir: Path
|
||||
) {
|
||||
val file = Files.createFile(tempDir.resolve("pkl.jar"))
|
||||
val e = assertThrows<IllegalArgumentException> {
|
||||
Executors.embedded(listOf(file))
|
||||
}
|
||||
val e = assertThrows<IllegalArgumentException> { Executors.embedded(listOf(file)) }
|
||||
|
||||
assertThat(e.message)
|
||||
.contains("Cannot find service")
|
||||
.contains("pkl.jar")
|
||||
assertThat(e.message).contains("Cannot find service").contains("pkl.jar")
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("getAllTestExecutors")
|
||||
fun `evaluate a module that is missing a ModuleInfo annotation`(executor: TestExecutor, @TempDir tempDir: Path) {
|
||||
fun `evaluate a module that is missing a ModuleInfo annotation`(
|
||||
executor: TestExecutor,
|
||||
@TempDir tempDir: Path
|
||||
) {
|
||||
val pklFile = tempDir.resolve("test.pkl")
|
||||
pklFile.toFile().writeText(
|
||||
"""
|
||||
pklFile
|
||||
.toFile()
|
||||
.writeText(
|
||||
"""
|
||||
module test
|
||||
|
||||
x = 1
|
||||
""".trimIndent()
|
||||
)
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
val e = assertThrows<ExecutorException> {
|
||||
executor.evaluatePath(pklFile) {
|
||||
allowedModules("file:")
|
||||
allowedResources("prop:")
|
||||
rootDir(tempDir)
|
||||
val e =
|
||||
assertThrows<ExecutorException> {
|
||||
executor.evaluatePath(pklFile) {
|
||||
allowedModules("file:")
|
||||
allowedResources("prop:")
|
||||
rootDir(tempDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(e.message)
|
||||
.contains("Pkl module `test.pkl` does not state which Pkl version it requires.")
|
||||
@@ -242,24 +268,31 @@ class EmbeddedExecutorTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("getAllTestExecutors")
|
||||
fun `evaluate a module that requests an incompatible Pkl version`(executor: TestExecutor, @TempDir tempDir: Path) {
|
||||
fun `evaluate a module that requests an incompatible Pkl version`(
|
||||
executor: TestExecutor,
|
||||
@TempDir tempDir: Path
|
||||
) {
|
||||
val pklFile = tempDir.resolve("test.pkl")
|
||||
pklFile.toFile().writeText(
|
||||
"""
|
||||
pklFile
|
||||
.toFile()
|
||||
.writeText(
|
||||
"""
|
||||
@ModuleInfo { minPklVersion = "99.99.99" }
|
||||
module test
|
||||
|
||||
x = 1
|
||||
""".trimIndent()
|
||||
)
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
val e = assertThrows<ExecutorException> {
|
||||
executor.evaluatePath(pklFile) {
|
||||
allowedModules("file:")
|
||||
allowedResources("prop:")
|
||||
rootDir(tempDir)
|
||||
val e =
|
||||
assertThrows<ExecutorException> {
|
||||
executor.evaluatePath(pklFile) {
|
||||
allowedModules("file:")
|
||||
allowedResources("prop:")
|
||||
rootDir(tempDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(e.message)
|
||||
.contains("Pkl version `99.99.99` requested by module `test.pkl` is not supported.")
|
||||
@@ -267,94 +300,113 @@ class EmbeddedExecutorTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("getAllTestExecutors")
|
||||
fun `evaluate a module that reads environment variables and external properties`(executor: TestExecutor, @TempDir tempDir: Path) {
|
||||
fun `evaluate a module that reads environment variables and external properties`(
|
||||
executor: TestExecutor,
|
||||
@TempDir tempDir: Path
|
||||
) {
|
||||
val pklFile = tempDir.resolve("test.pkl")
|
||||
pklFile.toFile().writeText(
|
||||
"""
|
||||
pklFile
|
||||
.toFile()
|
||||
.writeText(
|
||||
"""
|
||||
@ModuleInfo { minPklVersion = "0.11.0" }
|
||||
module test
|
||||
|
||||
x = read("env:ENV_VAR")
|
||||
y = read("prop:property")
|
||||
""".trimIndent()
|
||||
)
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
val result = executor.evaluatePath(pklFile) {
|
||||
allowedModules("file:")
|
||||
// should `prop:pkl.outputFormat` be allowed automatically?
|
||||
allowedResources("prop:", "env:")
|
||||
environmentVariables(mapOf("ENV_VAR" to "ENV_VAR"))
|
||||
externalProperties(mapOf("property" to "property"))
|
||||
}
|
||||
val result =
|
||||
executor.evaluatePath(pklFile) {
|
||||
allowedModules("file:")
|
||||
// should `prop:pkl.outputFormat` be allowed automatically?
|
||||
allowedResources("prop:", "env:")
|
||||
environmentVariables(mapOf("ENV_VAR" to "ENV_VAR"))
|
||||
externalProperties(mapOf("property" to "property"))
|
||||
}
|
||||
|
||||
assertThat(result.trim()).isEqualTo(
|
||||
"""
|
||||
assertThat(result.trim())
|
||||
.isEqualTo("""
|
||||
x = "ENV_VAR"
|
||||
y = "property"
|
||||
""".trimIndent().trim()
|
||||
)
|
||||
""".trimIndent().trim())
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("getAllTestExecutors")
|
||||
fun `evaluate a module that depends on another module`(executor: TestExecutor, @TempDir tempDir: Path) {
|
||||
fun `evaluate a module that depends on another module`(
|
||||
executor: TestExecutor,
|
||||
@TempDir tempDir: Path
|
||||
) {
|
||||
val pklFile = tempDir.resolve("test.pkl")
|
||||
pklFile.toFile().writeText(
|
||||
"""
|
||||
pklFile
|
||||
.toFile()
|
||||
.writeText(
|
||||
"""
|
||||
@ModuleInfo { minPklVersion = "0.11.0" }
|
||||
amends "template.pkl"
|
||||
|
||||
foo {
|
||||
bar = 42
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
val templateFile = tempDir.resolve("template.pkl")
|
||||
templateFile.toFile().writeText(
|
||||
"""
|
||||
templateFile
|
||||
.toFile()
|
||||
.writeText(
|
||||
"""
|
||||
foo: Foo
|
||||
|
||||
class Foo {
|
||||
bar: Int
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
val result = executor.evaluatePath(pklFile) {
|
||||
allowedModules("file:")
|
||||
allowedResources("prop:")
|
||||
}
|
||||
val result =
|
||||
executor.evaluatePath(pklFile) {
|
||||
allowedModules("file:")
|
||||
allowedResources("prop:")
|
||||
}
|
||||
|
||||
assertThat(result.trim()).isEqualTo(
|
||||
"""
|
||||
assertThat(result.trim())
|
||||
.isEqualTo("""
|
||||
foo {
|
||||
bar = 42
|
||||
}
|
||||
""".trimIndent().trim()
|
||||
)
|
||||
""".trimIndent().trim())
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("getAllTestExecutors")
|
||||
fun `evaluate a module whose evaluation fails`(executor: TestExecutor, @TempDir tempDir: Path) {
|
||||
val pklFile = tempDir.resolve("test.pkl")
|
||||
pklFile.toFile().writeText(
|
||||
"""
|
||||
pklFile
|
||||
.toFile()
|
||||
.writeText(
|
||||
"""
|
||||
@ModuleInfo { minPklVersion = "0.11.0" }
|
||||
module test
|
||||
|
||||
foo = throw("ouch")
|
||||
""".trimIndent()
|
||||
)
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
val e = assertThrows<ExecutorException> {
|
||||
executor.evaluatePath(pklFile) {
|
||||
allowedModules("file:")
|
||||
allowedResources("prop:")
|
||||
rootDir(tempDir)
|
||||
val e =
|
||||
assertThrows<ExecutorException> {
|
||||
executor.evaluatePath(pklFile) {
|
||||
allowedModules("file:")
|
||||
allowedResources("prop:")
|
||||
rootDir(tempDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(e.message)
|
||||
.contains("ouch")
|
||||
@@ -367,62 +419,73 @@ class EmbeddedExecutorTest {
|
||||
@MethodSource("getAllTestExecutors")
|
||||
fun `time out a module`(executor: TestExecutor, @TempDir tempDir: Path) {
|
||||
val pklFile = tempDir.resolve("test.pkl")
|
||||
pklFile.toFile().writeText(
|
||||
"""
|
||||
pklFile
|
||||
.toFile()
|
||||
.writeText(
|
||||
"""
|
||||
@ModuleInfo { minPklVersion = "0.11.0" }
|
||||
module test
|
||||
|
||||
x = fib(100)
|
||||
|
||||
function fib(n) = if (n < 2) n else fib(n - 1) + fib(n - 2)
|
||||
""".trimIndent()
|
||||
)
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
val e = assertThrows<ExecutorException> {
|
||||
executor.evaluatePath(pklFile) {
|
||||
allowedModules("file:")
|
||||
allowedResources("prop:")
|
||||
rootDir(tempDir)
|
||||
timeout(Duration.ofSeconds(1))
|
||||
val e =
|
||||
assertThrows<ExecutorException> {
|
||||
executor.evaluatePath(pklFile) {
|
||||
allowedModules("file:")
|
||||
allowedResources("prop:")
|
||||
rootDir(tempDir)
|
||||
timeout(Duration.ofSeconds(1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(e.message)
|
||||
.contains("Evaluation timed out after 1 second(s).")
|
||||
assertThat(e.message).contains("Evaluation timed out after 1 second(s).")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `evaluate a module that loads a package`(@TempDir tempDir: Path) {
|
||||
val cacheDir = tempDir.resolve("cache")
|
||||
val pklFile = tempDir.resolve("test.pkl")
|
||||
pklFile.toFile().writeText(
|
||||
"""
|
||||
pklFile
|
||||
.toFile()
|
||||
.writeText(
|
||||
"""
|
||||
@ModuleInfo { minPklVersion = "0.24.0" }
|
||||
module MyModule
|
||||
|
||||
import "package://localhost:0/birds@0.5.0#/Bird.pkl"
|
||||
|
||||
chirpy = new Bird { name = "Chirpy"; favoriteFruit { name = "Orange" } }
|
||||
""".trimIndent()
|
||||
)
|
||||
val result = PackageServer().use { server ->
|
||||
currentExecutor.evaluatePath(pklFile) {
|
||||
allowedModules("file:", "package:", "https:")
|
||||
allowedResources("prop:", "package:", "https:")
|
||||
moduleCacheDir(cacheDir)
|
||||
certificateFiles(FileTestUtils.selfSignedCertificate)
|
||||
testPort(server.port)
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
val result =
|
||||
PackageServer().use { server ->
|
||||
currentExecutor.evaluatePath(pklFile) {
|
||||
allowedModules("file:", "package:", "https:")
|
||||
allowedResources("prop:", "package:", "https:")
|
||||
moduleCacheDir(cacheDir)
|
||||
certificateFiles(FileTestUtils.selfSignedCertificate)
|
||||
testPort(server.port)
|
||||
}
|
||||
}
|
||||
}
|
||||
assertThat(result.trim()).isEqualTo("""
|
||||
assertThat(result.trim())
|
||||
.isEqualTo(
|
||||
"""
|
||||
chirpy {
|
||||
name = "Chirpy"
|
||||
favoriteFruit {
|
||||
name = "Orange"
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
// verify that cache was populated
|
||||
assertThat(cacheDir.toFile().list()).isNotEmpty()
|
||||
}
|
||||
@@ -436,15 +499,25 @@ class EmbeddedExecutorTest {
|
||||
PackageServer.populateLegacyCacheDir(cacheDir)
|
||||
val projectDir = tempDir.resolve("project/")
|
||||
projectDir.createDirectories()
|
||||
projectDir.resolve("PklProject").toFile().writeText("""
|
||||
projectDir
|
||||
.resolve("PklProject")
|
||||
.toFile()
|
||||
.writeText(
|
||||
"""
|
||||
amends "pkl:Project"
|
||||
|
||||
dependencies {
|
||||
["birds"] { uri = "package://localhost:0/birds@0.5.0" }
|
||||
}
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
val dollar = '$'
|
||||
projectDir.resolve("PklProject.deps.json").toFile().writeText("""
|
||||
projectDir
|
||||
.resolve("PklProject.deps.json")
|
||||
.toFile()
|
||||
.writeText(
|
||||
"""
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"resolvedDependencies": {
|
||||
@@ -464,25 +537,33 @@ class EmbeddedExecutorTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
val pklFile = projectDir.resolve("test.pkl")
|
||||
pklFile.toFile().writeText(
|
||||
"""
|
||||
pklFile
|
||||
.toFile()
|
||||
.writeText(
|
||||
"""
|
||||
@ModuleInfo { minPklVersion = "0.24.0" }
|
||||
module myModule
|
||||
|
||||
import "@birds/catalog/Swallow.pkl"
|
||||
|
||||
result = Swallow
|
||||
""".trimIndent()
|
||||
)
|
||||
val result = executor.evaluatePath(pklFile) {
|
||||
allowedModules("file:", "package:", "projectpackage:", "https:")
|
||||
allowedResources("file:", "prop:", "package:", "projectpackage:", "https:")
|
||||
moduleCacheDir(cacheDir)
|
||||
projectDir(projectDir)
|
||||
}
|
||||
assertThat(result).isEqualTo("""
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
val result =
|
||||
executor.evaluatePath(pklFile) {
|
||||
allowedModules("file:", "package:", "projectpackage:", "https:")
|
||||
allowedResources("file:", "prop:", "package:", "projectpackage:", "https:")
|
||||
moduleCacheDir(cacheDir)
|
||||
projectDir(projectDir)
|
||||
}
|
||||
assertThat(result)
|
||||
.isEqualTo(
|
||||
"""
|
||||
result {
|
||||
name = "Swallow"
|
||||
favoriteFruit {
|
||||
@@ -490,6 +571,8 @@ class EmbeddedExecutorTest {
|
||||
}
|
||||
}
|
||||
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* Copyright © 2024 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.executor
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
@@ -38,23 +53,16 @@ class VersionTest {
|
||||
|
||||
@Test
|
||||
fun `parse invalid version`() {
|
||||
assertThat(Version.parseOrNull("not a version number"))
|
||||
.isNull()
|
||||
assertThat(Version.parseOrNull("not a version number")).isNull()
|
||||
|
||||
assertThrows<IllegalArgumentException> {
|
||||
Version.parse("not a version number")
|
||||
}
|
||||
assertThrows<IllegalArgumentException> { Version.parse("not a version number") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `parse too large version`() {
|
||||
assertThrows<IllegalArgumentException> {
|
||||
Version.parse("not a version number")
|
||||
}
|
||||
assertThrows<IllegalArgumentException> { Version.parse("not a version number") }
|
||||
|
||||
assertThrows<IllegalArgumentException> {
|
||||
Version.parse("999999999999999.0.0")
|
||||
}
|
||||
assertThrows<IllegalArgumentException> { Version.parse("999999999999999.0.0") }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -67,137 +75,80 @@ class VersionTest {
|
||||
|
||||
@Test
|
||||
fun withMethods() {
|
||||
val version = Version.parse("0.0.0")
|
||||
.withMajor(1)
|
||||
.withMinor(2)
|
||||
.withPatch(3)
|
||||
.withPreRelease("rc.1")
|
||||
.withBuild("456.789")
|
||||
val version =
|
||||
Version.parse("0.0.0")
|
||||
.withMajor(1)
|
||||
.withMinor(2)
|
||||
.withPatch(3)
|
||||
.withPreRelease("rc.1")
|
||||
.withBuild("456.789")
|
||||
|
||||
assertThat(version).isEqualTo(Version.parse("1.2.3-rc.1+456.789"))
|
||||
|
||||
val version2 = Version.parse("0.0.0")
|
||||
.withBuild("456.789")
|
||||
.withPreRelease("rc.1")
|
||||
.withPatch(3)
|
||||
.withMinor(2)
|
||||
.withMajor(1)
|
||||
val version2 =
|
||||
Version.parse("0.0.0")
|
||||
.withBuild("456.789")
|
||||
.withPreRelease("rc.1")
|
||||
.withPatch(3)
|
||||
.withMinor(2)
|
||||
.withMajor(1)
|
||||
|
||||
assertThat(version2).isEqualTo(version)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `compareTo()`() {
|
||||
assertThat(
|
||||
Version(1, 2, 3, null, null).compareTo(
|
||||
Version(1, 2, 3, null, null)
|
||||
)
|
||||
).isEqualTo(0)
|
||||
assertThat(
|
||||
Version(1, 2, 3, "SNAPSHOT", null).compareTo(
|
||||
Version(1, 2, 3, "SNAPSHOT", null)
|
||||
)
|
||||
).isEqualTo(0)
|
||||
assertThat(
|
||||
Version(1, 2, 3, "alpha", null).compareTo(
|
||||
Version(1, 2, 3, "alpha", null)
|
||||
)
|
||||
).isEqualTo(0)
|
||||
assertThat(
|
||||
Version(1, 2, 3, "alpha", null).compareTo(
|
||||
Version(1, 2, 3, "alpha", "build123")
|
||||
)
|
||||
).isEqualTo(0)
|
||||
assertThat(Version(1, 2, 3, null, null).compareTo(Version(1, 2, 3, null, null))).isEqualTo(0)
|
||||
assertThat(Version(1, 2, 3, "SNAPSHOT", null).compareTo(Version(1, 2, 3, "SNAPSHOT", null)))
|
||||
.isEqualTo(0)
|
||||
assertThat(Version(1, 2, 3, "alpha", null).compareTo(Version(1, 2, 3, "alpha", null)))
|
||||
.isEqualTo(0)
|
||||
assertThat(Version(1, 2, 3, "alpha", null).compareTo(Version(1, 2, 3, "alpha", "build123")))
|
||||
.isEqualTo(0)
|
||||
|
||||
assertThat(
|
||||
Version(1, 2, 3, null, null).compareTo(
|
||||
Version(2, 2, 3, null, null)
|
||||
)
|
||||
).isLessThan(0)
|
||||
assertThat(
|
||||
Version(1, 2, 3, null, null).compareTo(
|
||||
Version(1, 3, 3, null, null)
|
||||
)
|
||||
).isLessThan(0)
|
||||
assertThat(
|
||||
Version(1, 2, 3, null, null).compareTo(
|
||||
Version(1, 2, 4, null, null)
|
||||
)
|
||||
).isLessThan(0)
|
||||
assertThat(Version(1, 2, 3, null, null).compareTo(Version(2, 2, 3, null, null))).isLessThan(0)
|
||||
assertThat(Version(1, 2, 3, null, null).compareTo(Version(1, 3, 3, null, null))).isLessThan(0)
|
||||
assertThat(Version(1, 2, 3, null, null).compareTo(Version(1, 2, 4, null, null))).isLessThan(0)
|
||||
|
||||
assertThat(
|
||||
Version(2, 2, 3, null, null).compareTo(
|
||||
Version(1, 2, 3, null, null)
|
||||
)
|
||||
).isGreaterThan(0)
|
||||
assertThat(
|
||||
Version(1, 3, 3, null, null).compareTo(
|
||||
Version(1, 2, 3, null, null)
|
||||
)
|
||||
).isGreaterThan(0)
|
||||
assertThat(
|
||||
Version(1, 2, 4, null, null).compareTo(
|
||||
Version(1, 2, 3, null, null)
|
||||
)
|
||||
).isGreaterThan(0)
|
||||
assertThat(Version(2, 2, 3, null, null).compareTo(Version(1, 2, 3, null, null)))
|
||||
.isGreaterThan(0)
|
||||
assertThat(Version(1, 3, 3, null, null).compareTo(Version(1, 2, 3, null, null)))
|
||||
.isGreaterThan(0)
|
||||
assertThat(Version(1, 2, 4, null, null).compareTo(Version(1, 2, 3, null, null)))
|
||||
.isGreaterThan(0)
|
||||
|
||||
assertThat(
|
||||
Version(1, 2, 3, "SNAPSHOT", null).compareTo(
|
||||
Version(1, 2, 3, null, null)
|
||||
)
|
||||
).isLessThan(0)
|
||||
assertThat(
|
||||
Version(1, 2, 3, "alpha", null).compareTo(
|
||||
Version(1, 2, 3, "beta", null)
|
||||
)
|
||||
).isLessThan(0)
|
||||
assertThat(
|
||||
Version(1, 2, 3, "alpha", "build123").compareTo(
|
||||
Version(1, 2, 3, "beta", null)
|
||||
)
|
||||
).isLessThan(0)
|
||||
assertThat(Version(1, 2, 3, "SNAPSHOT", null).compareTo(Version(1, 2, 3, null, null)))
|
||||
.isLessThan(0)
|
||||
assertThat(Version(1, 2, 3, "alpha", null).compareTo(Version(1, 2, 3, "beta", null)))
|
||||
.isLessThan(0)
|
||||
assertThat(Version(1, 2, 3, "alpha", "build123").compareTo(Version(1, 2, 3, "beta", null)))
|
||||
.isLessThan(0)
|
||||
|
||||
assertThat(
|
||||
Version(1, 2, 3, null, null).compareTo(
|
||||
Version(1, 2, 3, "SNAPSHOT", null)
|
||||
)
|
||||
).isGreaterThan(0)
|
||||
assertThat(
|
||||
Version(1, 2, 3, "beta", null).compareTo(
|
||||
Version(1, 2, 3, "alpha", "build123")
|
||||
)
|
||||
).isGreaterThan(0)
|
||||
assertThat(Version(1, 2, 3, null, null).compareTo(Version(1, 2, 3, "SNAPSHOT", null)))
|
||||
.isGreaterThan(0)
|
||||
assertThat(Version(1, 2, 3, "beta", null).compareTo(Version(1, 2, 3, "alpha", "build123")))
|
||||
.isGreaterThan(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `compare version with too large numeric pre-release identifier`() {
|
||||
// error is deferred until compareTo(), but should be good enough
|
||||
assertThrows<IllegalArgumentException> {
|
||||
Version(1, 2, 3, "999", null).compareTo(
|
||||
Version(1, 2, 3, "9999999999999999999", null)
|
||||
)
|
||||
Version(1, 2, 3, "999", null).compareTo(Version(1, 2, 3, "9999999999999999999", null))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `equals()`() {
|
||||
assertThat(Version(1, 2, 3, null, null))
|
||||
.isEqualTo(Version(1, 2, 3, null, null))
|
||||
assertThat(Version(1, 2, 3, "SNAPSHOT", null))
|
||||
.isEqualTo(Version(1, 2, 3, "SNAPSHOT", null))
|
||||
assertThat(Version(1, 2, 3, "alpha", null))
|
||||
.isEqualTo(Version(1, 2, 3, "alpha", null))
|
||||
assertThat(Version(1, 2, 3, "beta", "build123"))
|
||||
.isEqualTo(Version(1, 2, 3, "beta", "build456"))
|
||||
assertThat(Version(1, 2, 3, null, null)).isEqualTo(Version(1, 2, 3, null, null))
|
||||
assertThat(Version(1, 2, 3, "SNAPSHOT", null)).isEqualTo(Version(1, 2, 3, "SNAPSHOT", null))
|
||||
assertThat(Version(1, 2, 3, "alpha", null)).isEqualTo(Version(1, 2, 3, "alpha", null))
|
||||
assertThat(Version(1, 2, 3, "beta", "build123")).isEqualTo(Version(1, 2, 3, "beta", "build456"))
|
||||
|
||||
assertThat(Version(1, 3, 3, null, null))
|
||||
.isNotEqualTo(Version(1, 2, 3, null, null))
|
||||
assertThat(Version(1, 2, 4, null, null))
|
||||
.isNotEqualTo(Version(1, 2, 3, null, null))
|
||||
assertThat(Version(1, 2, 3, "SNAPSHOT", null))
|
||||
.isNotEqualTo(Version(1, 2, 3, null, null))
|
||||
assertThat(Version(1, 2, 3, "beta", null))
|
||||
.isNotEqualTo(Version(1, 2, 3, "alpha", null))
|
||||
assertThat(Version(1, 3, 3, null, null)).isNotEqualTo(Version(1, 2, 3, null, null))
|
||||
assertThat(Version(1, 2, 4, null, null)).isNotEqualTo(Version(1, 2, 3, null, null))
|
||||
assertThat(Version(1, 2, 3, "SNAPSHOT", null)).isNotEqualTo(Version(1, 2, 3, null, null))
|
||||
assertThat(Version(1, 2, 3, "beta", null)).isNotEqualTo(Version(1, 2, 3, "alpha", null))
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user