mirror of
https://github.com/apple/pkl.git
synced 2026-04-25 09:48:41 +02: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.
|
||||||
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
pklAllProjects
|
pklAllProjects
|
||||||
pklJavaLibrary
|
pklJavaLibrary
|
||||||
@@ -18,14 +33,15 @@ dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
jmh {
|
jmh {
|
||||||
//include = ["fib_class_java"]
|
// include = ["fib_class_java"]
|
||||||
//include = ["fib_class_constrained1", "fib_class_constrained2"]
|
// include = ["fib_class_constrained1", "fib_class_constrained2"]
|
||||||
jmhVersion.set(libs.versions.jmh)
|
jmhVersion.set(libs.versions.jmh)
|
||||||
// jvmArgsAppend = "-Dgraal.TruffleCompilationExceptionsAreFatal=true " +
|
// jvmArgsAppend = "-Dgraal.TruffleCompilationExceptionsAreFatal=true " +
|
||||||
// "-Dgraal.Dump=Truffle,TruffleTree -Dgraal.TraceTruffleCompilation=true " +
|
// "-Dgraal.Dump=Truffle,TruffleTree -Dgraal.TraceTruffleCompilation=true " +
|
||||||
// "-Dgraal.TruffleFunctionInlining=false"
|
// "-Dgraal.TruffleFunctionInlining=false"
|
||||||
jvm.set("${buildInfo.graalVmAmd64.baseDir}/bin/java")
|
jvm.set("${buildInfo.graalVmAmd64.baseDir}/bin/java")
|
||||||
// see: https://docs.oracle.com/en/graalvm/enterprise/20/docs/graalvm-as-a-platform/implement-language/#disable-class-path-separation
|
// see:
|
||||||
|
// https://docs.oracle.com/en/graalvm/enterprise/20/docs/graalvm-as-a-platform/implement-language/#disable-class-path-separation
|
||||||
jvmArgs.set(
|
jvmArgs.set(
|
||||||
listOf(
|
listOf(
|
||||||
// one JVM arg per list element doesn't work, but the following does
|
// one JVM arg per list element doesn't work, but the following does
|
||||||
@@ -33,16 +49,13 @@ jmh {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
includeTests.set(false)
|
includeTests.set(false)
|
||||||
//threads = Runtime.runtime.availableProcessors() / 2 + 1
|
// threads = Runtime.runtime.availableProcessors() / 2 + 1
|
||||||
//synchronizeIterations = false
|
// synchronizeIterations = false
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named("jmh") {
|
tasks.named("jmh") { dependsOn(":installGraalVmAmd64") }
|
||||||
dependsOn(":installGraalVmAmd64")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prevent this error which occurs when building in IntelliJ:
|
// Prevent this error which occurs when building in IntelliJ:
|
||||||
// "Entry org/pkl/core/fib_class_typed.pkl is a duplicate but no duplicate handling strategy has been set."
|
// "Entry org/pkl/core/fib_class_typed.pkl is a duplicate but no duplicate handling strategy has
|
||||||
tasks.processJmhResources {
|
// been set."
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
tasks.processJmhResources { duplicatesStrategy = DuplicatesStrategy.EXCLUDE }
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
// https://youtrack.jetbrains.com/issue/KTIJ-19369
|
// https://youtrack.jetbrains.com/issue/KTIJ-19369
|
||||||
@file:Suppress("DSL_SCOPE_VIOLATION")
|
@file:Suppress("DSL_SCOPE_VIOLATION")
|
||||||
|
|
||||||
import org.jetbrains.gradle.ext.ActionDelegationConfig
|
import org.jetbrains.gradle.ext.ActionDelegationConfig
|
||||||
import org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM
|
import org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM
|
||||||
@@ -40,15 +55,12 @@ idea {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val clean by tasks.existing {
|
val clean by tasks.existing { delete(layout.buildDirectory) }
|
||||||
delete(layout.buildDirectory)
|
|
||||||
}
|
|
||||||
|
|
||||||
val printVersion by tasks.registering {
|
val printVersion by tasks.registering { doFirst { println(buildInfo.pklVersion) } }
|
||||||
doFirst { println(buildInfo.pklVersion) }
|
|
||||||
}
|
|
||||||
|
|
||||||
val message = """
|
val message =
|
||||||
|
"""
|
||||||
====
|
====
|
||||||
Gradle version : ${gradle.gradleVersion}
|
Gradle version : ${gradle.gradleVersion}
|
||||||
Java version : ${System.getProperty("java.version")}
|
Java version : ${System.getProperty("java.version")}
|
||||||
@@ -63,5 +75,7 @@ Git Commit ID : ${buildInfo.commitId}
|
|||||||
====
|
====
|
||||||
"""
|
"""
|
||||||
|
|
||||||
val formattedMessage = message.replace("\n====", "\n" + "=".repeat(message.lines().maxByOrNull { it.length }!!.length))
|
val formattedMessage =
|
||||||
|
message.replace("\n====", "\n" + "=".repeat(message.lines().maxByOrNull { it.length }!!.length))
|
||||||
|
|
||||||
logger.info(formattedMessage)
|
logger.info(formattedMessage)
|
||||||
|
|||||||
@@ -13,9 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
plugins {
|
plugins { `kotlin-dsl` }
|
||||||
`kotlin-dsl`
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(libs.downloadTaskPlugin)
|
implementation(libs.downloadTaskPlugin)
|
||||||
|
|||||||
@@ -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.
|
||||||
|
*/
|
||||||
@file:Suppress("UnstableApiUsage")
|
@file:Suppress("UnstableApiUsage")
|
||||||
|
|
||||||
rootProject.name = "buildSrc"
|
rootProject.name = "buildSrc"
|
||||||
@@ -12,11 +27,7 @@ pluginManagement {
|
|||||||
// makes ~/.gradle/init.gradle unnecessary and ~/.gradle/gradle.properties optional
|
// makes ~/.gradle/init.gradle unnecessary and ~/.gradle/gradle.properties optional
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
// use same version catalog as main build
|
// use same version catalog as main build
|
||||||
versionCatalogs {
|
versionCatalogs { register("libs") { from(files("../gradle/libs.versions.toml")) } }
|
||||||
register("libs") {
|
|
||||||
from(files("../gradle/libs.versions.toml"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
|
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
|
||||||
|
|||||||
@@ -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.
|
||||||
|
*/
|
||||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -14,13 +29,9 @@ open class BuildInfo(project: Project) {
|
|||||||
System.getenv("GRAALVM_HOME") ?: "${System.getProperty("user.home")}/.graalvm"
|
System.getenv("GRAALVM_HOME") ?: "${System.getProperty("user.home")}/.graalvm"
|
||||||
}
|
}
|
||||||
|
|
||||||
val version: String by lazy {
|
val version: String by lazy { libs.findVersion("graalVm").get().toString() }
|
||||||
libs.findVersion("graalVm").get().toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
val graalVmJdkVersion: String by lazy {
|
val graalVmJdkVersion: String by lazy { libs.findVersion("graalVmJdkVersion").get().toString() }
|
||||||
libs.findVersion("graalVmJdkVersion").get().toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
val osName: String by lazy {
|
val osName: String by lazy {
|
||||||
when {
|
when {
|
||||||
@@ -31,9 +42,7 @@ open class BuildInfo(project: Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val baseName: String by lazy {
|
val baseName: String by lazy { "graalvm-jdk-${graalVmJdkVersion}_${osName}-${arch}_bin" }
|
||||||
"graalvm-jdk-${graalVmJdkVersion}_${osName}-${arch}_bin"
|
|
||||||
}
|
|
||||||
|
|
||||||
val downloadUrl: String by lazy {
|
val downloadUrl: String by lazy {
|
||||||
val jdkMajor = graalVmJdkVersion.takeWhile { it != '.' }
|
val jdkMajor = graalVmJdkVersion.takeWhile { it != '.' }
|
||||||
@@ -41,18 +50,14 @@ open class BuildInfo(project: Project) {
|
|||||||
"https://download.oracle.com/graalvm/$jdkMajor/archive/$baseName.$extension"
|
"https://download.oracle.com/graalvm/$jdkMajor/archive/$baseName.$extension"
|
||||||
}
|
}
|
||||||
|
|
||||||
val installDir: File by lazy {
|
val installDir: File by lazy { File(homeDir, baseName) }
|
||||||
File(homeDir, baseName)
|
|
||||||
}
|
|
||||||
|
|
||||||
val baseDir: String by lazy {
|
val baseDir: String by lazy {
|
||||||
if (os.isMacOsX) "$installDir/Contents/Home" else installDir.toString()
|
if (os.isMacOsX) "$installDir/Contents/Home" else installDir.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Same logic as [org.gradle.internal.os.OperatingSystem#arch], which is protected. */
|
||||||
* Same logic as [org.gradle.internal.os.OperatingSystem#arch], which is protected.
|
|
||||||
*/
|
|
||||||
val arch: String by lazy {
|
val arch: String by lazy {
|
||||||
when (val arch = System.getProperty("os.arch")) {
|
when (val arch = System.getProperty("os.arch")) {
|
||||||
"x86" -> "i386"
|
"x86" -> "i386"
|
||||||
@@ -66,13 +71,9 @@ open class BuildInfo(project: Project) {
|
|||||||
|
|
||||||
val graalVmAmd64: GraalVm = GraalVm("x64")
|
val graalVmAmd64: GraalVm = GraalVm("x64")
|
||||||
|
|
||||||
val isCiBuild: Boolean by lazy {
|
val isCiBuild: Boolean by lazy { System.getenv("CI") != null }
|
||||||
System.getenv("CI") != null
|
|
||||||
}
|
|
||||||
|
|
||||||
val isReleaseBuild: Boolean by lazy {
|
val isReleaseBuild: Boolean by lazy { java.lang.Boolean.getBoolean("releaseBuild") }
|
||||||
java.lang.Boolean.getBoolean("releaseBuild")
|
|
||||||
}
|
|
||||||
|
|
||||||
val hasMuslToolchain: Boolean by lazy {
|
val hasMuslToolchain: Boolean by lazy {
|
||||||
// see "install musl" in .circleci/jobs/BuildNativeJob.pkl
|
// see "install musl" in .circleci/jobs/BuildNativeJob.pkl
|
||||||
@@ -87,10 +88,11 @@ open class BuildInfo(project: Project) {
|
|||||||
val commitId: String by lazy {
|
val commitId: String by lazy {
|
||||||
// only run command once per build invocation
|
// only run command once per build invocation
|
||||||
if (project === project.rootProject) {
|
if (project === project.rootProject) {
|
||||||
val process = ProcessBuilder()
|
val process =
|
||||||
.command("git", "rev-parse", "--short", "HEAD")
|
ProcessBuilder()
|
||||||
.directory(project.rootDir)
|
.command("git", "rev-parse", "--short", "HEAD")
|
||||||
.start()
|
.directory(project.rootDir)
|
||||||
|
.start()
|
||||||
process.waitFor().also { exitCode ->
|
process.waitFor().also { exitCode ->
|
||||||
if (exitCode == -1) throw RuntimeException(process.errorStream.reader().readText())
|
if (exitCode == -1) throw RuntimeException(process.errorStream.reader().readText())
|
||||||
}
|
}
|
||||||
@@ -100,9 +102,7 @@ open class BuildInfo(project: Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val commitish: String by lazy {
|
val commitish: String by lazy { if (isReleaseBuild) project.version.toString() else commitId }
|
||||||
if (isReleaseBuild) project.version.toString() else commitId
|
|
||||||
}
|
|
||||||
|
|
||||||
val pklVersion: String by lazy {
|
val pklVersion: String by lazy {
|
||||||
if (isReleaseBuild) {
|
if (isReleaseBuild) {
|
||||||
|
|||||||
@@ -1,39 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* 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 org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.file.RegularFileProperty
|
import org.gradle.api.file.RegularFileProperty
|
||||||
import org.gradle.api.provider.ListProperty
|
import org.gradle.api.provider.ListProperty
|
||||||
import org.gradle.api.provider.Property
|
|
||||||
import org.gradle.api.tasks.Input
|
import org.gradle.api.tasks.Input
|
||||||
import org.gradle.api.tasks.InputFile
|
import org.gradle.api.tasks.InputFile
|
||||||
import org.gradle.api.tasks.OutputFile
|
import org.gradle.api.tasks.OutputFile
|
||||||
import org.gradle.api.tasks.TaskAction
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a self-contained Pkl CLI Jar that is directly executable on *nix
|
* Builds a self-contained Pkl CLI Jar that is directly executable on *nix and executable with `java
|
||||||
* and executable with `java -jar` on Windows.
|
* -jar` on Windows.
|
||||||
*
|
*
|
||||||
* For direct execution, the `java` command must be on the PATH.
|
* For direct execution, the `java` command must be on the PATH.
|
||||||
*
|
*
|
||||||
* https://skife.org/java/unix/2011/06/20/really_executable_jars.html
|
* https://skife.org/java/unix/2011/06/20/really_executable_jars.html
|
||||||
*/
|
*/
|
||||||
abstract class ExecutableJar : DefaultTask() {
|
abstract class ExecutableJar : DefaultTask() {
|
||||||
@get:InputFile
|
@get:InputFile abstract val inJar: RegularFileProperty
|
||||||
abstract val inJar: RegularFileProperty
|
|
||||||
|
|
||||||
@get:OutputFile
|
@get:OutputFile abstract val outJar: RegularFileProperty
|
||||||
abstract val outJar: RegularFileProperty
|
|
||||||
|
|
||||||
@get:Input
|
@get:Input abstract val jvmArgs: ListProperty<String>
|
||||||
abstract val jvmArgs: ListProperty<String>
|
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun buildJar() {
|
fun buildJar() {
|
||||||
val inFile = inJar.get().asFile
|
val inFile = inJar.get().asFile
|
||||||
val outFile = outJar.get().asFile
|
val outFile = outJar.get().asFile
|
||||||
val escapedJvmArgs = jvmArgs.get().joinToString(separator = " ") { "\"$it\"" }
|
val escapedJvmArgs = jvmArgs.get().joinToString(separator = " ") { "\"$it\"" }
|
||||||
val startScript = """
|
val startScript =
|
||||||
|
"""
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
exec java $escapedJvmArgs -jar $0 "$@"
|
exec java $escapedJvmArgs -jar $0 "$@"
|
||||||
""".trimIndent() + "\n\n\n"
|
"""
|
||||||
|
.trimIndent() + "\n\n\n"
|
||||||
outFile.outputStream().use { outStream ->
|
outFile.outputStream().use { outStream ->
|
||||||
startScript.byteInputStream().use { it.copyTo(outStream) }
|
startScript.byteInputStream().use { it.copyTo(outStream) }
|
||||||
inFile.inputStream().use { it.copyTo(outStream) }
|
inFile.inputStream().use { it.copyTo(outStream) }
|
||||||
|
|||||||
@@ -1,7 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* 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 org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
|
|
||||||
open class GradlePluginTests {
|
open class GradlePluginTests {
|
||||||
lateinit var minGradleVersion: GradleVersion
|
lateinit var minGradleVersion: GradleVersion
|
||||||
lateinit var maxGradleVersion: GradleVersion
|
lateinit var maxGradleVersion: GradleVersion
|
||||||
var skippedGradleVersions: List<GradleVersion> = listOf()
|
var skippedGradleVersions: List<GradleVersion> = listOf()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,21 @@
|
|||||||
import org.gradle.util.GradleVersion
|
/**
|
||||||
|
* 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 groovy.json.JsonSlurper
|
import groovy.json.JsonSlurper
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
import org.gradle.util.GradleVersion
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class GradleVersionInfo(json: Map<String, Any>) {
|
class GradleVersionInfo(json: Map<String, Any>) {
|
||||||
@@ -38,15 +53,19 @@ class GradleVersionInfo(json: Map<String, Any>) {
|
|||||||
val wrapperChecksumUrl: String by json
|
val wrapperChecksumUrl: String by json
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private fun fetchAll(): List<GradleVersionInfo> = fetchMultiple("https://services.gradle.org/versions/all")
|
private fun fetchAll(): List<GradleVersionInfo> =
|
||||||
|
fetchMultiple("https://services.gradle.org/versions/all")
|
||||||
|
|
||||||
fun fetchReleases(): List<GradleVersionInfo> = fetchAll().filter { it.isReleaseVersion }
|
fun fetchReleases(): List<GradleVersionInfo> = fetchAll().filter { it.isReleaseVersion }
|
||||||
|
|
||||||
fun fetchCurrent(): GradleVersionInfo = fetchSingle("https://services.gradle.org/versions/current")
|
fun fetchCurrent(): GradleVersionInfo =
|
||||||
|
fetchSingle("https://services.gradle.org/versions/current")
|
||||||
|
|
||||||
fun fetchRc(): GradleVersionInfo? = fetchSingleOrNull("https://services.gradle.org/versions/release-candidate")
|
fun fetchRc(): GradleVersionInfo? =
|
||||||
|
fetchSingleOrNull("https://services.gradle.org/versions/release-candidate")
|
||||||
|
|
||||||
fun fetchNightly(): GradleVersionInfo = fetchSingle("https://services.gradle.org/versions/nightly")
|
fun fetchNightly(): GradleVersionInfo =
|
||||||
|
fetchSingle("https://services.gradle.org/versions/nightly")
|
||||||
|
|
||||||
private fun fetchSingle(url: String): GradleVersionInfo {
|
private fun fetchSingle(url: String): GradleVersionInfo {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@@ -61,8 +80,9 @@ class GradleVersionInfo(json: Map<String, Any>) {
|
|||||||
|
|
||||||
private fun fetchMultiple(url: String): List<GradleVersionInfo> {
|
private fun fetchMultiple(url: String): List<GradleVersionInfo> {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return (JsonSlurper().parse(URI(url).toURL()) as List<Map<String, Any>>)
|
return (JsonSlurper().parse(URI(url).toURL()) as List<Map<String, Any>>).map {
|
||||||
.map { GradleVersionInfo(it) }
|
GradleVersionInfo(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* 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 org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.file.FileCollection
|
import org.gradle.api.file.FileCollection
|
||||||
|
|
||||||
open class HtmlValidator(project: Project) {
|
open class HtmlValidator(project: Project) {
|
||||||
var sources: FileCollection = project.files()
|
var sources: FileCollection = project.files()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.io.File
|
import java.io.File
|
||||||
import java.util.regex.Matcher
|
import java.util.regex.Matcher
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
@@ -15,21 +30,18 @@ import org.gradle.kotlin.dsl.listProperty
|
|||||||
import org.gradle.kotlin.dsl.mapProperty
|
import org.gradle.kotlin.dsl.mapProperty
|
||||||
|
|
||||||
open class MergeSourcesJars : DefaultTask() {
|
open class MergeSourcesJars : DefaultTask() {
|
||||||
@get:InputFiles
|
@get:InputFiles val inputJars: ConfigurableFileCollection = project.objects.fileCollection()
|
||||||
val inputJars: ConfigurableFileCollection = project.objects.fileCollection()
|
|
||||||
|
|
||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
val mergedBinaryJars: ConfigurableFileCollection = project.objects.fileCollection()
|
val mergedBinaryJars: ConfigurableFileCollection = project.objects.fileCollection()
|
||||||
|
|
||||||
@get:Input
|
@get:Input val relocatedPackages: MapProperty<String, String> = project.objects.mapProperty()
|
||||||
val relocatedPackages: MapProperty<String, String> = project.objects.mapProperty()
|
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
var sourceFileExtensions: ListProperty<String> = project.objects.listProperty<String>()
|
var sourceFileExtensions: ListProperty<String> =
|
||||||
.convention(listOf(".java", ".kt"))
|
project.objects.listProperty<String>().convention(listOf(".java", ".kt"))
|
||||||
|
|
||||||
@get:OutputFile
|
@get:OutputFile val outputJar: RegularFileProperty = project.objects.fileProperty()
|
||||||
val outputJar: RegularFileProperty = project.objects.fileProperty()
|
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@@ -38,12 +50,15 @@ open class MergeSourcesJars : DefaultTask() {
|
|||||||
|
|
||||||
val relocatedPkgs = relocatedPackages.get()
|
val relocatedPkgs = relocatedPackages.get()
|
||||||
|
|
||||||
val relocatedPaths = relocatedPkgs.entries.associate { (key, value) -> toPath(key) to toPath(value) }
|
val relocatedPaths =
|
||||||
|
relocatedPkgs.entries.associate { (key, value) -> toPath(key) to toPath(value) }
|
||||||
|
|
||||||
// use negative lookbehind to match any that don't precede with
|
// use negative lookbehind to match any that don't precede with
|
||||||
// a word or a period character. should catch most cases.
|
// a word or a period character. should catch most cases.
|
||||||
val importPattern = Pattern.compile("(?<!(\\w|\\.))(" +
|
val importPattern =
|
||||||
relocatedPkgs.keys.joinToString("|") { it.replace(".", "\\.") } + ")")
|
Pattern.compile(
|
||||||
|
"(?<!(\\w|\\.))(" + relocatedPkgs.keys.joinToString("|") { it.replace(".", "\\.") } + ")"
|
||||||
|
)
|
||||||
|
|
||||||
val sourceFileExts = sourceFileExtensions.get()
|
val sourceFileExts = sourceFileExtensions.get()
|
||||||
|
|
||||||
|
|||||||
@@ -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 org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.artifacts.Configuration
|
import org.gradle.api.artifacts.Configuration
|
||||||
import org.gradle.api.artifacts.result.ResolvedArtifactResult
|
import org.gradle.api.artifacts.result.ResolvedArtifactResult
|
||||||
@@ -12,27 +27,29 @@ import org.gradle.kotlin.dsl.property
|
|||||||
import org.gradle.language.base.artifact.SourcesArtifact
|
import org.gradle.language.base.artifact.SourcesArtifact
|
||||||
|
|
||||||
open class ResolveSourcesJars : DefaultTask() {
|
open class ResolveSourcesJars : DefaultTask() {
|
||||||
@get:InputFiles
|
@get:InputFiles val configuration: Property<Configuration> = project.objects.property()
|
||||||
val configuration: Property<Configuration> = project.objects.property()
|
|
||||||
|
|
||||||
@get:OutputDirectory
|
@get:OutputDirectory val outputDir: DirectoryProperty = project.objects.directoryProperty()
|
||||||
val outputDir: DirectoryProperty = project.objects.directoryProperty()
|
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
@Suppress("UnstableApiUsage", "unused")
|
@Suppress("UnstableApiUsage", "unused")
|
||||||
fun resolve() {
|
fun resolve() {
|
||||||
val componentIds = configuration.get().incoming.resolutionResult.allDependencies.map {
|
val componentIds =
|
||||||
(it as ResolvedDependencyResult).selected.id
|
configuration.get().incoming.resolutionResult.allDependencies.map {
|
||||||
}
|
(it as ResolvedDependencyResult).selected.id
|
||||||
|
}
|
||||||
|
|
||||||
val resolutionResult = project.dependencies.createArtifactResolutionQuery()
|
val resolutionResult =
|
||||||
.forComponents(componentIds)
|
project.dependencies
|
||||||
.withArtifacts(JvmLibrary::class.java, SourcesArtifact::class.java)
|
.createArtifactResolutionQuery()
|
||||||
.execute()
|
.forComponents(componentIds)
|
||||||
|
.withArtifacts(JvmLibrary::class.java, SourcesArtifact::class.java)
|
||||||
|
.execute()
|
||||||
|
|
||||||
val resolvedJars = resolutionResult.resolvedComponents
|
val resolvedJars =
|
||||||
.flatMap { it.getArtifacts(SourcesArtifact::class.java) }
|
resolutionResult.resolvedComponents
|
||||||
.map { (it as ResolvedArtifactResult).file }
|
.flatMap { it.getArtifacts(SourcesArtifact::class.java) }
|
||||||
|
.map { (it as ResolvedArtifactResult).file }
|
||||||
|
|
||||||
// copying to an output dir because I don't know how else to describe task outputs
|
// copying to an output dir because I don't know how else to describe task outputs
|
||||||
project.sync {
|
project.sync {
|
||||||
|
|||||||
@@ -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 org.gradle.api.GradleException
|
import org.gradle.api.GradleException
|
||||||
import org.gradle.api.artifacts.Configuration
|
import org.gradle.api.artifacts.Configuration
|
||||||
import org.gradle.api.component.AdhocComponentWithVariants
|
import org.gradle.api.component.AdhocComponentWithVariants
|
||||||
@@ -18,41 +33,43 @@ val fatJarConfiguration: Configuration = configurations.create("fatJar")
|
|||||||
val fatJarPublication: MavenPublication = publishing.publications.create<MavenPublication>("fatJar")
|
val fatJarPublication: MavenPublication = publishing.publications.create<MavenPublication>("fatJar")
|
||||||
|
|
||||||
// ideally we'd configure this automatically based on project dependencies
|
// ideally we'd configure this automatically based on project dependencies
|
||||||
val firstPartySourcesJarsConfiguration: Configuration = configurations.create("firstPartySourcesJars")
|
val firstPartySourcesJarsConfiguration: Configuration =
|
||||||
|
configurations.create("firstPartySourcesJars")
|
||||||
|
|
||||||
val relocations = mapOf(
|
val relocations =
|
||||||
// pkl-core dependencies
|
mapOf(
|
||||||
"org.antlr.v4." to "org.pkl.thirdparty.antlr.v4.",
|
// pkl-core dependencies
|
||||||
"com.oracle.truffle" to "org.pkl.thirdparty.truffle",
|
"org.antlr.v4." to "org.pkl.thirdparty.antlr.v4.",
|
||||||
"org.graalvm." to "org.pkl.thirdparty.graalvm.",
|
"com.oracle.truffle" to "org.pkl.thirdparty.truffle",
|
||||||
"org.organicdesign.fp." to "org.pkl.thirdparty.paguro.",
|
"org.graalvm." to "org.pkl.thirdparty.graalvm.",
|
||||||
"org.snakeyaml.engine." to "org.pkl.thirdparty.snakeyaml.engine.",
|
"org.organicdesign.fp." to "org.pkl.thirdparty.paguro.",
|
||||||
"org.msgpack." to "org.pkl.thirdparty.msgpack.",
|
"org.snakeyaml.engine." to "org.pkl.thirdparty.snakeyaml.engine.",
|
||||||
"org.w3c.dom." to "org.pkl.thirdparty.w3c.dom",
|
"org.msgpack." to "org.pkl.thirdparty.msgpack.",
|
||||||
"com.oracle.svm.core." to "org.pkl.thirdparty.svm.",
|
"org.w3c.dom." to "org.pkl.thirdparty.w3c.dom",
|
||||||
|
"com.oracle.svm.core." to "org.pkl.thirdparty.svm.",
|
||||||
|
|
||||||
// pkl-cli dependencies
|
// pkl-cli dependencies
|
||||||
"org.jline." to "org.pkl.thirdparty.jline.",
|
"org.jline." to "org.pkl.thirdparty.jline.",
|
||||||
"com.github.ajalt.clikt." to "org.pkl.thirdparty.clikt.",
|
"com.github.ajalt.clikt." to "org.pkl.thirdparty.clikt.",
|
||||||
"kotlin." to "org.pkl.thirdparty.kotlin.",
|
"kotlin." to "org.pkl.thirdparty.kotlin.",
|
||||||
"kotlinx." to "org.pkl.thirdparty.kotlinx.",
|
"kotlinx." to "org.pkl.thirdparty.kotlinx.",
|
||||||
"org.intellij." to "org.pkl.thirdparty.intellij.",
|
"org.intellij." to "org.pkl.thirdparty.intellij.",
|
||||||
"org.fusesource.jansi." to "org.pkl.thirdparty.jansi",
|
"org.fusesource.jansi." to "org.pkl.thirdparty.jansi",
|
||||||
"org.fusesource.hawtjni." to "org.pkl.thirdparty.hawtjni",
|
"org.fusesource.hawtjni." to "org.pkl.thirdparty.hawtjni",
|
||||||
|
|
||||||
// pkl-doc dependencies
|
// pkl-doc dependencies
|
||||||
"org.commonmark." to "org.pkl.thirdparty.commonmark.",
|
"org.commonmark." to "org.pkl.thirdparty.commonmark.",
|
||||||
"org.jetbrains." to "org.pkl.thirdparty.jetbrains.",
|
"org.jetbrains." to "org.pkl.thirdparty.jetbrains.",
|
||||||
|
|
||||||
// pkl-config-java dependencies
|
|
||||||
"io.leangen.geantyref." to "org.pkl.thirdparty.geantyref.",
|
|
||||||
|
|
||||||
// pkl-codegen-java dependencies
|
// pkl-config-java dependencies
|
||||||
"com.squareup.javapoet." to "org.pkl.thirdparty.javapoet.",
|
"io.leangen.geantyref." to "org.pkl.thirdparty.geantyref.",
|
||||||
|
|
||||||
// pkl-codegen-kotlin dependencies
|
// pkl-codegen-java dependencies
|
||||||
"com.squareup.kotlinpoet." to "org.pkl.thirdparty.kotlinpoet.",
|
"com.squareup.javapoet." to "org.pkl.thirdparty.javapoet.",
|
||||||
)
|
|
||||||
|
// pkl-codegen-kotlin dependencies
|
||||||
|
"com.squareup.kotlinpoet." to "org.pkl.thirdparty.kotlinpoet.",
|
||||||
|
)
|
||||||
|
|
||||||
val nonRelocations = listOf("com/oracle/truffle/")
|
val nonRelocations = listOf("com/oracle/truffle/")
|
||||||
|
|
||||||
@@ -82,82 +99,81 @@ tasks.shadowJar {
|
|||||||
|
|
||||||
// workaround for https://github.com/johnrengelman/shadow/issues/651
|
// workaround for https://github.com/johnrengelman/shadow/issues/651
|
||||||
components.withType(AdhocComponentWithVariants::class.java).forEach { c ->
|
components.withType(AdhocComponentWithVariants::class.java).forEach { c ->
|
||||||
c.withVariantsFromConfiguration(project.configurations.shadowRuntimeElements.get()) {
|
c.withVariantsFromConfiguration(project.configurations.shadowRuntimeElements.get()) { skip() }
|
||||||
skip()
|
}
|
||||||
|
|
||||||
|
val testFatJar by
|
||||||
|
tasks.registering(Test::class) {
|
||||||
|
testClassesDirs = files(tasks.test.get().testClassesDirs)
|
||||||
|
classpath =
|
||||||
|
// compiled test classes
|
||||||
|
sourceSets.test.get().output +
|
||||||
|
// fat Jar
|
||||||
|
tasks.shadowJar.get().outputs.files +
|
||||||
|
// test-only dependencies
|
||||||
|
// (test dependencies that are also main dependencies must already be contained in fat Jar;
|
||||||
|
// to verify that, we don't want to include them here)
|
||||||
|
(configurations.testRuntimeClasspath.get() - configurations.runtimeClasspath.get())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val testFatJar by tasks.registering(Test::class) {
|
tasks.check { dependsOn(testFatJar) }
|
||||||
testClassesDirs = files(tasks.test.get().testClassesDirs)
|
|
||||||
classpath =
|
|
||||||
// compiled test classes
|
|
||||||
sourceSets.test.get().output +
|
|
||||||
// fat Jar
|
|
||||||
tasks.shadowJar.get().outputs.files +
|
|
||||||
// test-only dependencies
|
|
||||||
// (test dependencies that are also main dependencies must already be contained in fat Jar;
|
|
||||||
// to verify that, we don't want to include them here)
|
|
||||||
(configurations.testRuntimeClasspath.get() - configurations.runtimeClasspath.get())
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.check {
|
val validateFatJar by
|
||||||
dependsOn(testFatJar)
|
tasks.registering {
|
||||||
}
|
val outputFile = layout.buildDirectory.file("validateFatJar/result.txt")
|
||||||
|
inputs.files(tasks.shadowJar)
|
||||||
|
inputs.property("nonRelocations", nonRelocations)
|
||||||
|
outputs.file(outputFile)
|
||||||
|
|
||||||
val validateFatJar by tasks.registering {
|
doLast {
|
||||||
val outputFile = layout.buildDirectory.file("validateFatJar/result.txt")
|
val unshadowedFiles = mutableListOf<String>()
|
||||||
inputs.files(tasks.shadowJar)
|
zipTree(tasks.shadowJar.get().outputs.files.singleFile).visit {
|
||||||
inputs.property("nonRelocations", nonRelocations)
|
val fileDetails = this
|
||||||
outputs.file(outputFile)
|
val path = fileDetails.relativePath.pathString
|
||||||
|
if (
|
||||||
doLast {
|
!(fileDetails.isDirectory ||
|
||||||
val unshadowedFiles = mutableListOf<String>()
|
path.startsWith("org/pkl/") ||
|
||||||
zipTree(tasks.shadowJar.get().outputs.files.singleFile).visit {
|
path.startsWith("META-INF/") ||
|
||||||
val fileDetails = this
|
nonRelocations.any { path.startsWith(it) })
|
||||||
val path = fileDetails.relativePath.pathString
|
) {
|
||||||
if (!(fileDetails.isDirectory ||
|
// don't throw exception inside `visit`
|
||||||
path.startsWith("org/pkl/") ||
|
// as this gives a misleading "Could not expand ZIP" error message
|
||||||
path.startsWith("META-INF/") ||
|
unshadowedFiles.add(path)
|
||||||
nonRelocations.any { path.startsWith(it) })) {
|
}
|
||||||
// don't throw exception inside `visit`
|
}
|
||||||
// as this gives a misleading "Could not expand ZIP" error message
|
if (unshadowedFiles.isEmpty()) {
|
||||||
unshadowedFiles.add(path)
|
outputFile.get().asFile.writeText("SUCCESS")
|
||||||
|
} else {
|
||||||
|
outputFile.get().asFile.writeText("FAILURE")
|
||||||
|
throw GradleException("Found unshadowed files:\n" + unshadowedFiles.joinToString("\n"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (unshadowedFiles.isEmpty()) {
|
|
||||||
outputFile.get().asFile.writeText("SUCCESS")
|
|
||||||
} else {
|
|
||||||
outputFile.get().asFile.writeText("FAILURE")
|
|
||||||
throw GradleException("Found unshadowed files:\n" + unshadowedFiles.joinToString("\n"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
tasks.check {
|
|
||||||
dependsOn(validateFatJar)
|
|
||||||
}
|
|
||||||
|
|
||||||
val resolveSourcesJars by tasks.registering(ResolveSourcesJars::class) {
|
tasks.check { dependsOn(validateFatJar) }
|
||||||
configuration.set(configurations.runtimeClasspath)
|
|
||||||
outputDir.set(layout.buildDirectory.dir("resolveSourcesJars"))
|
|
||||||
}
|
|
||||||
|
|
||||||
val fatSourcesJar by tasks.registering(MergeSourcesJars::class) {
|
val resolveSourcesJars by
|
||||||
plugins.withId("pklJavaLibrary") {
|
tasks.registering(ResolveSourcesJars::class) {
|
||||||
inputJars.from(tasks.named("sourcesJar"))
|
configuration.set(configurations.runtimeClasspath)
|
||||||
|
outputDir.set(layout.buildDirectory.dir("resolveSourcesJars"))
|
||||||
}
|
}
|
||||||
inputJars.from(firstPartySourcesJarsConfiguration)
|
|
||||||
inputJars.from(resolveSourcesJars.map { fileTree(it.outputDir) })
|
|
||||||
|
|
||||||
mergedBinaryJars.from(tasks.shadowJar)
|
val fatSourcesJar by
|
||||||
relocatedPackages.set(relocations)
|
tasks.registering(MergeSourcesJars::class) {
|
||||||
outputJar.fileProvider(provider {
|
plugins.withId("pklJavaLibrary") { inputJars.from(tasks.named("sourcesJar")) }
|
||||||
file(tasks.shadowJar.get().archiveFile.get().asFile.path.replace(".jar", "-sources.jar"))
|
inputJars.from(firstPartySourcesJarsConfiguration)
|
||||||
})
|
inputJars.from(resolveSourcesJars.map { fileTree(it.outputDir) })
|
||||||
}
|
|
||||||
|
|
||||||
artifacts {
|
mergedBinaryJars.from(tasks.shadowJar)
|
||||||
add("fatJar", tasks.shadowJar)
|
relocatedPackages.set(relocations)
|
||||||
}
|
outputJar.fileProvider(
|
||||||
|
provider {
|
||||||
|
file(tasks.shadowJar.get().archiveFile.get().asFile.path.replace(".jar", "-sources.jar"))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
artifacts { add("fatJar", tasks.shadowJar) }
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
@@ -165,16 +181,12 @@ publishing {
|
|||||||
project.shadow.component(this)
|
project.shadow.component(this)
|
||||||
|
|
||||||
// sources Jar is fat
|
// sources Jar is fat
|
||||||
artifact(fatSourcesJar.flatMap { it.outputJar.asFile }) {
|
artifact(fatSourcesJar.flatMap { it.outputJar.asFile }) { classifier = "sources" }
|
||||||
classifier = "sources"
|
|
||||||
}
|
|
||||||
|
|
||||||
plugins.withId("pklJavaLibrary") {
|
plugins.withId("pklJavaLibrary") {
|
||||||
val javadocJar by tasks.existing(Jar::class)
|
val javadocJar by tasks.existing(Jar::class)
|
||||||
// Javadoc Jar is not fat (didn't invest effort)
|
// Javadoc Jar is not fat (didn't invest effort)
|
||||||
artifact(javadocJar.flatMap { it.archiveFile }) {
|
artifact(javadocJar.flatMap { it.archiveFile }) { classifier = "javadoc" }
|
||||||
classifier = "javadoc"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,44 @@
|
|||||||
import java.nio.file.*
|
/**
|
||||||
import java.util.UUID
|
* 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 de.undercouch.gradle.tasks.download.Download
|
import de.undercouch.gradle.tasks.download.Download
|
||||||
import de.undercouch.gradle.tasks.download.Verify
|
import de.undercouch.gradle.tasks.download.Verify
|
||||||
|
import java.nio.file.*
|
||||||
|
import java.util.UUID
|
||||||
import kotlin.io.path.createDirectories
|
import kotlin.io.path.createDirectories
|
||||||
|
|
||||||
plugins {
|
plugins { id("de.undercouch.download") }
|
||||||
id("de.undercouch.download")
|
|
||||||
}
|
|
||||||
|
|
||||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||||
|
|
||||||
val BuildInfo.GraalVm.downloadFile get(): File {
|
val BuildInfo.GraalVm.downloadFile
|
||||||
val extension = if (buildInfo.os.isWindows) "zip" else "tar.gz"
|
get(): File {
|
||||||
return file(homeDir).resolve("${baseName}.$extension")
|
val extension = if (buildInfo.os.isWindows) "zip" else "tar.gz"
|
||||||
}
|
return file(homeDir).resolve("${baseName}.$extension")
|
||||||
|
}
|
||||||
|
|
||||||
// tries to minimize chance of corruption by download-to-temp-file-and-move
|
// tries to minimize chance of corruption by download-to-temp-file-and-move
|
||||||
val downloadGraalVmAarch64 by tasks.registering(Download::class) {
|
val downloadGraalVmAarch64 by
|
||||||
configureDownloadGraalVm(buildInfo.graalVmAarch64)
|
tasks.registering(Download::class) { configureDownloadGraalVm(buildInfo.graalVmAarch64) }
|
||||||
}
|
|
||||||
|
|
||||||
val downloadGraalVmAmd64 by tasks.registering(Download::class) {
|
val downloadGraalVmAmd64 by
|
||||||
configureDownloadGraalVm(buildInfo.graalVmAmd64)
|
tasks.registering(Download::class) { configureDownloadGraalVm(buildInfo.graalVmAmd64) }
|
||||||
}
|
|
||||||
|
|
||||||
fun Download.configureDownloadGraalVm(graalvm: BuildInfo.GraalVm) {
|
fun Download.configureDownloadGraalVm(graalvm: BuildInfo.GraalVm) {
|
||||||
onlyIf {
|
onlyIf { !graalvm.installDir.exists() }
|
||||||
!graalvm.installDir.exists()
|
doLast { println("Downloaded GraalVm to ${graalvm.downloadFile}") }
|
||||||
}
|
|
||||||
doLast {
|
|
||||||
println("Downloaded GraalVm to ${graalvm.downloadFile}")
|
|
||||||
}
|
|
||||||
|
|
||||||
src(graalvm.downloadUrl)
|
src(graalvm.downloadUrl)
|
||||||
dest(graalvm.downloadFile)
|
dest(graalvm.downloadFile)
|
||||||
@@ -38,42 +46,44 @@ fun Download.configureDownloadGraalVm(graalvm: BuildInfo.GraalVm) {
|
|||||||
tempAndMove(true)
|
tempAndMove(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
val verifyGraalVmAarch64 by tasks.registering(Verify::class) {
|
val verifyGraalVmAarch64 by
|
||||||
configureVerifyGraalVm(buildInfo.graalVmAarch64)
|
tasks.registering(Verify::class) {
|
||||||
dependsOn(downloadGraalVmAarch64)
|
configureVerifyGraalVm(buildInfo.graalVmAarch64)
|
||||||
}
|
dependsOn(downloadGraalVmAarch64)
|
||||||
|
|
||||||
val verifyGraalVmAmd64 by tasks.registering(Verify::class) {
|
|
||||||
configureVerifyGraalVm(buildInfo.graalVmAmd64)
|
|
||||||
dependsOn(downloadGraalVmAmd64)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Verify.configureVerifyGraalVm(graalvm: BuildInfo.GraalVm) {
|
|
||||||
onlyIf {
|
|
||||||
!graalvm.installDir.exists()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val verifyGraalVmAmd64 by
|
||||||
|
tasks.registering(Verify::class) {
|
||||||
|
configureVerifyGraalVm(buildInfo.graalVmAmd64)
|
||||||
|
dependsOn(downloadGraalVmAmd64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Verify.configureVerifyGraalVm(graalvm: BuildInfo.GraalVm) {
|
||||||
|
onlyIf { !graalvm.installDir.exists() }
|
||||||
|
|
||||||
src(graalvm.downloadFile)
|
src(graalvm.downloadFile)
|
||||||
checksum(buildInfo.libs.findVersion("graalVmSha256-${graalvm.osName}-${graalvm.arch}").get().toString())
|
checksum(
|
||||||
|
buildInfo.libs.findVersion("graalVmSha256-${graalvm.osName}-${graalvm.arch}").get().toString()
|
||||||
|
)
|
||||||
algorithm("SHA-256")
|
algorithm("SHA-256")
|
||||||
}
|
}
|
||||||
|
|
||||||
// minimize chance of corruption by extract-to-random-dir-and-flip-symlink
|
// minimize chance of corruption by extract-to-random-dir-and-flip-symlink
|
||||||
val installGraalVmAarch64 by tasks.registering {
|
val installGraalVmAarch64 by
|
||||||
dependsOn(verifyGraalVmAarch64)
|
tasks.registering {
|
||||||
configureInstallGraalVm(buildInfo.graalVmAarch64)
|
dependsOn(verifyGraalVmAarch64)
|
||||||
}
|
configureInstallGraalVm(buildInfo.graalVmAarch64)
|
||||||
|
}
|
||||||
|
|
||||||
// minimize chance of corruption by extract-to-random-dir-and-flip-symlink
|
// minimize chance of corruption by extract-to-random-dir-and-flip-symlink
|
||||||
val installGraalVmAmd64 by tasks.registering {
|
val installGraalVmAmd64 by
|
||||||
dependsOn(verifyGraalVmAmd64)
|
tasks.registering {
|
||||||
configureInstallGraalVm(buildInfo.graalVmAmd64)
|
dependsOn(verifyGraalVmAmd64)
|
||||||
}
|
configureInstallGraalVm(buildInfo.graalVmAmd64)
|
||||||
|
}
|
||||||
|
|
||||||
fun Task.configureInstallGraalVm(graalVm: BuildInfo.GraalVm) {
|
fun Task.configureInstallGraalVm(graalVm: BuildInfo.GraalVm) {
|
||||||
onlyIf {
|
onlyIf { !graalVm.installDir.exists() }
|
||||||
!graalVm.installDir.exists()
|
|
||||||
}
|
|
||||||
|
|
||||||
doLast {
|
doLast {
|
||||||
val distroDir = Paths.get(graalVm.homeDir, UUID.randomUUID().toString())
|
val distroDir = Paths.get(graalVm.homeDir, UUID.randomUUID().toString())
|
||||||
@@ -88,7 +98,9 @@ fun Task.configureInstallGraalVm(graalVm: BuildInfo.GraalVm) {
|
|||||||
args("--strip-components=1", "-xzf", graalVm.downloadFile)
|
args("--strip-components=1", "-xzf", graalVm.downloadFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
val distroBinDir = if (buildInfo.os.isMacOsX) distroDir.resolve("Contents/Home/bin") else distroDir.resolve("bin")
|
val distroBinDir =
|
||||||
|
if (buildInfo.os.isMacOsX) distroDir.resolve("Contents/Home/bin")
|
||||||
|
else distroDir.resolve("bin")
|
||||||
|
|
||||||
println("Installing native-image into $distroDir")
|
println("Installing native-image into $distroDir")
|
||||||
exec {
|
exec {
|
||||||
@@ -103,11 +115,15 @@ fun Task.configureInstallGraalVm(graalVm: BuildInfo.GraalVm) {
|
|||||||
try {
|
try {
|
||||||
Files.move(tempLink, graalVm.installDir.toPath(), StandardCopyOption.ATOMIC_MOVE)
|
Files.move(tempLink, graalVm.installDir.toPath(), StandardCopyOption.ATOMIC_MOVE)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
try { delete(tempLink.toFile()) } catch (ignored: Exception) {}
|
try {
|
||||||
|
delete(tempLink.toFile())
|
||||||
|
} catch (ignored: Exception) {}
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
try { delete(distroDir) } catch (ignored: Exception) {}
|
try {
|
||||||
|
delete(distroDir)
|
||||||
|
} catch (ignored: Exception) {}
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
/**
|
/**
|
||||||
* Allows to run Gradle plugin tests against different Gradle versions.
|
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||||
*
|
*
|
||||||
* Adds a `compatibilityTestX` task for every Gradle version X
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* between `ext.minSupportedGradleVersion` and `ext.maxSupportedGradleVersion`
|
* you may not use this file except in compliance with the License.
|
||||||
* that is not in `ext.gradleVersionsExcludedFromTesting`.
|
* You may obtain a copy of the License at
|
||||||
* The list of available Gradle versions is obtained from services.gradle.org.
|
*
|
||||||
* Adds lifecycle tasks to test against multiple Gradle versions at once, for example all Gradle release versions.
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
* Compatibility test tasks run the same tests and use the same task configuration as the project's `test` task.
|
*
|
||||||
* They set system properties for the Gradle version and distribution URL to be used.
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* These properties are consumed by the `AbstractTest` class.
|
* 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.
|
||||||
*/
|
*/
|
||||||
|
plugins { java }
|
||||||
plugins {
|
|
||||||
java
|
|
||||||
}
|
|
||||||
|
|
||||||
val gradlePluginTests = extensions.create<GradlePluginTests>("gradlePluginTests")
|
val gradlePluginTests = extensions.create<GradlePluginTests>("gradlePluginTests")
|
||||||
|
|
||||||
@@ -24,18 +24,23 @@ tasks.addRule("Pattern: compatibilityTest[All|Releases|Latest|Candidate|Nightly|
|
|||||||
when (val taskNameSuffix = matchResult.groupValues[1]) {
|
when (val taskNameSuffix = matchResult.groupValues[1]) {
|
||||||
"All" ->
|
"All" ->
|
||||||
task("compatibilityTestAll") {
|
task("compatibilityTestAll") {
|
||||||
dependsOn("compatibilityTestReleases", "compatibilityTestCandidate", "compatibilityTestNightly")
|
dependsOn(
|
||||||
|
"compatibilityTestReleases",
|
||||||
|
"compatibilityTestCandidate",
|
||||||
|
"compatibilityTestNightly"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// releases in configured range
|
// releases in configured range
|
||||||
"Releases" ->
|
"Releases" ->
|
||||||
task("compatibilityTestReleases") {
|
task("compatibilityTestReleases") {
|
||||||
val versionInfos = GradleVersionInfo.fetchReleases()
|
val versionInfos = GradleVersionInfo.fetchReleases()
|
||||||
val versionsToTestAgainst = versionInfos.filter { versionInfo ->
|
val versionsToTestAgainst =
|
||||||
val v = versionInfo.gradleVersion
|
versionInfos.filter { versionInfo ->
|
||||||
!versionInfo.broken &&
|
val v = versionInfo.gradleVersion
|
||||||
|
!versionInfo.broken &&
|
||||||
v in gradlePluginTests.minGradleVersion..gradlePluginTests.maxGradleVersion &&
|
v in gradlePluginTests.minGradleVersion..gradlePluginTests.maxGradleVersion &&
|
||||||
v !in gradlePluginTests.skippedGradleVersions
|
v !in gradlePluginTests.skippedGradleVersions
|
||||||
}
|
}
|
||||||
|
|
||||||
dependsOn(versionsToTestAgainst.map { createCompatibilityTestTask(it) })
|
dependsOn(versionsToTestAgainst.map { createCompatibilityTestTask(it) })
|
||||||
}
|
}
|
||||||
@@ -45,8 +50,10 @@ tasks.addRule("Pattern: compatibilityTest[All|Releases|Latest|Candidate|Nightly|
|
|||||||
val versionInfo = GradleVersionInfo.fetchCurrent()
|
val versionInfo = GradleVersionInfo.fetchCurrent()
|
||||||
if (versionInfo.version == gradle.gradleVersion) {
|
if (versionInfo.version == gradle.gradleVersion) {
|
||||||
doLast {
|
doLast {
|
||||||
println("No new Gradle release available. " +
|
println(
|
||||||
"(Run `gradlew test` to test against ${versionInfo.version}.)")
|
"No new Gradle release available. " +
|
||||||
|
"(Run `gradlew test` to test against ${versionInfo.version}.)"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dependsOn(createCompatibilityTestTask(versionInfo))
|
dependsOn(createCompatibilityTestTask(versionInfo))
|
||||||
@@ -59,9 +66,7 @@ tasks.addRule("Pattern: compatibilityTest[All|Releases|Latest|Candidate|Nightly|
|
|||||||
if (versionInfo?.activeRc == true) {
|
if (versionInfo?.activeRc == true) {
|
||||||
dependsOn(createCompatibilityTestTask(versionInfo))
|
dependsOn(createCompatibilityTestTask(versionInfo))
|
||||||
} else {
|
} else {
|
||||||
doLast {
|
doLast { println("No active Gradle release candidate available.") }
|
||||||
println("No active Gradle release candidate available.")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// latest nightly
|
// latest nightly
|
||||||
@@ -73,14 +78,14 @@ tasks.addRule("Pattern: compatibilityTest[All|Releases|Latest|Candidate|Nightly|
|
|||||||
// explicit version
|
// explicit version
|
||||||
else ->
|
else ->
|
||||||
createCompatibilityTestTask(
|
createCompatibilityTestTask(
|
||||||
taskNameSuffix,
|
taskNameSuffix,
|
||||||
"https://services.gradle.org/distributions-snapshots/gradle-$taskNameSuffix-bin.zip"
|
"https://services.gradle.org/distributions-snapshots/gradle-$taskNameSuffix-bin.zip"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createCompatibilityTestTask(versionInfo: GradleVersionInfo): Task =
|
fun createCompatibilityTestTask(versionInfo: GradleVersionInfo): Task =
|
||||||
createCompatibilityTestTask(versionInfo.version, versionInfo.downloadUrl)
|
createCompatibilityTestTask(versionInfo.version, versionInfo.downloadUrl)
|
||||||
|
|
||||||
fun createCompatibilityTestTask(version: String, downloadUrl: String): Task {
|
fun createCompatibilityTestTask(version: String, downloadUrl: String): Task {
|
||||||
return tasks.create("compatibilityTest$version", Test::class.java) {
|
return tasks.create("compatibilityTest$version", Test::class.java) {
|
||||||
|
|||||||
@@ -1,20 +1,33 @@
|
|||||||
plugins {
|
/**
|
||||||
base
|
* 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.
|
||||||
|
*/
|
||||||
|
plugins { base }
|
||||||
|
|
||||||
val htmlValidator = extensions.create<HtmlValidator>("htmlValidator", project)
|
val htmlValidator = extensions.create<HtmlValidator>("htmlValidator", project)
|
||||||
|
|
||||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||||
|
|
||||||
val validatorConfiguration: Configuration = configurations.create("validator") {
|
val validatorConfiguration: Configuration =
|
||||||
resolutionStrategy.eachDependency {
|
configurations.create("validator") {
|
||||||
if (requested.group == "log4j" && requested.name == "log4j") {
|
resolutionStrategy.eachDependency {
|
||||||
@Suppress("UnstableApiUsage")
|
if (requested.group == "log4j" && requested.name == "log4j") {
|
||||||
useTarget(buildInfo.libs.findLibrary("log4j12Api").get())
|
@Suppress("UnstableApiUsage") useTarget(buildInfo.libs.findLibrary("log4j12Api").get())
|
||||||
because("mitigate critical security vulnerabilities")
|
because("mitigate critical security vulnerabilities")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@Suppress("UnstableApiUsage")
|
@Suppress("UnstableApiUsage")
|
||||||
@@ -32,27 +45,29 @@ dependencies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val validateHtml by tasks.registering(JavaExec::class) {
|
val validateHtml by
|
||||||
val resultFile = layout.buildDirectory.file("validateHtml/result.txt")
|
tasks.registering(JavaExec::class) {
|
||||||
inputs.files(htmlValidator.sources)
|
val resultFile = layout.buildDirectory.file("validateHtml/result.txt")
|
||||||
outputs.file(resultFile)
|
inputs.files(htmlValidator.sources)
|
||||||
|
outputs.file(resultFile)
|
||||||
|
|
||||||
classpath = validatorConfiguration
|
classpath = validatorConfiguration
|
||||||
mainClass.set("nu.validator.client.SimpleCommandLineValidator")
|
mainClass.set("nu.validator.client.SimpleCommandLineValidator")
|
||||||
args("--skip-non-html") // --also-check-css doesn't work (still checks css as html), so limit to html files
|
args(
|
||||||
args("--filterpattern", "(.*)Consider adding “lang=(.*)")
|
"--skip-non-html"
|
||||||
args("--filterpattern", "(.*)Consider adding a “lang” attribute(.*)")
|
) // --also-check-css doesn't work (still checks css as html), so limit to html files
|
||||||
args("--filterpattern", "(.*)unrecognized media “amzn-kf8”(.*)") // kindle
|
args("--filterpattern", "(.*)Consider adding “lang=(.*)")
|
||||||
// for debugging
|
args("--filterpattern", "(.*)Consider adding a “lang” attribute(.*)")
|
||||||
// args "--verbose"
|
args("--filterpattern", "(.*)unrecognized media “amzn-kf8”(.*)") // kindle
|
||||||
args(htmlValidator.sources)
|
// for debugging
|
||||||
|
// args "--verbose"
|
||||||
|
args(htmlValidator.sources)
|
||||||
|
|
||||||
// write a basic result file s.t. gradle can consider task up-to-date
|
// write a basic result file s.t. gradle can consider task up-to-date
|
||||||
// writing a result file in case validation fails is not easily possible with JavaExec, but also not strictly necessary
|
// writing a result file in case validation fails is not easily possible with JavaExec, but also
|
||||||
doFirst { project.delete(resultFile) }
|
// not strictly necessary
|
||||||
doLast { resultFile.get().asFile.writeText("Success.") }
|
doFirst { project.delete(resultFile) }
|
||||||
}
|
doLast { resultFile.get().asFile.writeText("Success.") }
|
||||||
|
}
|
||||||
|
|
||||||
tasks.check {
|
tasks.check { dependsOn(validateHtml) }
|
||||||
dependsOn(validateHtml)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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 org.gradle.accessors.dm.LibrariesForLibs
|
import org.gradle.accessors.dm.LibrariesForLibs
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
|
|||||||
@@ -1,9 +1,22 @@
|
|||||||
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
|
/**
|
||||||
|
* 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.net.URI
|
import java.net.URI
|
||||||
|
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
|
||||||
|
|
||||||
plugins {
|
plugins { kotlin("jvm") }
|
||||||
kotlin("jvm")
|
|
||||||
}
|
|
||||||
|
|
||||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||||
|
|
||||||
@@ -23,38 +36,40 @@ tasks.withType<Test>().configureEach {
|
|||||||
|
|
||||||
// enable checking of stdlib return types
|
// enable checking of stdlib return types
|
||||||
systemProperty("org.pkl.testMode", "true")
|
systemProperty("org.pkl.testMode", "true")
|
||||||
|
|
||||||
// Disable colour output in tests
|
// Disable colour output in tests
|
||||||
systemProperty("org.fusesource.jansi.Ansi.disable", "true")
|
systemProperty("org.fusesource.jansi.Ansi.disable", "true")
|
||||||
|
|
||||||
reports.named("html") {
|
reports.named("html") { enabled = true }
|
||||||
enabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
testLogging {
|
testLogging { exceptionFormat = TestExceptionFormat.FULL }
|
||||||
exceptionFormat = TestExceptionFormat.FULL
|
|
||||||
}
|
|
||||||
|
|
||||||
addTestListener(object : TestListener {
|
addTestListener(
|
||||||
override fun beforeSuite(suite: TestDescriptor) {}
|
object : TestListener {
|
||||||
override fun beforeTest(testDescriptor: TestDescriptor) {}
|
override fun beforeSuite(suite: TestDescriptor) {}
|
||||||
override fun afterTest(testDescriptor: TestDescriptor, result: TestResult) {}
|
|
||||||
|
|
||||||
// print report link at end of task, not just at end of build
|
override fun beforeTest(testDescriptor: TestDescriptor) {}
|
||||||
override fun afterSuite(descriptor: TestDescriptor, result: TestResult) {
|
|
||||||
if (descriptor.parent != null) return // only interested in overall result
|
|
||||||
|
|
||||||
if (result.resultType == TestResult.ResultType.FAILURE) {
|
override fun afterTest(testDescriptor: TestDescriptor, result: TestResult) {}
|
||||||
println("\nThere were failing tests. See the report at: ${fixFileUri(testTask.reports.html.entryPoint.toURI())}")
|
|
||||||
|
// print report link at end of task, not just at end of build
|
||||||
|
override fun afterSuite(descriptor: TestDescriptor, result: TestResult) {
|
||||||
|
if (descriptor.parent != null) return // only interested in overall result
|
||||||
|
|
||||||
|
if (result.resultType == TestResult.ResultType.FAILURE) {
|
||||||
|
println(
|
||||||
|
"\nThere were failing tests. See the report at: ${fixFileUri(testTask.reports.html.entryPoint.toURI())}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// makes links clickable on macOS
|
||||||
|
private fun fixFileUri(uri: URI): URI {
|
||||||
|
if ("file" == uri.scheme && !uri.schemeSpecificPart.startsWith("//")) {
|
||||||
|
return URI.create("file://" + uri.schemeSpecificPart)
|
||||||
|
}
|
||||||
|
return uri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)
|
||||||
// makes links clickable on macOS
|
|
||||||
private fun fixFileUri(uri: URI): URI {
|
|
||||||
if ("file" == uri.scheme && !uri.schemeSpecificPart.startsWith("//")) {
|
|
||||||
return URI.create("file://" + uri.schemeSpecificPart)
|
|
||||||
}
|
|
||||||
return uri
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
val assembleNative by tasks.registering {}
|
val assembleNative by tasks.registering {}
|
||||||
|
|
||||||
val testNative by tasks.registering {}
|
val testNative by tasks.registering {}
|
||||||
|
|
||||||
val checkNative by tasks.registering {
|
val checkNative by tasks.registering { dependsOn(testNative) }
|
||||||
dependsOn(testNative)
|
|
||||||
}
|
|
||||||
|
|
||||||
val buildNative by tasks.registering {
|
val buildNative by tasks.registering { dependsOn(assembleNative, checkNative) }
|
||||||
dependsOn(assembleNative, checkNative)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,21 @@
|
|||||||
import org.gradle.api.publish.maven.tasks.GenerateMavenPom
|
/**
|
||||||
|
* 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.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
import java.util.Base64
|
import java.util.Base64
|
||||||
|
import org.gradle.api.publish.maven.tasks.GenerateMavenPom
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
@@ -10,9 +25,7 @@ plugins {
|
|||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
components.findByName("java")?.let { javaComponent ->
|
components.findByName("java")?.let { javaComponent ->
|
||||||
create<MavenPublication>("library") {
|
create<MavenPublication>("library") { from(javaComponent) }
|
||||||
from(javaComponent)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
withType<MavenPublication>().configureEach {
|
withType<MavenPublication>().configureEach {
|
||||||
pom {
|
pom {
|
||||||
@@ -49,63 +62,66 @@ publishing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val validatePom by tasks.registering {
|
val validatePom by
|
||||||
if (tasks.findByName("generatePomFileForLibraryPublication") == null) {
|
tasks.registering {
|
||||||
return@registering
|
if (tasks.findByName("generatePomFileForLibraryPublication") == null) {
|
||||||
}
|
return@registering
|
||||||
val generatePomFileForLibraryPublication by tasks.existing(GenerateMavenPom::class)
|
}
|
||||||
val outputFile = layout.buildDirectory.file("validatePom") // dummy output to satisfy up-to-date check
|
val generatePomFileForLibraryPublication by tasks.existing(GenerateMavenPom::class)
|
||||||
|
val outputFile =
|
||||||
|
layout.buildDirectory.file("validatePom") // dummy output to satisfy up-to-date check
|
||||||
|
|
||||||
dependsOn(generatePomFileForLibraryPublication)
|
dependsOn(generatePomFileForLibraryPublication)
|
||||||
inputs.file(generatePomFileForLibraryPublication.get().destination)
|
inputs.file(generatePomFileForLibraryPublication.get().destination)
|
||||||
outputs.file(outputFile)
|
outputs.file(outputFile)
|
||||||
|
|
||||||
doLast {
|
doLast {
|
||||||
outputFile.get().asFile.delete()
|
outputFile.get().asFile.delete()
|
||||||
|
|
||||||
val pomFile = generatePomFileForLibraryPublication.get().destination
|
val pomFile = generatePomFileForLibraryPublication.get().destination
|
||||||
assert(pomFile.exists())
|
assert(pomFile.exists())
|
||||||
|
|
||||||
val text = pomFile.readText()
|
val text = pomFile.readText()
|
||||||
|
|
||||||
run {
|
run {
|
||||||
val unresolvedVersion = Regex("<version>.*[+,()\\[\\]].*</version>")
|
val unresolvedVersion = Regex("<version>.*[+,()\\[\\]].*</version>")
|
||||||
val matches = unresolvedVersion.findAll(text).toList()
|
val matches = unresolvedVersion.findAll(text).toList()
|
||||||
if (matches.isNotEmpty()) {
|
if (matches.isNotEmpty()) {
|
||||||
throw GradleException(
|
throw GradleException(
|
||||||
"""
|
"""
|
||||||
Found unresolved version selector(s) in generated POM:
|
Found unresolved version selector(s) in generated POM:
|
||||||
${matches.joinToString("\n") { it.groupValues[0] }}
|
${matches.joinToString("\n") { it.groupValues[0] }}
|
||||||
""".trimIndent()
|
"""
|
||||||
)
|
.trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||||
if (buildInfo.isReleaseBuild) {
|
if (buildInfo.isReleaseBuild) {
|
||||||
val snapshotVersion = Regex("<version>.*-SNAPSHOT</version>")
|
val snapshotVersion = Regex("<version>.*-SNAPSHOT</version>")
|
||||||
val matches = snapshotVersion.findAll(text).toList()
|
val matches = snapshotVersion.findAll(text).toList()
|
||||||
if (matches.isNotEmpty()) {
|
if (matches.isNotEmpty()) {
|
||||||
throw GradleException(
|
throw GradleException(
|
||||||
"""
|
"""
|
||||||
Found snapshot version(s) in generated POM of Pkl release version:
|
Found snapshot version(s) in generated POM of Pkl release version:
|
||||||
${matches.joinToString("\n") { it.groupValues[0] }}
|
${matches.joinToString("\n") { it.groupValues[0] }}
|
||||||
""".trimIndent()
|
"""
|
||||||
)
|
.trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outputFile.get().asFile.writeText("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
outputFile.get().asFile.writeText("OK")
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
tasks.publish {
|
tasks.publish { dependsOn(validatePom) }
|
||||||
dependsOn(validatePom)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Workaround for maven publish plugin not setting up dependencies correctly.
|
// Workaround for maven publish plugin not setting up dependencies correctly.
|
||||||
// Taken from https://github.com/gradle/gradle/issues/26091#issuecomment-1798137734
|
// Taken from https://github.com/gradle/gradle/issues/26091#issuecomment-1798137734
|
||||||
val dependsOnTasks = mutableListOf<String>()
|
val dependsOnTasks = mutableListOf<String>()
|
||||||
|
|
||||||
tasks.withType<AbstractPublishToMaven>().configureEach {
|
tasks.withType<AbstractPublishToMaven>().configureEach {
|
||||||
dependsOnTasks.add(name.replace("publish", "sign").replaceAfter("Publication", ""))
|
dependsOnTasks.add(name.replace("publish", "sign").replaceAfter("Publication", ""))
|
||||||
dependsOn(dependsOnTasks)
|
dependsOn(dependsOnTasks)
|
||||||
@@ -114,8 +130,10 @@ tasks.withType<AbstractPublishToMaven>().configureEach {
|
|||||||
signing {
|
signing {
|
||||||
// provided as env vars `ORG_GRADLE_PROJECT_signingKey` and `ORG_GRADLE_PROJECT_signingPassword`
|
// provided as env vars `ORG_GRADLE_PROJECT_signingKey` and `ORG_GRADLE_PROJECT_signingPassword`
|
||||||
// in CI.
|
// in CI.
|
||||||
val signingKey = (findProperty("signingKey") as String?)
|
val signingKey =
|
||||||
?.let { Base64.getDecoder().decode(it).toString(StandardCharsets.US_ASCII) }
|
(findProperty("signingKey") as String?)?.let {
|
||||||
|
Base64.getDecoder().decode(it).toString(StandardCharsets.US_ASCII)
|
||||||
|
}
|
||||||
val signingPassword = findProperty("signingPassword") as String?
|
val signingPassword = findProperty("signingPassword") as String?
|
||||||
if (signingKey != null && signingPassword != null) {
|
if (signingKey != null && signingPassword != null) {
|
||||||
useInMemoryPgpKeys(signingKey, signingPassword)
|
useInMemoryPgpKeys(signingKey, signingPassword)
|
||||||
|
|||||||
@@ -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 org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
@@ -12,10 +27,7 @@ sourceSets {
|
|||||||
srcDir(file("modules/pkl-config-java/examples"))
|
srcDir(file("modules/pkl-config-java/examples"))
|
||||||
srcDir(file("modules/java-binding/examples"))
|
srcDir(file("modules/java-binding/examples"))
|
||||||
}
|
}
|
||||||
val kotlin = project.extensions
|
val kotlin = project.extensions.getByType<KotlinJvmProjectExtension>().sourceSets[name].kotlin
|
||||||
.getByType<KotlinJvmProjectExtension>()
|
|
||||||
.sourceSets[name]
|
|
||||||
.kotlin
|
|
||||||
kotlin.srcDir(file("modules/kotlin-binding/examples"))
|
kotlin.srcDir(file("modules/kotlin-binding/examples"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,7 +42,8 @@ dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tasks.test {
|
tasks.test {
|
||||||
inputs.files(fileTree("modules").matching {
|
inputs
|
||||||
include("**/pages/*.adoc")
|
.files(fileTree("modules").matching { include("**/pages/*.adoc") })
|
||||||
}).withPropertyName("asciiDocFiles").withPathSensitivity(PathSensitivity.RELATIVE)
|
.withPropertyName("asciiDocFiles")
|
||||||
|
.withPathSensitivity(PathSensitivity.RELATIVE)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
pklAllProjects
|
pklAllProjects
|
||||||
pklKotlinLibrary
|
pklKotlinLibrary
|
||||||
@@ -7,11 +22,9 @@ plugins {
|
|||||||
|
|
||||||
// already on build script class path (see buildSrc/build.gradle.kts),
|
// already on build script class path (see buildSrc/build.gradle.kts),
|
||||||
// hence must only specify plugin ID here
|
// hence must only specify plugin ID here
|
||||||
@Suppress("DSL_SCOPE_VIOLATION")
|
@Suppress("DSL_SCOPE_VIOLATION") id(libs.plugins.shadow.get().pluginId)
|
||||||
id(libs.plugins.shadow.get().pluginId)
|
|
||||||
|
|
||||||
@Suppress("DSL_SCOPE_VIOLATION")
|
@Suppress("DSL_SCOPE_VIOLATION") alias(libs.plugins.checksum)
|
||||||
alias(libs.plugins.checksum)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// make Java executable available to other subprojects
|
// make Java executable available to other subprojects
|
||||||
@@ -54,7 +67,7 @@ dependencies {
|
|||||||
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk8")
|
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk8")
|
||||||
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-common")
|
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-common")
|
||||||
}
|
}
|
||||||
|
|
||||||
testImplementation(projects.pklCommonsTest)
|
testImplementation(projects.pklCommonsTest)
|
||||||
testImplementation(libs.wiremock)
|
testImplementation(libs.wiremock)
|
||||||
|
|
||||||
@@ -69,17 +82,13 @@ dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tasks.jar {
|
tasks.jar {
|
||||||
manifest {
|
manifest { attributes += mapOf("Main-Class" to "org.pkl.cli.Main") }
|
||||||
attributes += mapOf("Main-Class" to "org.pkl.cli.Main")
|
|
||||||
}
|
|
||||||
|
|
||||||
// not required at runtime
|
// not required at runtime
|
||||||
exclude("org/pkl/cli/svm/**")
|
exclude("org/pkl/cli/svm/**")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.javadoc {
|
tasks.javadoc { enabled = false }
|
||||||
enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.shadowJar {
|
tasks.shadowJar {
|
||||||
archiveFileName.set("jpkl")
|
archiveFileName.set("jpkl")
|
||||||
@@ -93,72 +102,74 @@ tasks.shadowJar {
|
|||||||
exclude("module-info.*")
|
exclude("module-info.*")
|
||||||
}
|
}
|
||||||
|
|
||||||
val javaExecutable by tasks.registering(ExecutableJar::class) {
|
val javaExecutable by
|
||||||
inJar.set(tasks.shadowJar.flatMap { it.archiveFile })
|
tasks.registering(ExecutableJar::class) {
|
||||||
outJar.set(layout.buildDirectory.file("executable/jpkl"))
|
inJar.set(tasks.shadowJar.flatMap { it.archiveFile })
|
||||||
|
outJar.set(layout.buildDirectory.file("executable/jpkl"))
|
||||||
|
|
||||||
// uncomment for debugging
|
// uncomment for debugging
|
||||||
//jvmArgs.addAll("-ea", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005")
|
// jvmArgs.addAll("-ea", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005")
|
||||||
}
|
}
|
||||||
|
|
||||||
val testJavaExecutable by tasks.registering(Test::class) {
|
val testJavaExecutable by
|
||||||
testClassesDirs = tasks.test.get().testClassesDirs
|
tasks.registering(Test::class) {
|
||||||
classpath =
|
testClassesDirs = tasks.test.get().testClassesDirs
|
||||||
// compiled test classes
|
classpath =
|
||||||
sourceSets.test.get().output +
|
// compiled test classes
|
||||||
// java executable
|
sourceSets.test.get().output +
|
||||||
javaExecutable.get().outputs.files +
|
// java executable
|
||||||
// test-only dependencies
|
javaExecutable.get().outputs.files +
|
||||||
// (test dependencies that are also main dependencies must already be contained in java executable;
|
// test-only dependencies
|
||||||
// to verify that, we don't want to include them here)
|
// (test dependencies that are also main dependencies must already be contained in java
|
||||||
(configurations.testRuntimeClasspath.get() - configurations.runtimeClasspath.get())
|
// executable;
|
||||||
}
|
// to verify that, we don't want to include them here)
|
||||||
|
(configurations.testRuntimeClasspath.get() - configurations.runtimeClasspath.get())
|
||||||
|
}
|
||||||
|
|
||||||
tasks.check {
|
tasks.check { dependsOn(testJavaExecutable) }
|
||||||
dependsOn(testJavaExecutable)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0.14 Java executable was broken because javaExecutable.jvmArgs wasn't commented out.
|
// 0.14 Java executable was broken because javaExecutable.jvmArgs wasn't commented out.
|
||||||
// To catch this and similar problems, test that Java executable starts successfully.
|
// To catch this and similar problems, test that Java executable starts successfully.
|
||||||
val testStartJavaExecutable by tasks.registering(Exec::class) {
|
val testStartJavaExecutable by
|
||||||
dependsOn(javaExecutable)
|
tasks.registering(Exec::class) {
|
||||||
val outputFile =
|
dependsOn(javaExecutable)
|
||||||
layout.buildDirectory.file("testStartJavaExecutable") // dummy output to satisfy up-to-date check
|
val outputFile =
|
||||||
outputs.file(outputFile)
|
layout.buildDirectory.file(
|
||||||
|
"testStartJavaExecutable"
|
||||||
|
) // dummy output to satisfy up-to-date check
|
||||||
|
outputs.file(outputFile)
|
||||||
|
|
||||||
if (buildInfo.os.isWindows) {
|
if (buildInfo.os.isWindows) {
|
||||||
executable = "java"
|
executable = "java"
|
||||||
args("-jar", javaExecutable.get().outputs.files.singleFile.toString(), "--version")
|
args("-jar", javaExecutable.get().outputs.files.singleFile.toString(), "--version")
|
||||||
} else {
|
} else {
|
||||||
executable = javaExecutable.get().outputs.files.singleFile.toString()
|
executable = javaExecutable.get().outputs.files.singleFile.toString()
|
||||||
args("--version")
|
args("--version")
|
||||||
|
}
|
||||||
|
|
||||||
|
doFirst { outputFile.get().asFile.delete() }
|
||||||
|
|
||||||
|
doLast { outputFile.get().asFile.writeText("OK") }
|
||||||
}
|
}
|
||||||
|
|
||||||
doFirst { outputFile.get().asFile.delete() }
|
tasks.check { dependsOn(testStartJavaExecutable) }
|
||||||
|
|
||||||
doLast { outputFile.get().asFile.writeText("OK") }
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.check {
|
|
||||||
dependsOn(testStartJavaExecutable)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Exec.configureExecutable(
|
fun Exec.configureExecutable(
|
||||||
graalVm: BuildInfo.GraalVm,
|
graalVm: BuildInfo.GraalVm,
|
||||||
outputFile: Provider<RegularFile>,
|
outputFile: Provider<RegularFile>,
|
||||||
extraArgs: List<String> = listOf()
|
extraArgs: List<String> = listOf()
|
||||||
) {
|
) {
|
||||||
inputs.files(sourceSets.main.map { it.output })
|
inputs
|
||||||
|
.files(sourceSets.main.map { it.output })
|
||||||
.withPropertyName("mainSourceSets")
|
.withPropertyName("mainSourceSets")
|
||||||
.withPathSensitivity(PathSensitivity.RELATIVE)
|
.withPathSensitivity(PathSensitivity.RELATIVE)
|
||||||
inputs.files(configurations.runtimeClasspath)
|
inputs
|
||||||
|
.files(configurations.runtimeClasspath)
|
||||||
.withPropertyName("runtimeClasspath")
|
.withPropertyName("runtimeClasspath")
|
||||||
.withNormalizer(ClasspathNormalizer::class)
|
.withNormalizer(ClasspathNormalizer::class)
|
||||||
val nativeImageCommandName = if (buildInfo.os.isWindows) "native-image.cmd" else "native-image"
|
val nativeImageCommandName = if (buildInfo.os.isWindows) "native-image.cmd" else "native-image"
|
||||||
inputs.files(
|
inputs
|
||||||
file(graalVm.baseDir)
|
.files(file(graalVm.baseDir).resolve("bin/$nativeImageCommandName"))
|
||||||
.resolve("bin/$nativeImageCommandName")
|
|
||||||
)
|
|
||||||
.withPropertyName("graalVmNativeImage")
|
.withPropertyName("graalVmNativeImage")
|
||||||
.withPathSensitivity(PathSensitivity.ABSOLUTE)
|
.withPathSensitivity(PathSensitivity.ABSOLUTE)
|
||||||
outputs.file(outputFile)
|
outputs.file(outputFile)
|
||||||
@@ -170,99 +181,108 @@ fun Exec.configureExecutable(
|
|||||||
// JARs to exclude from the class path for the native-image build.
|
// JARs to exclude from the class path for the native-image build.
|
||||||
val exclusions = listOf(libs.truffleApi, libs.graalSdk).map { it.get().module.name }
|
val exclusions = listOf(libs.truffleApi, libs.graalSdk).map { it.get().module.name }
|
||||||
// https://www.graalvm.org/22.0/reference-manual/native-image/Options/
|
// https://www.graalvm.org/22.0/reference-manual/native-image/Options/
|
||||||
argumentProviders.add(CommandLineArgumentProvider {
|
argumentProviders.add(
|
||||||
buildList {
|
CommandLineArgumentProvider {
|
||||||
// currently gives a deprecation warning, but we've been told
|
buildList {
|
||||||
// that the "initialize everything at build time" *CLI* option is likely here to stay
|
// currently gives a deprecation warning, but we've been told
|
||||||
add("--initialize-at-build-time=")
|
// that the "initialize everything at build time" *CLI* option is likely here to stay
|
||||||
// needed for messagepack-java (see https://github.com/msgpack/msgpack-java/issues/600)
|
add("--initialize-at-build-time=")
|
||||||
// needed for jansi (see https://github.com/fusesource/jansi/issues/199#issuecomment-1252268229)
|
// needed for messagepack-java (see https://github.com/msgpack/msgpack-java/issues/600)
|
||||||
add("--initialize-at-run-time=org.msgpack.core.buffer.DirectBufferAccess,org.fusesource.jansi.internal")
|
// needed for jansi (see
|
||||||
add("--no-fallback")
|
// https://github.com/fusesource/jansi/issues/199#issuecomment-1252268229)
|
||||||
add("-H:IncludeResources=org/pkl/core/stdlib/.*\\.pkl")
|
add(
|
||||||
add("-H:IncludeResources=org/jline/utils/.*")
|
"--initialize-at-run-time=org.msgpack.core.buffer.DirectBufferAccess,org.fusesource.jansi.internal"
|
||||||
add("-H:IncludeResourceBundles=org.pkl.core.errorMessages")
|
)
|
||||||
add("-H:IncludeResources=org/pkl/commons/cli/PklCARoots.pem")
|
add("--no-fallback")
|
||||||
add("--macro:truffle")
|
add("-H:IncludeResources=org/pkl/core/stdlib/.*\\.pkl")
|
||||||
add("-H:Class=org.pkl.cli.Main")
|
add("-H:IncludeResources=org/jline/utils/.*")
|
||||||
add("-H:Name=${outputFile.get().asFile.name}")
|
add("-H:IncludeResourceBundles=org.pkl.core.errorMessages")
|
||||||
// the actual limit (currently) used by native-image is this number + 1400 (idea is to compensate for Truffle's own nodes)
|
add("-H:IncludeResources=org/pkl/commons/cli/PklCARoots.pem")
|
||||||
add("-H:MaxRuntimeCompileMethods=1800")
|
add("--macro:truffle")
|
||||||
add("-H:+EnforceMaxRuntimeCompileMethods")
|
add("-H:Class=org.pkl.cli.Main")
|
||||||
add("--enable-url-protocols=http,https")
|
add("-H:Name=${outputFile.get().asFile.name}")
|
||||||
add("-H:+ReportExceptionStackTraces")
|
// the actual limit (currently) used by native-image is this number + 1400 (idea is to
|
||||||
// disable automatic support for JVM CLI options (puts our main class in full control of argument parsing)
|
// compensate for Truffle's own nodes)
|
||||||
add("-H:-ParseRuntimeOptions")
|
add("-H:MaxRuntimeCompileMethods=1800")
|
||||||
// quick build mode: 40% faster compilation, 20% smaller (but presumably also slower) executable
|
add("-H:+EnforceMaxRuntimeCompileMethods")
|
||||||
if (!buildInfo.isReleaseBuild) {
|
add("--enable-url-protocols=http,https")
|
||||||
add("-Ob")
|
add("-H:+ReportExceptionStackTraces")
|
||||||
|
// disable automatic support for JVM CLI options (puts our main class in full control of
|
||||||
|
// argument parsing)
|
||||||
|
add("-H:-ParseRuntimeOptions")
|
||||||
|
// quick build mode: 40% faster compilation, 20% smaller (but presumably also slower)
|
||||||
|
// executable
|
||||||
|
if (!buildInfo.isReleaseBuild) {
|
||||||
|
add("-Ob")
|
||||||
|
}
|
||||||
|
add("-march=compatibility")
|
||||||
|
// native-image rejects non-existing class path entries -> filter
|
||||||
|
add("--class-path")
|
||||||
|
val pathInput =
|
||||||
|
sourceSets.main.get().output +
|
||||||
|
configurations.runtimeClasspath.get().filter {
|
||||||
|
it.exists() && !exclusions.any { exclude -> it.name.contains(exclude) }
|
||||||
|
}
|
||||||
|
add(pathInput.asPath)
|
||||||
|
// make sure dev machine stays responsive (15% slowdown on my laptop)
|
||||||
|
val processors =
|
||||||
|
Runtime.getRuntime().availableProcessors() /
|
||||||
|
if (buildInfo.os.isMacOsX && !buildInfo.isCiBuild) 4 else 1
|
||||||
|
add("-J-XX:ActiveProcessorCount=${processors}")
|
||||||
|
// Pass through all `HOMEBREW_` prefixed environment variables to allow build with shimmed
|
||||||
|
// tools.
|
||||||
|
addAll(environment.keys.filter { it.startsWith("HOMEBREW_") }.map { "-E$it" })
|
||||||
|
addAll(extraArgs)
|
||||||
}
|
}
|
||||||
add("-march=compatibility")
|
|
||||||
// native-image rejects non-existing class path entries -> filter
|
|
||||||
add("--class-path")
|
|
||||||
val pathInput = sourceSets.main.get().output + configurations.runtimeClasspath.get()
|
|
||||||
.filter { it.exists() && !exclusions.any { exclude -> it.name.contains(exclude) } }
|
|
||||||
add(pathInput.asPath)
|
|
||||||
// make sure dev machine stays responsive (15% slowdown on my laptop)
|
|
||||||
val processors = Runtime.getRuntime().availableProcessors() /
|
|
||||||
if (buildInfo.os.isMacOsX && !buildInfo.isCiBuild) 4 else 1
|
|
||||||
add("-J-XX:ActiveProcessorCount=${processors}")
|
|
||||||
// Pass through all `HOMEBREW_` prefixed environment variables to allow build with shimmed tools.
|
|
||||||
addAll(environment.keys.filter { it.startsWith("HOMEBREW_") }.map { "-E$it" })
|
|
||||||
addAll(extraArgs)
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the pkl CLI for macOS/amd64.
|
|
||||||
*/
|
|
||||||
val macExecutableAmd64: TaskProvider<Exec> by tasks.registering(Exec::class) {
|
|
||||||
dependsOn(":installGraalVmAmd64")
|
|
||||||
configureExecutable(
|
|
||||||
buildInfo.graalVmAmd64,
|
|
||||||
layout.buildDirectory.file("executable/pkl-macos-amd64")
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Builds the pkl CLI for macOS/amd64. */
|
||||||
* Builds the pkl CLI for macOS/aarch64.
|
val macExecutableAmd64: TaskProvider<Exec> by
|
||||||
*/
|
tasks.registering(Exec::class) {
|
||||||
val macExecutableAarch64: TaskProvider<Exec> by tasks.registering(Exec::class) {
|
dependsOn(":installGraalVmAmd64")
|
||||||
dependsOn(":installGraalVmAarch64")
|
configureExecutable(
|
||||||
configureExecutable(
|
buildInfo.graalVmAmd64,
|
||||||
buildInfo.graalVmAarch64,
|
layout.buildDirectory.file("executable/pkl-macos-amd64")
|
||||||
layout.buildDirectory.file("executable/pkl-macos-aarch64"),
|
|
||||||
listOf(
|
|
||||||
"-H:+AllowDeprecatedBuilderClassesOnImageClasspath"
|
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Builds the pkl CLI for macOS/aarch64. */
|
||||||
* Builds the pkl CLI for linux/amd64.
|
val macExecutableAarch64: TaskProvider<Exec> by
|
||||||
*/
|
tasks.registering(Exec::class) {
|
||||||
val linuxExecutableAmd64: TaskProvider<Exec> by tasks.registering(Exec::class) {
|
dependsOn(":installGraalVmAarch64")
|
||||||
dependsOn(":installGraalVmAmd64")
|
configureExecutable(
|
||||||
configureExecutable(
|
buildInfo.graalVmAarch64,
|
||||||
buildInfo.graalVmAmd64,
|
layout.buildDirectory.file("executable/pkl-macos-aarch64"),
|
||||||
layout.buildDirectory.file("executable/pkl-linux-amd64")
|
listOf("-H:+AllowDeprecatedBuilderClassesOnImageClasspath")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Builds the pkl CLI for linux/amd64. */
|
||||||
|
val linuxExecutableAmd64: TaskProvider<Exec> by
|
||||||
|
tasks.registering(Exec::class) {
|
||||||
|
dependsOn(":installGraalVmAmd64")
|
||||||
|
configureExecutable(
|
||||||
|
buildInfo.graalVmAmd64,
|
||||||
|
layout.buildDirectory.file("executable/pkl-linux-amd64")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the pkl CLI for linux/aarch64.
|
* Builds the pkl CLI for linux/aarch64.
|
||||||
*
|
*
|
||||||
* Right now, this is built within a container on Mac using emulation because CI does not have
|
* Right now, this is built within a container on Mac using emulation because CI does not have ARM
|
||||||
* ARM instances.
|
* instances.
|
||||||
*/
|
*/
|
||||||
val linuxExecutableAarch64: TaskProvider<Exec> by tasks.registering(Exec::class) {
|
val linuxExecutableAarch64: TaskProvider<Exec> by
|
||||||
dependsOn(":installGraalVmAarch64")
|
tasks.registering(Exec::class) {
|
||||||
configureExecutable(
|
dependsOn(":installGraalVmAarch64")
|
||||||
buildInfo.graalVmAarch64,
|
configureExecutable(
|
||||||
layout.buildDirectory.file("executable/pkl-linux-aarch64")
|
buildInfo.graalVmAarch64,
|
||||||
)
|
layout.buildDirectory.file("executable/pkl-linux-aarch64")
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a statically linked CLI for linux/amd64.
|
* Builds a statically linked CLI for linux/amd64.
|
||||||
@@ -270,23 +290,25 @@ val linuxExecutableAarch64: TaskProvider<Exec> by tasks.registering(Exec::class)
|
|||||||
* Note: we don't publish the same for linux/aarch64 because native-image doesn't support this.
|
* Note: we don't publish the same for linux/aarch64 because native-image doesn't support this.
|
||||||
* Details: https://www.graalvm.org/22.0/reference-manual/native-image/ARM64/
|
* Details: https://www.graalvm.org/22.0/reference-manual/native-image/ARM64/
|
||||||
*/
|
*/
|
||||||
val alpineExecutableAmd64: TaskProvider<Exec> by tasks.registering(Exec::class) {
|
val alpineExecutableAmd64: TaskProvider<Exec> by
|
||||||
dependsOn(":installGraalVmAmd64")
|
tasks.registering(Exec::class) {
|
||||||
configureExecutable(
|
dependsOn(":installGraalVmAmd64")
|
||||||
buildInfo.graalVmAmd64,
|
configureExecutable(
|
||||||
layout.buildDirectory.file("executable/pkl-alpine-linux-amd64"),
|
buildInfo.graalVmAmd64,
|
||||||
listOf("--static", "--libc=musl")
|
layout.buildDirectory.file("executable/pkl-alpine-linux-amd64"),
|
||||||
)
|
listOf("--static", "--libc=musl")
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val windowsExecutableAmd64: TaskProvider<Exec> by tasks.registering(Exec::class) {
|
val windowsExecutableAmd64: TaskProvider<Exec> by
|
||||||
dependsOn(":installGraalVmAmd64")
|
tasks.registering(Exec::class) {
|
||||||
configureExecutable(
|
dependsOn(":installGraalVmAmd64")
|
||||||
buildInfo.graalVmAmd64,
|
configureExecutable(
|
||||||
layout.buildDirectory.file("executable/pkl-windows-amd64"),
|
buildInfo.graalVmAmd64,
|
||||||
listOf("-Dfile.encoding=UTF-8")
|
layout.buildDirectory.file("executable/pkl-windows-amd64"),
|
||||||
)
|
listOf("-Dfile.encoding=UTF-8")
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
|
||||||
tasks.assembleNative {
|
tasks.assembleNative {
|
||||||
when {
|
when {
|
||||||
@@ -296,15 +318,12 @@ tasks.assembleNative {
|
|||||||
dependsOn(macExecutableAarch64)
|
dependsOn(macExecutableAarch64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildInfo.os.isWindows -> {
|
buildInfo.os.isWindows -> {
|
||||||
dependsOn(windowsExecutableAmd64)
|
dependsOn(windowsExecutableAmd64)
|
||||||
}
|
}
|
||||||
|
|
||||||
buildInfo.os.isLinux && buildInfo.arch == "aarch64" -> {
|
buildInfo.os.isLinux && buildInfo.arch == "aarch64" -> {
|
||||||
dependsOn(linuxExecutableAarch64)
|
dependsOn(linuxExecutableAarch64)
|
||||||
}
|
}
|
||||||
|
|
||||||
buildInfo.os.isLinux && buildInfo.arch == "amd64" -> {
|
buildInfo.os.isLinux && buildInfo.arch == "amd64" -> {
|
||||||
dependsOn(linuxExecutableAmd64)
|
dependsOn(linuxExecutableAmd64)
|
||||||
if (buildInfo.hasMuslToolchain) {
|
if (buildInfo.hasMuslToolchain) {
|
||||||
@@ -315,7 +334,8 @@ tasks.assembleNative {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make Java executable available to other subprojects
|
// make Java executable available to other subprojects
|
||||||
// (we don't do the same for native executables because we don't want tasks assemble/build to build them)
|
// (we don't do the same for native executables because we don't want tasks assemble/build to build
|
||||||
|
// them)
|
||||||
artifacts {
|
artifacts {
|
||||||
add("javaExecutable", javaExecutable.map { it.outputs.files.singleFile }) {
|
add("javaExecutable", javaExecutable.map { it.outputs.files.singleFile }) {
|
||||||
name = "pkl-cli-java"
|
name = "pkl-cli-java"
|
||||||
@@ -325,7 +345,7 @@ artifacts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//region Maven Publishing
|
// region Maven Publishing
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
register<MavenPublication>("javaExecutable") {
|
register<MavenPublication>("javaExecutable") {
|
||||||
@@ -344,7 +364,8 @@ publishing {
|
|||||||
Pkl CLI executable for Java.
|
Pkl CLI executable for Java.
|
||||||
Can be executed directly on *nix (if the `java` command is found on the PATH) and with `java -jar` otherwise.
|
Can be executed directly on *nix (if the `java` command is found on the PATH) and with `java -jar` otherwise.
|
||||||
Requires Java 17 or higher.
|
Requires Java 17 or higher.
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -438,5 +459,4 @@ signing {
|
|||||||
sign(publishing.publications["macExecutableAmd64"])
|
sign(publishing.publications["macExecutableAmd64"])
|
||||||
sign(publishing.publications["alpineLinuxExecutableAmd64"])
|
sign(publishing.publications["alpineLinuxExecutableAmd64"])
|
||||||
sign(publishing.publications["windowsExecutableAmd64"])
|
sign(publishing.publications["windowsExecutableAmd64"])
|
||||||
}
|
} // endregion
|
||||||
//endregion
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
pklAllProjects
|
pklAllProjects
|
||||||
pklKotlinLibrary
|
pklKotlinLibrary
|
||||||
@@ -19,25 +34,22 @@ dependencies {
|
|||||||
// with `org.gradle.parallel=true` and without the line below, `test` strangely runs into:
|
// with `org.gradle.parallel=true` and without the line below, `test` strangely runs into:
|
||||||
// java.lang.NoClassDefFoundError: Lorg/pkl/config/java/ConfigEvaluator;
|
// java.lang.NoClassDefFoundError: Lorg/pkl/config/java/ConfigEvaluator;
|
||||||
// perhaps somehow related to InMemoryJavaCompiler?
|
// perhaps somehow related to InMemoryJavaCompiler?
|
||||||
tasks.test {
|
tasks.test { mustRunAfter(":pkl-config-java:testFatJar") }
|
||||||
mustRunAfter(":pkl-config-java:testFatJar")
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.jar {
|
tasks.jar { manifest { attributes += mapOf("Main-Class" to "org.pkl.codegen.java.Main") } }
|
||||||
manifest {
|
|
||||||
attributes += mapOf("Main-Class" to "org.pkl.codegen.java.Main")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
named<MavenPublication>("library") {
|
named<MavenPublication>("library") {
|
||||||
pom {
|
pom {
|
||||||
url.set("https://github.com/apple/pkl/tree/main/pkl-codegen-java")
|
url.set("https://github.com/apple/pkl/tree/main/pkl-codegen-java")
|
||||||
description.set("""
|
description.set(
|
||||||
|
"""
|
||||||
Java source code generator that generates corresponding Java classes for Pkl classes,
|
Java source code generator that generates corresponding Java classes for Pkl classes,
|
||||||
simplifying consumption of Pkl configuration as statically typed Java objects.
|
simplifying consumption of Pkl configuration as statically typed Java objects.
|
||||||
""".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.
|
||||||
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
pklAllProjects
|
pklAllProjects
|
||||||
pklKotlinLibrary
|
pklKotlinLibrary
|
||||||
@@ -9,26 +24,25 @@ publishing {
|
|||||||
named<MavenPublication>("library") {
|
named<MavenPublication>("library") {
|
||||||
pom {
|
pom {
|
||||||
url.set("https://github.com/apple/pkl/tree/main/pkl-codegen-kotlin")
|
url.set("https://github.com/apple/pkl/tree/main/pkl-codegen-kotlin")
|
||||||
description.set("""
|
description.set(
|
||||||
|
"""
|
||||||
Kotlin source code generator that generates corresponding Kotlin classes for Pkl classes,
|
Kotlin source code generator that generates corresponding Kotlin classes for Pkl classes,
|
||||||
simplifying consumption of Pkl configuration as statically typed Kotlin objects.
|
simplifying consumption of Pkl configuration as statically typed Kotlin objects.
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.jar {
|
tasks.jar { manifest { attributes += mapOf("Main-Class" to "org.pkl.codegen.kotlin.Main") } }
|
||||||
manifest {
|
|
||||||
attributes += mapOf("Main-Class" to "org.pkl.codegen.kotlin.Main")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(projects.pklCommons)
|
implementation(projects.pklCommons)
|
||||||
api(projects.pklCommonsCli)
|
api(projects.pklCommonsCli)
|
||||||
api(projects.pklCore)
|
api(projects.pklCore)
|
||||||
|
|
||||||
implementation(libs.kotlinPoet)
|
implementation(libs.kotlinPoet)
|
||||||
implementation(libs.kotlinReflect)
|
implementation(libs.kotlinReflect)
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
pklAllProjects
|
pklAllProjects
|
||||||
pklKotlinLibrary
|
pklKotlinLibrary
|
||||||
|
|||||||
@@ -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.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
@@ -19,8 +34,8 @@ dependencies {
|
|||||||
/**
|
/**
|
||||||
* Creates test packages from the `src/test/files/packages` directory.
|
* Creates test packages from the `src/test/files/packages` directory.
|
||||||
*
|
*
|
||||||
* These packages are used by PackageServer to serve assets when running
|
* These packages are used by PackageServer to serve assets when running LanguageSnippetTests and
|
||||||
* LanguageSnippetTests and PackageResolversTest.
|
* PackageResolversTest.
|
||||||
*/
|
*/
|
||||||
val createTestPackages by tasks.registering
|
val createTestPackages by tasks.registering
|
||||||
|
|
||||||
@@ -38,38 +53,38 @@ for (packageDir in file("src/main/files/packages").listFiles()!!) {
|
|||||||
val zipFileName = "${packageDir.name}.zip"
|
val zipFileName = "${packageDir.name}.zip"
|
||||||
val archiveFile = destinationDir.map { it.file(zipFileName) }
|
val archiveFile = destinationDir.map { it.file(zipFileName) }
|
||||||
|
|
||||||
val zipTask = tasks.register("zip-${packageDir.name}", Zip::class) {
|
val zipTask =
|
||||||
destinationDirectory.set(destinationDir)
|
tasks.register("zip-${packageDir.name}", Zip::class) {
|
||||||
archiveFileName.set(zipFileName)
|
destinationDirectory.set(destinationDir)
|
||||||
from(packageContents)
|
archiveFileName.set(zipFileName)
|
||||||
// required so that checksums are reproducible
|
from(packageContents)
|
||||||
isPreserveFileTimestamps = false
|
// required so that checksums are reproducible
|
||||||
isReproducibleFileOrder = true
|
isPreserveFileTimestamps = false
|
||||||
}
|
isReproducibleFileOrder = true
|
||||||
|
|
||||||
val copyTask = tasks.register("copy-${packageDir.name}", Copy::class) {
|
|
||||||
dependsOn(zipTask)
|
|
||||||
from(metadataJson)
|
|
||||||
into(destinationDir)
|
|
||||||
val shasumFile = destinationDir.map { it.file("${packageDir.name}.json.sha256") }
|
|
||||||
outputs.file(shasumFile)
|
|
||||||
filter { line ->
|
|
||||||
line.replaceFirst("\$computedChecksum", archiveFile.get().asFile.computeChecksum())
|
|
||||||
}
|
}
|
||||||
doLast {
|
|
||||||
val outputFile = destinationDir.get().asFile.resolve("${packageDir.name}.json")
|
val copyTask =
|
||||||
if (buildInfo.os.isWindows) {
|
tasks.register("copy-${packageDir.name}", Copy::class) {
|
||||||
val contents = outputFile.readText()
|
dependsOn(zipTask)
|
||||||
// workaround for https://github.com/gradle/gradle/issues/1151
|
from(metadataJson)
|
||||||
outputFile.writeText(contents.replace("\r\n", "\n"))
|
into(destinationDir)
|
||||||
|
val shasumFile = destinationDir.map { it.file("${packageDir.name}.json.sha256") }
|
||||||
|
outputs.file(shasumFile)
|
||||||
|
filter { line ->
|
||||||
|
line.replaceFirst("\$computedChecksum", archiveFile.get().asFile.computeChecksum())
|
||||||
|
}
|
||||||
|
doLast {
|
||||||
|
val outputFile = destinationDir.get().asFile.resolve("${packageDir.name}.json")
|
||||||
|
if (buildInfo.os.isWindows) {
|
||||||
|
val contents = outputFile.readText()
|
||||||
|
// workaround for https://github.com/gradle/gradle/issues/1151
|
||||||
|
outputFile.writeText(contents.replace("\r\n", "\n"))
|
||||||
|
}
|
||||||
|
shasumFile.get().asFile.writeText(outputFile.computeChecksum())
|
||||||
}
|
}
|
||||||
shasumFile.get().asFile.writeText(outputFile.computeChecksum())
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
createTestPackages.configure {
|
createTestPackages.configure { dependsOn(copyTask) }
|
||||||
dependsOn(copyTask)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val keystoreDir = layout.buildDirectory.dir("keystore")
|
val keystoreDir = layout.buildDirectory.dir("keystore")
|
||||||
@@ -77,47 +92,61 @@ val keystoreName = "localhost.p12"
|
|||||||
val keystoreFile = keystoreDir.map { it.file(keystoreName) }
|
val keystoreFile = keystoreDir.map { it.file(keystoreName) }
|
||||||
val certsFileName = "localhost.pem"
|
val certsFileName = "localhost.pem"
|
||||||
|
|
||||||
val generateKeys by tasks.registering(JavaExec::class) {
|
val generateKeys by
|
||||||
outputs.file(keystoreFile)
|
tasks.registering(JavaExec::class) {
|
||||||
mainClass.set("sun.security.tools.keytool.Main")
|
outputs.file(keystoreFile)
|
||||||
args = listOf(
|
mainClass.set("sun.security.tools.keytool.Main")
|
||||||
"-genkeypair",
|
args =
|
||||||
"-keyalg", "RSA",
|
listOf(
|
||||||
"-alias", "integ_tests",
|
"-genkeypair",
|
||||||
"-keystore", keystoreName,
|
"-keyalg",
|
||||||
"-storepass", "password",
|
"RSA",
|
||||||
"-dname", "CN=localhost"
|
"-alias",
|
||||||
)
|
"integ_tests",
|
||||||
workingDir(keystoreDir)
|
"-keystore",
|
||||||
doFirst {
|
keystoreName,
|
||||||
workingDir.mkdirs()
|
"-storepass",
|
||||||
keystoreFile.get().asFile.delete()
|
"password",
|
||||||
|
"-dname",
|
||||||
|
"CN=localhost"
|
||||||
|
)
|
||||||
|
workingDir(keystoreDir)
|
||||||
|
doFirst {
|
||||||
|
workingDir.mkdirs()
|
||||||
|
keystoreFile.get().asFile.delete()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val exportCerts by tasks.registering(JavaExec::class) {
|
val exportCerts by
|
||||||
val outputFile = keystoreDir.map { it.file(certsFileName) }
|
tasks.registering(JavaExec::class) {
|
||||||
dependsOn(generateKeys)
|
val outputFile = keystoreDir.map { it.file(certsFileName) }
|
||||||
inputs.file(keystoreFile)
|
dependsOn(generateKeys)
|
||||||
outputs.file(outputFile)
|
inputs.file(keystoreFile)
|
||||||
mainClass.set("sun.security.tools.keytool.Main")
|
outputs.file(outputFile)
|
||||||
args = listOf(
|
mainClass.set("sun.security.tools.keytool.Main")
|
||||||
"-exportcert",
|
args =
|
||||||
"-alias", "integ_tests",
|
listOf(
|
||||||
"-storepass", "password",
|
"-exportcert",
|
||||||
"-keystore", keystoreName,
|
"-alias",
|
||||||
"-rfc",
|
"integ_tests",
|
||||||
"-file", certsFileName
|
"-storepass",
|
||||||
)
|
"password",
|
||||||
workingDir(keystoreDir)
|
"-keystore",
|
||||||
doFirst {
|
keystoreName,
|
||||||
workingDir.mkdirs()
|
"-rfc",
|
||||||
outputFile.get().asFile.delete()
|
"-file",
|
||||||
|
certsFileName
|
||||||
|
)
|
||||||
|
workingDir(keystoreDir)
|
||||||
|
doFirst {
|
||||||
|
workingDir.mkdirs()
|
||||||
|
outputFile.get().asFile.delete()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun toHex(hash: ByteArray): String {
|
fun toHex(hash: ByteArray): String {
|
||||||
val hexDigitTable = charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f')
|
val hexDigitTable =
|
||||||
|
charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f')
|
||||||
return buildString(hash.size * 2) {
|
return buildString(hash.size * 2) {
|
||||||
for (b in hash) {
|
for (b in hash) {
|
||||||
append(hexDigitTable[b.toInt() shr 4 and 0xF])
|
append(hexDigitTable[b.toInt() shr 4 and 0xF])
|
||||||
|
|||||||
@@ -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.
|
||||||
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
pklAllProjects
|
pklAllProjects
|
||||||
pklKotlinLibrary
|
pklKotlinLibrary
|
||||||
|
|||||||
@@ -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.
|
||||||
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
pklAllProjects
|
pklAllProjects
|
||||||
pklJavaLibrary
|
pklJavaLibrary
|
||||||
@@ -9,55 +24,53 @@ plugins {
|
|||||||
val pklCodegenJava: Configuration by configurations.creating
|
val pklCodegenJava: Configuration by configurations.creating
|
||||||
val firstPartySourcesJars by configurations.existing
|
val firstPartySourcesJars by configurations.existing
|
||||||
|
|
||||||
val generateTestConfigClasses by tasks.registering(JavaExec::class) {
|
val generateTestConfigClasses by
|
||||||
val outputDir = layout.buildDirectory.dir("testConfigClasses")
|
tasks.registering(JavaExec::class) {
|
||||||
outputs.dir(outputDir)
|
val outputDir = layout.buildDirectory.dir("testConfigClasses")
|
||||||
inputs.dir("src/test/resources/codegenPkl")
|
outputs.dir(outputDir)
|
||||||
|
inputs.dir("src/test/resources/codegenPkl")
|
||||||
|
|
||||||
classpath = pklCodegenJava
|
classpath = pklCodegenJava
|
||||||
mainClass.set("org.pkl.codegen.java.Main")
|
mainClass.set("org.pkl.codegen.java.Main")
|
||||||
argumentProviders.add(CommandLineArgumentProvider {
|
argumentProviders.add(
|
||||||
listOf(
|
CommandLineArgumentProvider {
|
||||||
"--output-dir", outputDir.get().asFile.path,
|
listOf("--output-dir", outputDir.get().asFile.path, "--generate-javadoc") +
|
||||||
"--generate-javadoc"
|
fileTree("src/test/resources/codegenPkl").map { it.path }
|
||||||
) + fileTree("src/test/resources/codegenPkl").map { it.path }
|
}
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.processTestResources {
|
tasks.processTestResources { dependsOn(generateTestConfigClasses) }
|
||||||
dependsOn(generateTestConfigClasses)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.compileTestKotlin {
|
tasks.compileTestKotlin { dependsOn(generateTestConfigClasses) }
|
||||||
dependsOn(generateTestConfigClasses)
|
|
||||||
}
|
|
||||||
|
|
||||||
val bundleTests by tasks.registering(Jar::class) {
|
val bundleTests by tasks.registering(Jar::class) { from(sourceSets.test.get().output) }
|
||||||
from(sourceSets.test.get().output)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Runs unit tests using jar'd class files as a source.
|
// Runs unit tests using jar'd class files as a source.
|
||||||
// This is to test loading the ClassRegistry from within a jar, as opposed to directly from the file system.
|
// This is to test loading the ClassRegistry from within a jar, as opposed to directly from the file
|
||||||
val testFromJar by tasks.registering(Test::class) {
|
// system.
|
||||||
dependsOn(bundleTests)
|
val testFromJar by
|
||||||
|
tasks.registering(Test::class) {
|
||||||
|
dependsOn(bundleTests)
|
||||||
|
|
||||||
testClassesDirs = files(tasks.test.get().testClassesDirs)
|
testClassesDirs = files(tasks.test.get().testClassesDirs)
|
||||||
|
|
||||||
classpath =
|
classpath =
|
||||||
// compiled test classes
|
// compiled test classes
|
||||||
bundleTests.get().outputs.files +
|
bundleTests.get().outputs.files +
|
||||||
// fat Jar
|
// fat Jar
|
||||||
tasks.shadowJar.get().outputs.files +
|
tasks.shadowJar.get().outputs.files +
|
||||||
// test-only dependencies
|
// test-only dependencies
|
||||||
// (test dependencies that are also main dependencies must already be contained in fat Jar;
|
// (test dependencies that are also main dependencies must already be contained in fat Jar;
|
||||||
// to verify that, we don't want to include them here)
|
// to verify that, we don't want to include them here)
|
||||||
(configurations.testRuntimeClasspath.get() - configurations.runtimeClasspath.get())
|
(configurations.testRuntimeClasspath.get() - configurations.runtimeClasspath.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: the below snippet causes `./gradlew check` to fail specifically on `pkl-codegen-java:check`. Why?
|
// TODO: the below snippet causes `./gradlew check` to fail specifically on
|
||||||
//tasks.test {
|
// `pkl-codegen-java:check`. Why?
|
||||||
|
// tasks.test {
|
||||||
// dependsOn(testFromJar)
|
// dependsOn(testFromJar)
|
||||||
//}
|
// }
|
||||||
|
|
||||||
sourceSets.getByName("test") {
|
sourceSets.getByName("test") {
|
||||||
java.srcDir(layout.buildDirectory.dir("testConfigClasses/java"))
|
java.srcDir(layout.buildDirectory.dir("testConfigClasses/java"))
|
||||||
@@ -77,9 +90,7 @@ dependencies {
|
|||||||
pklCodegenJava(projects.pklCodegenJava)
|
pklCodegenJava(projects.pklCodegenJava)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.shadowJar {
|
tasks.shadowJar { archiveBaseName.set("pkl-config-java-all") }
|
||||||
archiveBaseName.set("pkl-config-java-all")
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
@@ -94,12 +105,12 @@ publishing {
|
|||||||
artifactId = "pkl-config-java-all"
|
artifactId = "pkl-config-java-all"
|
||||||
pom {
|
pom {
|
||||||
url.set("https://github.com/apple/pkl/tree/main/pkl-config-java")
|
url.set("https://github.com/apple/pkl/tree/main/pkl-config-java")
|
||||||
description.set("Shaded fat Jar for pkl-config-java, a Java config library based on the Pkl config language.")
|
description.set(
|
||||||
|
"Shaded fat Jar for pkl-config-java, a Java config library based on the Pkl config language."
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
signing {
|
signing { sign(publishing.publications["fatJar"]) }
|
||||||
sign(publishing.publications["fatJar"])
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,19 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* 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.config.java.mapper
|
package org.pkl.config.java.mapper
|
||||||
|
|
||||||
import org.pkl.config.java.ConfigEvaluator
|
|
||||||
import org.pkl.core.ModuleSource
|
|
||||||
import com.example.Lib
|
import com.example.Lib
|
||||||
import com.example.PolymorphicModuleTest
|
import com.example.PolymorphicModuleTest
|
||||||
import com.example.PolymorphicModuleTest.Strudel
|
import com.example.PolymorphicModuleTest.Strudel
|
||||||
import com.example.PolymorphicModuleTest.TurkishDelight
|
import com.example.PolymorphicModuleTest.TurkishDelight
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.pkl.config.java.ConfigEvaluator
|
||||||
|
import org.pkl.core.ModuleSource
|
||||||
|
|
||||||
class PolymorphicTest {
|
class PolymorphicTest {
|
||||||
@Test
|
@Test
|
||||||
fun `deserializing polymorphic objects`() {
|
fun `deserializing polymorphic objects`() {
|
||||||
val evaluator = ConfigEvaluator.preconfigured()
|
val evaluator = ConfigEvaluator.preconfigured()
|
||||||
val module = evaluator.evaluate(ModuleSource.modulePath("/codegenPkl/PolymorphicModuleTest.pkl")).`as`(PolymorphicModuleTest::class.java)
|
val module =
|
||||||
|
evaluator
|
||||||
|
.evaluate(ModuleSource.modulePath("/codegenPkl/PolymorphicModuleTest.pkl"))
|
||||||
|
.`as`(PolymorphicModuleTest::class.java)
|
||||||
assertThat(module.desserts[0]).isInstanceOf(Strudel::class.java)
|
assertThat(module.desserts[0]).isInstanceOf(Strudel::class.java)
|
||||||
assertThat(module.desserts[1]).isInstanceOf(TurkishDelight::class.java)
|
assertThat(module.desserts[1]).isInstanceOf(TurkishDelight::class.java)
|
||||||
assertThat(module.planes[0]).isInstanceOf(Lib.Jet::class.java)
|
assertThat(module.planes[0]).isInstanceOf(Lib.Jet::class.java)
|
||||||
|
|||||||
@@ -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.
|
||||||
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
pklAllProjects
|
pklAllProjects
|
||||||
pklKotlinLibrary
|
pklKotlinLibrary
|
||||||
@@ -23,61 +38,61 @@ dependencies {
|
|||||||
pklCodegenKotlin(projects.pklCodegenKotlin)
|
pklCodegenKotlin(projects.pklCodegenKotlin)
|
||||||
|
|
||||||
implementation(libs.kotlinReflect)
|
implementation(libs.kotlinReflect)
|
||||||
|
|
||||||
testImplementation(libs.geantyref)
|
testImplementation(libs.geantyref)
|
||||||
}
|
}
|
||||||
|
|
||||||
val generateTestConfigClasses by tasks.registering(JavaExec::class) {
|
val generateTestConfigClasses by
|
||||||
val outputDir = layout.buildDirectory.dir("testConfigClasses")
|
tasks.registering(JavaExec::class) {
|
||||||
outputs.dir(outputDir)
|
val outputDir = layout.buildDirectory.dir("testConfigClasses")
|
||||||
inputs.dir("src/test/resources/codegenPkl")
|
outputs.dir(outputDir)
|
||||||
|
inputs.dir("src/test/resources/codegenPkl")
|
||||||
|
|
||||||
classpath = pklCodegenKotlin
|
classpath = pklCodegenKotlin
|
||||||
mainClass.set("org.pkl.codegen.kotlin.Main")
|
mainClass.set("org.pkl.codegen.kotlin.Main")
|
||||||
argumentProviders.add(CommandLineArgumentProvider {
|
argumentProviders.add(
|
||||||
listOf("--output-dir", outputDir.get().asFile.absolutePath) +
|
CommandLineArgumentProvider {
|
||||||
fileTree("src/test/resources/codegenPkl").map { it.absolutePath }
|
listOf("--output-dir", outputDir.get().asFile.absolutePath) +
|
||||||
})
|
fileTree("src/test/resources/codegenPkl").map { it.absolutePath }
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
sourceSets.getByName("test") {
|
sourceSets.getByName("test") {
|
||||||
java.srcDir(layout.buildDirectory.dir("testConfigClasses/kotlin"))
|
java.srcDir(layout.buildDirectory.dir("testConfigClasses/kotlin"))
|
||||||
resources.srcDir(layout.buildDirectory.dir("testConfigClasses/resources"))
|
resources.srcDir(layout.buildDirectory.dir("testConfigClasses/resources"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.processTestResources {
|
tasks.processTestResources { dependsOn(generateTestConfigClasses) }
|
||||||
dependsOn(generateTestConfigClasses)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.compileTestKotlin {
|
tasks.compileTestKotlin { dependsOn(generateTestConfigClasses) }
|
||||||
dependsOn(generateTestConfigClasses)
|
|
||||||
}
|
|
||||||
|
|
||||||
// use pkl-config-java-all for testing (same as for publishing)
|
// use pkl-config-java-all for testing (same as for publishing)
|
||||||
tasks.test {
|
tasks.test { classpath = classpath - pklConfigJava + pklConfigJavaAll }
|
||||||
classpath = classpath - pklConfigJava + pklConfigJavaAll
|
|
||||||
}
|
|
||||||
|
|
||||||
// disable publishing of .module until we find a way to manipulate it like POM (or ideally both together)
|
// disable publishing of .module until we find a way to manipulate it like POM (or ideally both
|
||||||
tasks.withType<GenerateModuleMetadata> {
|
// together)
|
||||||
enabled = false
|
tasks.withType<GenerateModuleMetadata> { enabled = false }
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
named<MavenPublication>("library") {
|
named<MavenPublication>("library") {
|
||||||
pom {
|
pom {
|
||||||
url.set("https://github.com/apple/pkl/tree/main/pkl-config-kotlin")
|
url.set("https://github.com/apple/pkl/tree/main/pkl-config-kotlin")
|
||||||
description.set("Kotlin extensions for pkl-config-java, a Java config library based on the Pkl config language.")
|
description.set(
|
||||||
|
"Kotlin extensions for pkl-config-java, a Java config library based on the Pkl config language."
|
||||||
|
)
|
||||||
|
|
||||||
// change dependency pkl-config-java to pkl-config-java-all
|
// change dependency pkl-config-java to pkl-config-java-all
|
||||||
withXml {
|
withXml {
|
||||||
val projectElement = asElement()
|
val projectElement = asElement()
|
||||||
val dependenciesElement = projectElement.getElementsByTagName("dependencies").item(0) as org.w3c.dom.Element
|
val dependenciesElement =
|
||||||
|
projectElement.getElementsByTagName("dependencies").item(0) as org.w3c.dom.Element
|
||||||
val dependencyElements = dependenciesElement.getElementsByTagName("dependency")
|
val dependencyElements = dependenciesElement.getElementsByTagName("dependency")
|
||||||
for (idx in 0 until dependencyElements.length) {
|
for (idx in 0 until dependencyElements.length) {
|
||||||
val dependencyElement = dependencyElements.item(idx) as org.w3c.dom.Element
|
val dependencyElement = dependencyElements.item(idx) as org.w3c.dom.Element
|
||||||
val artifactIdElement = dependencyElement.getElementsByTagName("artifactId").item(0) as org.w3c.dom.Element
|
val artifactIdElement =
|
||||||
|
dependencyElement.getElementsByTagName("artifactId").item(0) as org.w3c.dom.Element
|
||||||
if (artifactIdElement.textContent == "pkl-config-java") {
|
if (artifactIdElement.textContent == "pkl-config-java") {
|
||||||
artifactIdElement.textContent = "pkl-config-java-all"
|
artifactIdElement.textContent = "pkl-config-java-all"
|
||||||
return@withXml
|
return@withXml
|
||||||
|
|||||||
@@ -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 org.apache.tools.ant.filters.ReplaceTokens
|
import org.apache.tools.ant.filters.ReplaceTokens
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
@@ -12,13 +27,7 @@ plugins {
|
|||||||
|
|
||||||
val generatorSourceSet = sourceSets.register("generator")
|
val generatorSourceSet = sourceSets.register("generator")
|
||||||
|
|
||||||
sourceSets {
|
sourceSets { main { java { srcDir(file("generated/antlr")) } } }
|
||||||
main {
|
|
||||||
java {
|
|
||||||
srcDir(file("generated/antlr"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
idea {
|
idea {
|
||||||
module {
|
module {
|
||||||
@@ -51,16 +60,14 @@ dependencies {
|
|||||||
implementation(libs.truffleApi)
|
implementation(libs.truffleApi)
|
||||||
implementation(libs.graalSdk)
|
implementation(libs.graalSdk)
|
||||||
|
|
||||||
implementation(libs.paguro) {
|
implementation(libs.paguro) { exclude(group = "org.jetbrains", module = "annotations") }
|
||||||
exclude(group = "org.jetbrains", module = "annotations")
|
|
||||||
}
|
|
||||||
|
|
||||||
implementation(libs.snakeYaml)
|
implementation(libs.snakeYaml)
|
||||||
|
|
||||||
implementation(libs.jansi)
|
implementation(libs.jansi)
|
||||||
|
|
||||||
testImplementation(projects.pklCommonsTest)
|
testImplementation(projects.pklCommonsTest)
|
||||||
|
|
||||||
add("generatorImplementation", libs.javaPoet)
|
add("generatorImplementation", libs.javaPoet)
|
||||||
add("generatorImplementation", libs.truffleApi)
|
add("generatorImplementation", libs.truffleApi)
|
||||||
add("generatorImplementation", libs.kotlinStdLib)
|
add("generatorImplementation", libs.kotlinStdLib)
|
||||||
@@ -73,11 +80,14 @@ publishing {
|
|||||||
named<MavenPublication>("library") {
|
named<MavenPublication>("library") {
|
||||||
pom {
|
pom {
|
||||||
url.set("https://github.com/apple/pkl/tree/main/pkl-core")
|
url.set("https://github.com/apple/pkl/tree/main/pkl-core")
|
||||||
description.set("""
|
description.set(
|
||||||
|
"""
|
||||||
Core implementation of the Pkl configuration language.
|
Core implementation of the Pkl configuration language.
|
||||||
Includes Java APIs for embedding the language into JVM applications,
|
Includes Java APIs for embedding the language into JVM applications,
|
||||||
and for building libraries and tools on top of the language.
|
and for building libraries and tools on top of the language.
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,63 +107,52 @@ tasks.generateGrammarSource {
|
|||||||
outputDirectory = file("generated/antlr/org/pkl/core/parser/antlr")
|
outputDirectory = file("generated/antlr/org/pkl/core/parser/antlr")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.compileJava {
|
tasks.compileJava { dependsOn(tasks.generateGrammarSource) }
|
||||||
dependsOn(tasks.generateGrammarSource)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.sourcesJar {
|
tasks.sourcesJar { dependsOn(tasks.generateGrammarSource) }
|
||||||
dependsOn(tasks.generateGrammarSource)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.generateTestGrammarSource {
|
tasks.generateTestGrammarSource { enabled = false }
|
||||||
enabled = false
|
|
||||||
}
|
tasks.named("generateGeneratorGrammarSource") { enabled = false }
|
||||||
tasks.named("generateGeneratorGrammarSource") {
|
|
||||||
enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Satisfy expectations of IntelliJ ANTLR plugin,
|
// Satisfy expectations of IntelliJ ANTLR plugin,
|
||||||
// which can't otherwise cope with our ANTLR setup.
|
// which can't otherwise cope with our ANTLR setup.
|
||||||
val makeIntelliJAntlrPluginHappy by tasks.registering(Copy::class) {
|
val makeIntelliJAntlrPluginHappy by
|
||||||
dependsOn(tasks.generateGrammarSource)
|
tasks.registering(Copy::class) {
|
||||||
into("src/main/antlr")
|
dependsOn(tasks.generateGrammarSource)
|
||||||
from("generated/antlr/org/pkl/core/parser/antlr") {
|
into("src/main/antlr")
|
||||||
include("PklLexer.tokens")
|
from("generated/antlr/org/pkl/core/parser/antlr") { include("PklLexer.tokens") }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
tasks.processResources {
|
tasks.processResources {
|
||||||
inputs.property("version", buildInfo.pklVersion)
|
inputs.property("version", buildInfo.pklVersion)
|
||||||
inputs.property("commitId", buildInfo.commitId)
|
inputs.property("commitId", buildInfo.commitId)
|
||||||
|
|
||||||
filesMatching("org/pkl/core/Release.properties") {
|
filesMatching("org/pkl/core/Release.properties") {
|
||||||
val stdlibModules = fileTree("$rootDir/stdlib") {
|
val stdlibModules =
|
||||||
include("*.pkl")
|
fileTree("$rootDir/stdlib") {
|
||||||
exclude("doc-package-info.pkl")
|
include("*.pkl")
|
||||||
}.map { "pkl:" + it.nameWithoutExtension }
|
exclude("doc-package-info.pkl")
|
||||||
.sortedBy { it.lowercase() }
|
}
|
||||||
|
.map { "pkl:" + it.nameWithoutExtension }
|
||||||
filter<ReplaceTokens>("tokens" to mapOf(
|
.sortedBy { it.lowercase() }
|
||||||
"version" to buildInfo.pklVersion,
|
|
||||||
"commitId" to buildInfo.commitId,
|
filter<ReplaceTokens>(
|
||||||
"stdlibModules" to stdlibModules.joinToString(",")
|
"tokens" to
|
||||||
))
|
mapOf(
|
||||||
|
"version" to buildInfo.pklVersion,
|
||||||
|
"commitId" to buildInfo.commitId,
|
||||||
|
"stdlibModules" to stdlibModules.joinToString(",")
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
into("org/pkl/core/stdlib") {
|
into("org/pkl/core/stdlib") { from("$rootDir/stdlib") { include("*.pkl") } }
|
||||||
from("$rootDir/stdlib") {
|
|
||||||
include("*.pkl")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.compileJava {
|
tasks.compileJava { options.generatedSourceOutputDirectory.set(file("generated/truffle")) }
|
||||||
options.generatedSourceOutputDirectory.set(file("generated/truffle"))
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.compileKotlin {
|
tasks.compileKotlin { enabled = false }
|
||||||
enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.test {
|
tasks.test {
|
||||||
configureTest()
|
configureTest()
|
||||||
@@ -166,52 +165,58 @@ tasks.test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val testJavaExecutable by tasks.registering(Test::class) {
|
val testJavaExecutable by
|
||||||
configureExecutableTest("LanguageSnippetTestsEngine")
|
tasks.registering(Test::class) {
|
||||||
classpath =
|
configureExecutableTest("LanguageSnippetTestsEngine")
|
||||||
// compiled test classes
|
classpath =
|
||||||
sourceSets.test.get().output +
|
// compiled test classes
|
||||||
// java executable
|
sourceSets.test.get().output +
|
||||||
javaExecutableConfiguration +
|
// java executable
|
||||||
// test-only dependencies
|
javaExecutableConfiguration +
|
||||||
// (test dependencies that are also main dependencies must already be contained in java executable;
|
// test-only dependencies
|
||||||
// to verify that we don't want to include them here)
|
// (test dependencies that are also main dependencies must already be contained in java
|
||||||
(configurations.testRuntimeClasspath.get() - configurations.runtimeClasspath.get())
|
// executable;
|
||||||
}
|
// to verify that we don't want to include them here)
|
||||||
|
(configurations.testRuntimeClasspath.get() - configurations.runtimeClasspath.get())
|
||||||
|
}
|
||||||
|
|
||||||
tasks.check {
|
tasks.check { dependsOn(testJavaExecutable) }
|
||||||
dependsOn(testJavaExecutable)
|
|
||||||
}
|
|
||||||
|
|
||||||
val testMacExecutableAmd64 by tasks.registering(Test::class) {
|
val testMacExecutableAmd64 by
|
||||||
dependsOn(":pkl-cli:macExecutableAmd64")
|
tasks.registering(Test::class) {
|
||||||
configureExecutableTest("MacAmd64LanguageSnippetTestsEngine")
|
dependsOn(":pkl-cli:macExecutableAmd64")
|
||||||
}
|
configureExecutableTest("MacAmd64LanguageSnippetTestsEngine")
|
||||||
|
}
|
||||||
|
|
||||||
val testMacExecutableAarch64 by tasks.registering(Test::class) {
|
val testMacExecutableAarch64 by
|
||||||
dependsOn(":pkl-cli:macExecutableAarch64")
|
tasks.registering(Test::class) {
|
||||||
configureExecutableTest("MacAarch64LanguageSnippetTestsEngine")
|
dependsOn(":pkl-cli:macExecutableAarch64")
|
||||||
}
|
configureExecutableTest("MacAarch64LanguageSnippetTestsEngine")
|
||||||
|
}
|
||||||
|
|
||||||
val testLinuxExecutableAmd64 by tasks.registering(Test::class) {
|
val testLinuxExecutableAmd64 by
|
||||||
dependsOn(":pkl-cli:linuxExecutableAmd64")
|
tasks.registering(Test::class) {
|
||||||
configureExecutableTest("LinuxAmd64LanguageSnippetTestsEngine")
|
dependsOn(":pkl-cli:linuxExecutableAmd64")
|
||||||
}
|
configureExecutableTest("LinuxAmd64LanguageSnippetTestsEngine")
|
||||||
|
}
|
||||||
|
|
||||||
val testLinuxExecutableAarch64 by tasks.registering(Test::class) {
|
val testLinuxExecutableAarch64 by
|
||||||
dependsOn(":pkl-cli:linuxExecutableAarch64")
|
tasks.registering(Test::class) {
|
||||||
configureExecutableTest("LinuxAarch64LanguageSnippetTestsEngine")
|
dependsOn(":pkl-cli:linuxExecutableAarch64")
|
||||||
}
|
configureExecutableTest("LinuxAarch64LanguageSnippetTestsEngine")
|
||||||
|
}
|
||||||
|
|
||||||
val testAlpineExecutableAmd64 by tasks.registering(Test::class) {
|
val testAlpineExecutableAmd64 by
|
||||||
dependsOn(":pkl-cli:alpineExecutableAmd64")
|
tasks.registering(Test::class) {
|
||||||
configureExecutableTest("AlpineLanguageSnippetTestsEngine")
|
dependsOn(":pkl-cli:alpineExecutableAmd64")
|
||||||
}
|
configureExecutableTest("AlpineLanguageSnippetTestsEngine")
|
||||||
|
}
|
||||||
|
|
||||||
val testWindowsExecutableAmd64 by tasks.registering(Test::class) {
|
val testWindowsExecutableAmd64 by
|
||||||
dependsOn(":pkl-cli:windowsExecutableAmd64")
|
tasks.registering(Test::class) {
|
||||||
configureExecutableTest("WindowsLanguageSnippetTestsEngine")
|
dependsOn(":pkl-cli:windowsExecutableAmd64")
|
||||||
}
|
configureExecutableTest("WindowsLanguageSnippetTestsEngine")
|
||||||
|
}
|
||||||
|
|
||||||
tasks.testNative {
|
tasks.testNative {
|
||||||
when {
|
when {
|
||||||
@@ -249,13 +254,16 @@ spotless {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Test.configureTest() {
|
private fun Test.configureTest() {
|
||||||
inputs.dir("src/test/files/LanguageSnippetTests/input")
|
inputs
|
||||||
|
.dir("src/test/files/LanguageSnippetTests/input")
|
||||||
.withPropertyName("languageSnippetTestsInput")
|
.withPropertyName("languageSnippetTestsInput")
|
||||||
.withPathSensitivity(PathSensitivity.RELATIVE)
|
.withPathSensitivity(PathSensitivity.RELATIVE)
|
||||||
inputs.dir("src/test/files/LanguageSnippetTests/input-helper")
|
inputs
|
||||||
|
.dir("src/test/files/LanguageSnippetTests/input-helper")
|
||||||
.withPropertyName("languageSnippetTestsInputHelper")
|
.withPropertyName("languageSnippetTestsInputHelper")
|
||||||
.withPathSensitivity(PathSensitivity.RELATIVE)
|
.withPathSensitivity(PathSensitivity.RELATIVE)
|
||||||
inputs.dir("src/test/files/LanguageSnippetTests/output")
|
inputs
|
||||||
|
.dir("src/test/files/LanguageSnippetTests/output")
|
||||||
.withPropertyName("languageSnippetTestsOutput")
|
.withPropertyName("languageSnippetTestsOutput")
|
||||||
.withPathSensitivity(PathSensitivity.RELATIVE)
|
.withPathSensitivity(PathSensitivity.RELATIVE)
|
||||||
}
|
}
|
||||||
@@ -264,7 +272,5 @@ private fun Test.configureExecutableTest(engineName: String) {
|
|||||||
configureTest()
|
configureTest()
|
||||||
testClassesDirs = files(tasks.test.get().testClassesDirs)
|
testClassesDirs = files(tasks.test.get().testClassesDirs)
|
||||||
classpath = tasks.test.get().classpath
|
classpath = tasks.test.get().classpath
|
||||||
useJUnitPlatform {
|
useJUnitPlatform { includeEngines(engineName) }
|
||||||
includeEngines(engineName)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.generator
|
package org.pkl.core.generator
|
||||||
|
|
||||||
import com.oracle.truffle.api.dsl.GeneratedBy
|
import com.oracle.truffle.api.dsl.GeneratedBy
|
||||||
import com.squareup.javapoet.ClassName
|
import com.squareup.javapoet.ClassName
|
||||||
import javax.lang.model.SourceVersion
|
|
||||||
import javax.annotation.processing.RoundEnvironment
|
|
||||||
import com.squareup.javapoet.MethodSpec
|
|
||||||
import com.squareup.javapoet.JavaFile
|
import com.squareup.javapoet.JavaFile
|
||||||
|
import com.squareup.javapoet.MethodSpec
|
||||||
import com.squareup.javapoet.TypeSpec
|
import com.squareup.javapoet.TypeSpec
|
||||||
import javax.annotation.processing.AbstractProcessor
|
import javax.annotation.processing.AbstractProcessor
|
||||||
|
import javax.annotation.processing.RoundEnvironment
|
||||||
|
import javax.lang.model.SourceVersion
|
||||||
import javax.lang.model.element.*
|
import javax.lang.model.element.*
|
||||||
import javax.lang.model.type.TypeMirror
|
import javax.lang.model.type.TypeMirror
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a subclass of `org.pkl.core.stdlib.registry.ExternalMemberRegistry`
|
* Generates a subclass of `org.pkl.core.stdlib.registry.ExternalMemberRegistry` for each stdlib
|
||||||
* for each stdlib module and a factory to instantiate them.
|
* module and a factory to instantiate them. Generated classes are written to
|
||||||
* Generated classes are written to `generated/truffle/org/pkl/core/stdlib/registry`.
|
* `generated/truffle/org/pkl/core/stdlib/registry`.
|
||||||
*
|
*
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* - Generated Truffle node classes for stdlib members.
|
* - Generated Truffle node classes for stdlib members. These classes are located in subpackages of
|
||||||
* These classes are located in subpackages of `org.pkl.core.stdlib`
|
* `org.pkl.core.stdlib` and identified via their `@GeneratedBy` annotations.
|
||||||
* and identified via their `@GeneratedBy` annotations.
|
* - `@PklName` annotations on handwritten node classes from which Truffle node classes are
|
||||||
* - `@PklName` annotations on handwritten node classes from which Truffle node classes are generated.
|
* generated.
|
||||||
*/
|
*/
|
||||||
class MemberRegistryGenerator : AbstractProcessor() {
|
class MemberRegistryGenerator : AbstractProcessor() {
|
||||||
private val truffleNodeClassSuffix = "NodeGen"
|
private val truffleNodeClassSuffix = "NodeGen"
|
||||||
@@ -35,10 +50,8 @@ class MemberRegistryGenerator : AbstractProcessor() {
|
|||||||
ClassName.get(registryPackageName, "EmptyMemberRegistry")
|
ClassName.get(registryPackageName, "EmptyMemberRegistry")
|
||||||
private val memberRegistryFactoryClassName: ClassName =
|
private val memberRegistryFactoryClassName: ClassName =
|
||||||
ClassName.get(registryPackageName, "MemberRegistryFactory")
|
ClassName.get(registryPackageName, "MemberRegistryFactory")
|
||||||
private val moduleKeyClassName: ClassName =
|
private val moduleKeyClassName: ClassName = ClassName.get(modulePackageName, "ModuleKey")
|
||||||
ClassName.get(modulePackageName, "ModuleKey")
|
private val moduleKeysClassName: ClassName = ClassName.get(modulePackageName, "ModuleKeys")
|
||||||
private val moduleKeysClassName: ClassName =
|
|
||||||
ClassName.get(modulePackageName, "ModuleKeys")
|
|
||||||
|
|
||||||
override fun getSupportedAnnotationTypes(): Set<String> = setOf(GeneratedBy::class.java.name)
|
override fun getSupportedAnnotationTypes(): Set<String> = setOf(GeneratedBy::class.java.name)
|
||||||
|
|
||||||
@@ -54,19 +67,27 @@ class MemberRegistryGenerator : AbstractProcessor() {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun collectNodeClasses(roundEnv: RoundEnvironment) = roundEnv
|
private fun collectNodeClasses(roundEnv: RoundEnvironment) =
|
||||||
.getElementsAnnotatedWith(GeneratedBy::class.java)
|
roundEnv
|
||||||
.asSequence()
|
.getElementsAnnotatedWith(GeneratedBy::class.java)
|
||||||
.filterIsInstance<TypeElement>()
|
.asSequence()
|
||||||
.filter { it.qualifiedName.toString().startsWith(stdLibPackageName) }
|
.filterIsInstance<TypeElement>()
|
||||||
.filter { it.simpleName.toString().endsWith(truffleNodeClassSuffix) }
|
.filter { it.qualifiedName.toString().startsWith(stdLibPackageName) }
|
||||||
.sortedWith(compareBy(
|
.filter { it.simpleName.toString().endsWith(truffleNodeClassSuffix) }
|
||||||
{ if (it.enclosingElement.kind == ElementKind.PACKAGE) "" else it.enclosingElement.simpleName.toString() },
|
.sortedWith(
|
||||||
{ it.simpleName.toString() }
|
compareBy(
|
||||||
))
|
{
|
||||||
.groupBy { processingEnv.elementUtils.getPackageOf(it) }
|
if (it.enclosingElement.kind == ElementKind.PACKAGE) ""
|
||||||
|
else it.enclosingElement.simpleName.toString()
|
||||||
|
},
|
||||||
|
{ it.simpleName.toString() }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.groupBy { processingEnv.elementUtils.getPackageOf(it) }
|
||||||
|
|
||||||
private fun generateRegistryClasses(nodeClassesByPackage: Map<PackageElement, List<TypeElement>>) {
|
private fun generateRegistryClasses(
|
||||||
|
nodeClassesByPackage: Map<PackageElement, List<TypeElement>>
|
||||||
|
) {
|
||||||
for ((pkg, nodeClasses) in nodeClassesByPackage) {
|
for ((pkg, nodeClasses) in nodeClassesByPackage) {
|
||||||
generateRegistryClass(pkg, nodeClasses)
|
generateRegistryClass(pkg, nodeClasses)
|
||||||
}
|
}
|
||||||
@@ -75,32 +96,38 @@ class MemberRegistryGenerator : AbstractProcessor() {
|
|||||||
private fun generateRegistryClass(pkg: PackageElement, nodeClasses: List<TypeElement>) {
|
private fun generateRegistryClass(pkg: PackageElement, nodeClasses: List<TypeElement>) {
|
||||||
val pklModuleName = getAnnotatedPklName(pkg) ?: pkg.simpleName.toString()
|
val pklModuleName = getAnnotatedPklName(pkg) ?: pkg.simpleName.toString()
|
||||||
val pklModuleNameCapitalized = pklModuleName.capitalize()
|
val pklModuleNameCapitalized = pklModuleName.capitalize()
|
||||||
val registryClassName = ClassName.get(registryPackageName, "${pklModuleNameCapitalized}MemberRegistry")
|
val registryClassName =
|
||||||
|
ClassName.get(registryPackageName, "${pklModuleNameCapitalized}MemberRegistry")
|
||||||
|
|
||||||
val registryClass = TypeSpec.classBuilder(registryClassName)
|
val registryClass =
|
||||||
.addJavadoc("Generated by {@link ${this::class.qualifiedName}}.")
|
TypeSpec.classBuilder(registryClassName)
|
||||||
.addModifiers(Modifier.FINAL)
|
.addJavadoc("Generated by {@link ${this::class.qualifiedName}}.")
|
||||||
.superclass(externalMemberRegistryClassName)
|
.addModifiers(Modifier.FINAL)
|
||||||
|
.superclass(externalMemberRegistryClassName)
|
||||||
val registryClassConstructor = MethodSpec.constructorBuilder()
|
val registryClassConstructor = MethodSpec.constructorBuilder()
|
||||||
|
|
||||||
for (nodeClass in nodeClasses) {
|
for (nodeClass in nodeClasses) {
|
||||||
val enclosingClass = nodeClass.enclosingElement
|
val enclosingClass = nodeClass.enclosingElement
|
||||||
val pklClassName = getAnnotatedPklName(enclosingClass)
|
val pklClassName =
|
||||||
?: enclosingClass.simpleName.toString().removeSuffix(truffleNodeFactorySuffix)
|
getAnnotatedPklName(enclosingClass)
|
||||||
val pklMemberName = getAnnotatedPklName(nodeClass)
|
?: enclosingClass.simpleName.toString().removeSuffix(truffleNodeFactorySuffix)
|
||||||
?: nodeClass.simpleName.toString().removeSuffix(truffleNodeClassSuffix)
|
val pklMemberName =
|
||||||
val pklMemberNameQualified = when (pklClassName) {
|
getAnnotatedPklName(nodeClass)
|
||||||
// By convention, the top-level class containing node classes
|
?: nodeClass.simpleName.toString().removeSuffix(truffleNodeClassSuffix)
|
||||||
// for *module* members is named `<SimpleModuleName>Nodes`.
|
val pklMemberNameQualified =
|
||||||
// Example: `BaseNodes` for pkl.base
|
when (pklClassName) {
|
||||||
pklModuleNameCapitalized ->
|
// By convention, the top-level class containing node classes
|
||||||
"pkl.$pklModuleName#$pklMemberName"
|
// for *module* members is named `<SimpleModuleName>Nodes`.
|
||||||
else ->
|
// Example: `BaseNodes` for pkl.base
|
||||||
"pkl.$pklModuleName#$pklClassName.$pklMemberName"
|
pklModuleNameCapitalized -> "pkl.$pklModuleName#$pklMemberName"
|
||||||
}
|
else -> "pkl.$pklModuleName#$pklClassName.$pklMemberName"
|
||||||
|
}
|
||||||
registryClass.addOriginatingElement(nodeClass)
|
registryClass.addOriginatingElement(nodeClass)
|
||||||
registryClassConstructor
|
registryClassConstructor.addStatement(
|
||||||
.addStatement("register(\$S, \$T::create)", pklMemberNameQualified, nodeClass)
|
"register(\$S, \$T::create)",
|
||||||
|
pklMemberNameQualified,
|
||||||
|
nodeClass
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
registryClass.addMethod(registryClassConstructor.build())
|
registryClass.addMethod(registryClassConstructor.build())
|
||||||
@@ -109,25 +136,27 @@ class MemberRegistryGenerator : AbstractProcessor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateRegistryFactoryClass(packages: Collection<PackageElement>) {
|
private fun generateRegistryFactoryClass(packages: Collection<PackageElement>) {
|
||||||
val registryFactoryClass = TypeSpec.classBuilder(memberRegistryFactoryClassName)
|
val registryFactoryClass =
|
||||||
.addJavadoc("Generated by {@link ${this::class.qualifiedName}}.")
|
TypeSpec.classBuilder(memberRegistryFactoryClassName)
|
||||||
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
.addJavadoc("Generated by {@link ${this::class.qualifiedName}}.")
|
||||||
val registryFactoryConstructor = MethodSpec.constructorBuilder()
|
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||||
.addModifiers(Modifier.PRIVATE)
|
val registryFactoryConstructor = MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE)
|
||||||
registryFactoryClass.addMethod(registryFactoryConstructor.build())
|
registryFactoryClass.addMethod(registryFactoryConstructor.build())
|
||||||
val registryFactoryGetMethod = MethodSpec.methodBuilder("get")
|
val registryFactoryGetMethod =
|
||||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
MethodSpec.methodBuilder("get")
|
||||||
.addParameter(moduleKeyClassName, "moduleKey")
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
.returns(externalMemberRegistryClassName)
|
.addParameter(moduleKeyClassName, "moduleKey")
|
||||||
.beginControlFlow("if (!\$T.isStdLibModule(moduleKey))", moduleKeysClassName)
|
.returns(externalMemberRegistryClassName)
|
||||||
.addStatement("return \$T.INSTANCE", emptyMemberRegistryClassName)
|
.beginControlFlow("if (!\$T.isStdLibModule(moduleKey))", moduleKeysClassName)
|
||||||
.endControlFlow()
|
.addStatement("return \$T.INSTANCE", emptyMemberRegistryClassName)
|
||||||
.beginControlFlow("switch (moduleKey.getUri().getSchemeSpecificPart())")
|
.endControlFlow()
|
||||||
|
.beginControlFlow("switch (moduleKey.getUri().getSchemeSpecificPart())")
|
||||||
|
|
||||||
for (pkg in packages) {
|
for (pkg in packages) {
|
||||||
val pklModuleName = getAnnotatedPklName(pkg) ?: pkg.simpleName.toString()
|
val pklModuleName = getAnnotatedPklName(pkg) ?: pkg.simpleName.toString()
|
||||||
val pklModuleNameCapitalized = pklModuleName.capitalize()
|
val pklModuleNameCapitalized = pklModuleName.capitalize()
|
||||||
val registryClassName = ClassName.get(registryPackageName, "${pklModuleNameCapitalized}MemberRegistry")
|
val registryClassName =
|
||||||
|
ClassName.get(registryPackageName, "${pklModuleNameCapitalized}MemberRegistry")
|
||||||
|
|
||||||
// declare dependency on package-info.java (for `@PklName`)
|
// declare dependency on package-info.java (for `@PklName`)
|
||||||
registryFactoryClass.addOriginatingElement(pkg)
|
registryFactoryClass.addOriginatingElement(pkg)
|
||||||
@@ -148,8 +177,7 @@ class MemberRegistryGenerator : AbstractProcessor() {
|
|||||||
private fun getAnnotatedPklName(element: Element): String? {
|
private fun getAnnotatedPklName(element: Element): String? {
|
||||||
for (annotation in element.annotationMirrors) {
|
for (annotation in element.annotationMirrors) {
|
||||||
when (annotation.annotationType.asElement().simpleName.toString()) {
|
when (annotation.annotationType.asElement().simpleName.toString()) {
|
||||||
"PklName" ->
|
"PklName" -> return annotation.elementValues.values.iterator().next().value.toString()
|
||||||
return annotation.elementValues.values.iterator().next().value.toString()
|
|
||||||
"GeneratedBy" -> {
|
"GeneratedBy" -> {
|
||||||
val annotationValue = annotation.elementValues.values.first().value as TypeMirror
|
val annotationValue = annotation.elementValues.values.first().value as TypeMirror
|
||||||
return getAnnotatedPklName(processingEnv.typeUtils.asElement(annotationValue))
|
return getAnnotatedPklName(processingEnv.typeUtils.asElement(annotationValue))
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
@@ -8,9 +23,10 @@ class ClassInheritanceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `property override without type annotation is considered an object property definition`() {
|
fun `property override without type annotation is considered an object property definition`() {
|
||||||
val module = evaluator.evaluateSchema(
|
val module =
|
||||||
ModuleSource.text(
|
evaluator.evaluateSchema(
|
||||||
"""
|
ModuleSource.text(
|
||||||
|
"""
|
||||||
class Thing
|
class Thing
|
||||||
open class Base {
|
open class Base {
|
||||||
hidden thing: Thing
|
hidden thing: Thing
|
||||||
@@ -18,9 +34,10 @@ class ClassInheritanceTest {
|
|||||||
class Derived extends Base {
|
class Derived extends Base {
|
||||||
thing {}
|
thing {}
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
val derivedClass = module.classes["Derived"]!!
|
val derivedClass = module.classes["Derived"]!!
|
||||||
assertThat(derivedClass.properties["thing"]).isNull()
|
assertThat(derivedClass.properties["thing"]).isNull()
|
||||||
@@ -33,9 +50,10 @@ class ClassInheritanceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `property override with type annotation is considered a class property definition`() {
|
fun `property override with type annotation is considered a class property definition`() {
|
||||||
val module = evaluator.evaluateSchema(
|
val module =
|
||||||
ModuleSource.text(
|
evaluator.evaluateSchema(
|
||||||
"""
|
ModuleSource.text(
|
||||||
|
"""
|
||||||
class Thing
|
class Thing
|
||||||
open class Base {
|
open class Base {
|
||||||
hidden thing: Thing
|
hidden thing: Thing
|
||||||
@@ -43,9 +61,10 @@ class ClassInheritanceTest {
|
|||||||
class Derived extends Base {
|
class Derived extends Base {
|
||||||
thing: Thing = new {}
|
thing: Thing = new {}
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
val derivedClass = module.classes["Derived"]!!
|
val derivedClass = module.classes["Derived"]!!
|
||||||
val thingProperty = derivedClass.properties["thing"]
|
val thingProperty = derivedClass.properties["thing"]
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import kotlin.math.nextDown
|
import kotlin.math.nextDown
|
||||||
@@ -68,10 +83,9 @@ class DurationTest {
|
|||||||
assertThat(duration1.convertTo(MILLIS)).isEqualTo(duration2)
|
assertThat(duration1.convertTo(MILLIS)).isEqualTo(duration2)
|
||||||
assertThat(duration2.convertTo(SECONDS)).isEqualTo(duration1)
|
assertThat(duration2.convertTo(SECONDS)).isEqualTo(duration1)
|
||||||
|
|
||||||
assertThat(duration4.convertTo(NANOS))
|
assertThat(duration4.convertTo(NANOS)).isEqualTo(Duration(0.0, NANOS))
|
||||||
.isEqualTo(Duration(0.0, NANOS))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun toIsoString() {
|
fun toIsoString() {
|
||||||
assertThat(duration1.toIsoString()).isEqualTo("PT0.3S")
|
assertThat(duration1.toIsoString()).isEqualTo("PT0.3S")
|
||||||
@@ -79,8 +93,10 @@ class DurationTest {
|
|||||||
assertThat(duration3.toIsoString()).isEqualTo("PT0.3001S")
|
assertThat(duration3.toIsoString()).isEqualTo("PT0.3001S")
|
||||||
assertThat(duration4.toIsoString()).isEqualTo("PT0S")
|
assertThat(duration4.toIsoString()).isEqualTo("PT0S")
|
||||||
assertThat(Duration(1.0, NANOS).toIsoString()).isEqualTo("PT0.000000001S")
|
assertThat(Duration(1.0, NANOS).toIsoString()).isEqualTo("PT0.000000001S")
|
||||||
// Although ISO8601 allows for durations (P) denoted in days, months and years, it is not recommended.
|
// Although ISO8601 allows for durations (P) denoted in days, months and years, it is not
|
||||||
// The day notation can express an hour more or less, depending on whether it crosses a daylight savings transition,
|
// recommended.
|
||||||
|
// The day notation can express an hour more or less, depending on whether it crosses a daylight
|
||||||
|
// savings transition,
|
||||||
// when added to "now" (at the time of evaluation).
|
// when added to "now" (at the time of evaluation).
|
||||||
assertThat(Duration(100.0, DAYS).toIsoString()).isEqualTo("PT2400H")
|
assertThat(Duration(100.0, DAYS).toIsoString()).isEqualTo("PT2400H")
|
||||||
}
|
}
|
||||||
@@ -96,165 +112,132 @@ class DurationTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `toJavaDuration() - positive`() {
|
fun `toJavaDuration() - positive`() {
|
||||||
assertThat(Duration(999.0, NANOS).toJavaDuration()).isEqualTo(java.time.Duration.ofNanos(999))
|
assertThat(Duration(999.0, NANOS).toJavaDuration()).isEqualTo(java.time.Duration.ofNanos(999))
|
||||||
assertThat(Duration(999999.0, NANOS).toJavaDuration()).isEqualTo(java.time.Duration.ofNanos(999999))
|
assertThat(Duration(999999.0, NANOS).toJavaDuration())
|
||||||
assertThat(Duration(999999999.0, NANOS).toJavaDuration()).isEqualTo(java.time.Duration.ofNanos(999999999))
|
.isEqualTo(java.time.Duration.ofNanos(999999))
|
||||||
assertThat(Duration(999999999999.0, NANOS).toJavaDuration()).isEqualTo(java.time.Duration.ofNanos(999999999999))
|
assertThat(Duration(999999999.0, NANOS).toJavaDuration())
|
||||||
assertThat(
|
.isEqualTo(java.time.Duration.ofNanos(999999999))
|
||||||
Duration(
|
assertThat(Duration(999999999999.0, NANOS).toJavaDuration())
|
||||||
999999999999999.0,
|
.isEqualTo(java.time.Duration.ofNanos(999999999999))
|
||||||
NANOS
|
assertThat(Duration(999999999999999.0, NANOS).toJavaDuration())
|
||||||
).toJavaDuration()
|
.isEqualTo(java.time.Duration.ofNanos(999999999999999))
|
||||||
).isEqualTo(java.time.Duration.ofNanos(999999999999999))
|
assertThat(Duration(9999999999999999.0, NANOS).toJavaDuration())
|
||||||
assertThat(Duration(9999999999999999.0, NANOS).toJavaDuration()).isNotEqualTo(
|
.isNotEqualTo(java.time.Duration.ofNanos(9999999999999999))
|
||||||
java.time.Duration.ofNanos(
|
|
||||||
9999999999999999
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(Duration(999.0, SECONDS).toJavaDuration()).isEqualTo(java.time.Duration.ofSeconds(999))
|
assertThat(Duration(999.0, SECONDS).toJavaDuration())
|
||||||
assertThat(Duration(999999.0, SECONDS).toJavaDuration()).isEqualTo(java.time.Duration.ofSeconds(999999))
|
.isEqualTo(java.time.Duration.ofSeconds(999))
|
||||||
assertThat(Duration(999999999.0, SECONDS).toJavaDuration()).isEqualTo(java.time.Duration.ofSeconds(999999999))
|
assertThat(Duration(999999.0, SECONDS).toJavaDuration())
|
||||||
assertThat(Duration(999999999999.0, SECONDS).toJavaDuration()).isEqualTo(java.time.Duration.ofSeconds(999999999999))
|
.isEqualTo(java.time.Duration.ofSeconds(999999))
|
||||||
assertThat(Duration(999999999999999.0, SECONDS).toJavaDuration()).isEqualTo(
|
assertThat(Duration(999999999.0, SECONDS).toJavaDuration())
|
||||||
java.time.Duration.ofSeconds(
|
.isEqualTo(java.time.Duration.ofSeconds(999999999))
|
||||||
999999999999999
|
assertThat(Duration(999999999999.0, SECONDS).toJavaDuration())
|
||||||
)
|
.isEqualTo(java.time.Duration.ofSeconds(999999999999))
|
||||||
)
|
assertThat(Duration(999999999999999.0, SECONDS).toJavaDuration())
|
||||||
assertThat(Duration(9999999999999999.0, SECONDS).toJavaDuration()).isNotEqualTo(
|
.isEqualTo(java.time.Duration.ofSeconds(999999999999999))
|
||||||
java.time.Duration.ofSeconds(
|
assertThat(Duration(9999999999999999.0, SECONDS).toJavaDuration())
|
||||||
9999999999999999
|
.isNotEqualTo(java.time.Duration.ofSeconds(9999999999999999))
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(Duration(999.0, MINUTES).toJavaDuration()).isEqualTo(java.time.Duration.ofMinutes(999))
|
assertThat(Duration(999.0, MINUTES).toJavaDuration())
|
||||||
assertThat(Duration(999999.0, MINUTES).toJavaDuration()).isEqualTo(java.time.Duration.ofMinutes(999999))
|
.isEqualTo(java.time.Duration.ofMinutes(999))
|
||||||
assertThat(Duration(999999999.0, MINUTES).toJavaDuration()).isEqualTo(java.time.Duration.ofMinutes(999999999))
|
assertThat(Duration(999999.0, MINUTES).toJavaDuration())
|
||||||
assertThat(Duration(999999999999.0, MINUTES).toJavaDuration()).isEqualTo(java.time.Duration.ofMinutes(999999999999))
|
.isEqualTo(java.time.Duration.ofMinutes(999999))
|
||||||
assertThat(Duration(999999999999999.0, MINUTES).toJavaDuration()).isEqualTo(
|
assertThat(Duration(999999999.0, MINUTES).toJavaDuration())
|
||||||
java.time.Duration.ofMinutes(
|
.isEqualTo(java.time.Duration.ofMinutes(999999999))
|
||||||
999999999999999
|
assertThat(Duration(999999999999.0, MINUTES).toJavaDuration())
|
||||||
)
|
.isEqualTo(java.time.Duration.ofMinutes(999999999999))
|
||||||
)
|
assertThat(Duration(999999999999999.0, MINUTES).toJavaDuration())
|
||||||
assertThat(Duration(9999999999999999.0, MINUTES).toJavaDuration()).isNotEqualTo(
|
.isEqualTo(java.time.Duration.ofMinutes(999999999999999))
|
||||||
java.time.Duration.ofMinutes(
|
assertThat(Duration(9999999999999999.0, MINUTES).toJavaDuration())
|
||||||
9999999999999999
|
.isNotEqualTo(java.time.Duration.ofMinutes(9999999999999999))
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(Duration(999.0, HOURS).toJavaDuration()).isEqualTo(java.time.Duration.ofHours(999))
|
assertThat(Duration(999.0, HOURS).toJavaDuration()).isEqualTo(java.time.Duration.ofHours(999))
|
||||||
assertThat(Duration(999999.0, HOURS).toJavaDuration()).isEqualTo(java.time.Duration.ofHours(999999))
|
assertThat(Duration(999999.0, HOURS).toJavaDuration())
|
||||||
assertThat(Duration(999999999.0, HOURS).toJavaDuration()).isEqualTo(java.time.Duration.ofHours(999999999))
|
.isEqualTo(java.time.Duration.ofHours(999999))
|
||||||
assertThat(Duration(999999999999.0, HOURS).toJavaDuration()).isEqualTo(java.time.Duration.ofHours(999999999999))
|
assertThat(Duration(999999999.0, HOURS).toJavaDuration())
|
||||||
assertThat(
|
.isEqualTo(java.time.Duration.ofHours(999999999))
|
||||||
Duration(
|
assertThat(Duration(999999999999.0, HOURS).toJavaDuration())
|
||||||
999999999999999.0,
|
.isEqualTo(java.time.Duration.ofHours(999999999999))
|
||||||
HOURS
|
assertThat(Duration(999999999999999.0, HOURS).toJavaDuration())
|
||||||
).toJavaDuration()
|
.isEqualTo(java.time.Duration.ofHours(999999999999999))
|
||||||
).isEqualTo(java.time.Duration.ofHours(999999999999999))
|
|
||||||
assertThrows<ArithmeticException> { Duration(9999999999999999.0, HOURS).toJavaDuration() }
|
assertThrows<ArithmeticException> { Duration(9999999999999999.0, HOURS).toJavaDuration() }
|
||||||
|
|
||||||
assertThat(Duration(999.0, DAYS).toJavaDuration()).isEqualTo(java.time.Duration.ofDays(999))
|
assertThat(Duration(999.0, DAYS).toJavaDuration()).isEqualTo(java.time.Duration.ofDays(999))
|
||||||
assertThat(Duration(999999.0, DAYS).toJavaDuration()).isEqualTo(java.time.Duration.ofDays(999999))
|
assertThat(Duration(999999.0, DAYS).toJavaDuration())
|
||||||
assertThat(Duration(999999999.0, DAYS).toJavaDuration()).isEqualTo(java.time.Duration.ofDays(999999999))
|
.isEqualTo(java.time.Duration.ofDays(999999))
|
||||||
assertThat(Duration(999999999999.0, DAYS).toJavaDuration()).isEqualTo(java.time.Duration.ofDays(999999999999))
|
assertThat(Duration(999999999.0, DAYS).toJavaDuration())
|
||||||
|
.isEqualTo(java.time.Duration.ofDays(999999999))
|
||||||
|
assertThat(Duration(999999999999.0, DAYS).toJavaDuration())
|
||||||
|
.isEqualTo(java.time.Duration.ofDays(999999999999))
|
||||||
assertThrows<ArithmeticException> { Duration(999999999999999.0, DAYS).toJavaDuration() }
|
assertThrows<ArithmeticException> { Duration(999999999999999.0, DAYS).toJavaDuration() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `toJavaDuration() - negative`() {
|
fun `toJavaDuration() - negative`() {
|
||||||
assertThat(Duration(-999.0, NANOS).toJavaDuration()).isEqualTo(java.time.Duration.ofNanos(-999))
|
assertThat(Duration(-999.0, NANOS).toJavaDuration()).isEqualTo(java.time.Duration.ofNanos(-999))
|
||||||
assertThat(Duration(-999999.0, NANOS).toJavaDuration()).isEqualTo(java.time.Duration.ofNanos(-999999))
|
assertThat(Duration(-999999.0, NANOS).toJavaDuration())
|
||||||
assertThat(Duration(-999999999.0, NANOS).toJavaDuration()).isEqualTo(java.time.Duration.ofNanos(-999999999))
|
.isEqualTo(java.time.Duration.ofNanos(-999999))
|
||||||
assertThat(Duration(-999999999999.0, NANOS).toJavaDuration()).isEqualTo(java.time.Duration.ofNanos(-999999999999))
|
assertThat(Duration(-999999999.0, NANOS).toJavaDuration())
|
||||||
assertThat(
|
.isEqualTo(java.time.Duration.ofNanos(-999999999))
|
||||||
Duration(
|
assertThat(Duration(-999999999999.0, NANOS).toJavaDuration())
|
||||||
-999999999999999.0,
|
.isEqualTo(java.time.Duration.ofNanos(-999999999999))
|
||||||
NANOS
|
assertThat(Duration(-999999999999999.0, NANOS).toJavaDuration())
|
||||||
).toJavaDuration()
|
.isEqualTo(java.time.Duration.ofNanos(-999999999999999))
|
||||||
).isEqualTo(java.time.Duration.ofNanos(-999999999999999))
|
assertThat(Duration(-9999999999999999.0, NANOS).toJavaDuration())
|
||||||
assertThat(
|
.isNotEqualTo(java.time.Duration.ofNanos(-9999999999999999))
|
||||||
Duration(
|
|
||||||
-9999999999999999.0,
|
|
||||||
NANOS
|
|
||||||
).toJavaDuration()
|
|
||||||
).isNotEqualTo(java.time.Duration.ofNanos(-9999999999999999))
|
|
||||||
|
|
||||||
assertThat(Duration(-999.0, SECONDS).toJavaDuration()).isEqualTo(java.time.Duration.ofSeconds(-999))
|
assertThat(Duration(-999.0, SECONDS).toJavaDuration())
|
||||||
assertThat(Duration(-999999.0, SECONDS).toJavaDuration()).isEqualTo(java.time.Duration.ofSeconds(-999999))
|
.isEqualTo(java.time.Duration.ofSeconds(-999))
|
||||||
assertThat(Duration(-999999999.0, SECONDS).toJavaDuration()).isEqualTo(java.time.Duration.ofSeconds(-999999999))
|
assertThat(Duration(-999999.0, SECONDS).toJavaDuration())
|
||||||
assertThat(
|
.isEqualTo(java.time.Duration.ofSeconds(-999999))
|
||||||
Duration(
|
assertThat(Duration(-999999999.0, SECONDS).toJavaDuration())
|
||||||
-999999999999.0,
|
.isEqualTo(java.time.Duration.ofSeconds(-999999999))
|
||||||
SECONDS
|
assertThat(Duration(-999999999999.0, SECONDS).toJavaDuration())
|
||||||
).toJavaDuration()
|
.isEqualTo(java.time.Duration.ofSeconds(-999999999999))
|
||||||
).isEqualTo(java.time.Duration.ofSeconds(-999999999999))
|
assertThat(Duration(-999999999999999.0, SECONDS).toJavaDuration())
|
||||||
assertThat(
|
.isEqualTo(java.time.Duration.ofSeconds(-999999999999999))
|
||||||
Duration(
|
assertThat(Duration(-9999999999999999.0, SECONDS).toJavaDuration())
|
||||||
-999999999999999.0,
|
.isNotEqualTo(java.time.Duration.ofSeconds(-9999999999999999))
|
||||||
SECONDS
|
|
||||||
).toJavaDuration()
|
|
||||||
).isEqualTo(java.time.Duration.ofSeconds(-999999999999999))
|
|
||||||
assertThat(
|
|
||||||
Duration(
|
|
||||||
-9999999999999999.0,
|
|
||||||
SECONDS
|
|
||||||
).toJavaDuration()
|
|
||||||
).isNotEqualTo(java.time.Duration.ofSeconds(-9999999999999999))
|
|
||||||
|
|
||||||
assertThat(Duration(-999.0, MINUTES).toJavaDuration()).isEqualTo(java.time.Duration.ofMinutes(-999))
|
assertThat(Duration(-999.0, MINUTES).toJavaDuration())
|
||||||
assertThat(Duration(-999999.0, MINUTES).toJavaDuration()).isEqualTo(java.time.Duration.ofMinutes(-999999))
|
.isEqualTo(java.time.Duration.ofMinutes(-999))
|
||||||
assertThat(Duration(-999999999.0, MINUTES).toJavaDuration()).isEqualTo(java.time.Duration.ofMinutes(-999999999))
|
assertThat(Duration(-999999.0, MINUTES).toJavaDuration())
|
||||||
assertThat(
|
.isEqualTo(java.time.Duration.ofMinutes(-999999))
|
||||||
Duration(
|
assertThat(Duration(-999999999.0, MINUTES).toJavaDuration())
|
||||||
-999999999999.0,
|
.isEqualTo(java.time.Duration.ofMinutes(-999999999))
|
||||||
MINUTES
|
assertThat(Duration(-999999999999.0, MINUTES).toJavaDuration())
|
||||||
).toJavaDuration()
|
.isEqualTo(java.time.Duration.ofMinutes(-999999999999))
|
||||||
).isEqualTo(java.time.Duration.ofMinutes(-999999999999))
|
assertThat(Duration(-999999999999999.0, MINUTES).toJavaDuration())
|
||||||
assertThat(
|
.isEqualTo(java.time.Duration.ofMinutes(-999999999999999))
|
||||||
Duration(
|
assertThat(Duration(-9999999999999999.0, MINUTES).toJavaDuration())
|
||||||
-999999999999999.0,
|
.isNotEqualTo(java.time.Duration.ofMinutes(-9999999999999999))
|
||||||
MINUTES
|
|
||||||
).toJavaDuration()
|
|
||||||
).isEqualTo(java.time.Duration.ofMinutes(-999999999999999))
|
|
||||||
assertThat(
|
|
||||||
Duration(
|
|
||||||
-9999999999999999.0,
|
|
||||||
MINUTES
|
|
||||||
).toJavaDuration()
|
|
||||||
).isNotEqualTo(java.time.Duration.ofMinutes(-9999999999999999))
|
|
||||||
|
|
||||||
assertThat(Duration(-999.0, HOURS).toJavaDuration()).isEqualTo(java.time.Duration.ofHours(-999))
|
assertThat(Duration(-999.0, HOURS).toJavaDuration()).isEqualTo(java.time.Duration.ofHours(-999))
|
||||||
assertThat(Duration(-999999.0, HOURS).toJavaDuration()).isEqualTo(java.time.Duration.ofHours(-999999))
|
assertThat(Duration(-999999.0, HOURS).toJavaDuration())
|
||||||
assertThat(Duration(-999999999.0, HOURS).toJavaDuration()).isEqualTo(java.time.Duration.ofHours(-999999999))
|
.isEqualTo(java.time.Duration.ofHours(-999999))
|
||||||
assertThat(Duration(-999999999999.0, HOURS).toJavaDuration()).isEqualTo(java.time.Duration.ofHours(-999999999999))
|
assertThat(Duration(-999999999.0, HOURS).toJavaDuration())
|
||||||
assertThat(
|
.isEqualTo(java.time.Duration.ofHours(-999999999))
|
||||||
Duration(
|
assertThat(Duration(-999999999999.0, HOURS).toJavaDuration())
|
||||||
-999999999999999.0,
|
.isEqualTo(java.time.Duration.ofHours(-999999999999))
|
||||||
HOURS
|
assertThat(Duration(-999999999999999.0, HOURS).toJavaDuration())
|
||||||
).toJavaDuration()
|
.isEqualTo(java.time.Duration.ofHours(-999999999999999))
|
||||||
).isEqualTo(java.time.Duration.ofHours(-999999999999999))
|
|
||||||
assertThrows<ArithmeticException> { Duration(-9999999999999999.0, HOURS).toJavaDuration() }
|
assertThrows<ArithmeticException> { Duration(-9999999999999999.0, HOURS).toJavaDuration() }
|
||||||
|
|
||||||
assertThat(Duration(-999.0, DAYS).toJavaDuration()).isEqualTo(java.time.Duration.ofDays(-999))
|
assertThat(Duration(-999.0, DAYS).toJavaDuration()).isEqualTo(java.time.Duration.ofDays(-999))
|
||||||
assertThat(Duration(-999999.0, DAYS).toJavaDuration()).isEqualTo(java.time.Duration.ofDays(-999999))
|
assertThat(Duration(-999999.0, DAYS).toJavaDuration())
|
||||||
assertThat(Duration(-999999999.0, DAYS).toJavaDuration()).isEqualTo(java.time.Duration.ofDays(-999999999))
|
.isEqualTo(java.time.Duration.ofDays(-999999))
|
||||||
assertThat(Duration(-999999999999.0, DAYS).toJavaDuration()).isEqualTo(java.time.Duration.ofDays(-999999999999))
|
assertThat(Duration(-999999999.0, DAYS).toJavaDuration())
|
||||||
|
.isEqualTo(java.time.Duration.ofDays(-999999999))
|
||||||
|
assertThat(Duration(-999999999999.0, DAYS).toJavaDuration())
|
||||||
|
.isEqualTo(java.time.Duration.ofDays(-999999999999))
|
||||||
assertThrows<ArithmeticException> { Duration(-999999999999999.0, DAYS).toJavaDuration() }
|
assertThrows<ArithmeticException> { Duration(-999999999999999.0, DAYS).toJavaDuration() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `toJavaDuration() - edge cases`() {
|
fun `toJavaDuration() - edge cases`() {
|
||||||
assertThat(Duration(0.0, NANOS).toJavaDuration()).isEqualTo(java.time.Duration.ofNanos(0))
|
assertThat(Duration(0.0, NANOS).toJavaDuration()).isEqualTo(java.time.Duration.ofNanos(0))
|
||||||
assertThat(Duration(Long.MAX_VALUE.toDouble(), SECONDS).toJavaDuration()).isEqualTo(
|
assertThat(Duration(Long.MAX_VALUE.toDouble(), SECONDS).toJavaDuration())
|
||||||
java.time.Duration.ofSeconds(
|
.isEqualTo(java.time.Duration.ofSeconds(Long.MAX_VALUE))
|
||||||
Long.MAX_VALUE
|
assertThat(Duration(Long.MIN_VALUE.toDouble(), SECONDS).toJavaDuration())
|
||||||
)
|
.isEqualTo(java.time.Duration.ofSeconds(Long.MIN_VALUE))
|
||||||
)
|
|
||||||
assertThat(Duration(Long.MIN_VALUE.toDouble(), SECONDS).toJavaDuration()).isEqualTo(
|
|
||||||
java.time.Duration.ofSeconds(
|
|
||||||
Long.MIN_VALUE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
val justTooLarge = Duration(Long.MAX_VALUE.toDouble().nextUp(), SECONDS)
|
val justTooLarge = Duration(Long.MAX_VALUE.toDouble().nextUp(), SECONDS)
|
||||||
assertThrows<ArithmeticException> { justTooLarge.toJavaDuration() }
|
assertThrows<ArithmeticException> { justTooLarge.toJavaDuration() }
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import java.time.temporal.ChronoUnit
|
import java.time.temporal.ChronoUnit
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
@@ -5,19 +20,21 @@ import org.junit.jupiter.api.assertDoesNotThrow
|
|||||||
import org.junit.jupiter.api.assertThrows
|
import org.junit.jupiter.api.assertThrows
|
||||||
|
|
||||||
class DynamicTest {
|
class DynamicTest {
|
||||||
private fun brokenInput(value: String): String = """
|
private fun brokenInput(value: String): String =
|
||||||
|
"""
|
||||||
class Person { name: String; age: Int }
|
class Person { name: String; age: Int }
|
||||||
|
|
||||||
person: Person = new { name = 42; age = "Pigeon" } // oops
|
person: Person = new { name = 42; age = "Pigeon" } // oops
|
||||||
|
|
||||||
output { value = $value }
|
output { value = $value }
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `property access respects type`() {
|
fun `property access respects type`() {
|
||||||
// Does not involve Dynamic, but is a baseline for the other cases.
|
// Does not involve Dynamic, but is a baseline for the other cases.
|
||||||
val evaluator = Evaluator.preconfigured()
|
val evaluator = Evaluator.preconfigured()
|
||||||
assertThrows<PklException> {
|
assertThrows<PklException> {
|
||||||
evaluator.evaluateOutputText(ModuleSource.text(brokenInput("person.name")))
|
evaluator.evaluateOutputText(ModuleSource.text(brokenInput("person.name")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
@@ -18,33 +33,41 @@ class ErrorColoringTest {
|
|||||||
private fun evaluate(program: String, expression: String): Any {
|
private fun evaluate(program: String, expression: String): Any {
|
||||||
return evaluator.evaluateExpression(ModuleSource.text(program), expression)
|
return evaluator.evaluateExpression(ModuleSource.text(program), expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
fun setup() {
|
fun setup() {
|
||||||
// Enable colouring before each test
|
// Enable colouring before each test
|
||||||
Ansi.setEnabled(true)
|
Ansi.setEnabled(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
fun teardown() {
|
fun teardown() {
|
||||||
// Disable colouring after each test
|
// Disable colouring after each test
|
||||||
Ansi.setEnabled(false)
|
Ansi.setEnabled(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `simple error`() {
|
fun `simple error`() {
|
||||||
val error = assertThrows<PklException> { evaluate("bar = 2", "bar = 15") }
|
val error = assertThrows<PklException> { evaluate("bar = 2", "bar = 15") }
|
||||||
|
|
||||||
assertThat(error).message()
|
assertThat(error)
|
||||||
|
.message()
|
||||||
.contains("\u001B[31m–– Pkl Error ––\u001B[m")
|
.contains("\u001B[31m–– Pkl Error ––\u001B[m")
|
||||||
.contains("\u001B[94m1 | \u001B[m")
|
.contains("\u001B[94m1 | \u001B[m")
|
||||||
.contains("\u001B[0;31m^")
|
.contains("\u001B[0;31m^")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `repeated error`() {
|
fun `repeated error`() {
|
||||||
val error = assertThrows<PklException> { evaluate("""self: String = "Strings; if they were lazy, you could tie the knot on \(self.take(7))"""", "self") }
|
val error =
|
||||||
assertThat(error).message()
|
assertThrows<PklException> {
|
||||||
|
evaluate(
|
||||||
|
"""self: String = "Strings; if they were lazy, you could tie the knot on \(self.take(7))"""",
|
||||||
|
"self"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
assertThat(error)
|
||||||
|
.message()
|
||||||
.contains("[91mA stack overflow occurred.[m")
|
.contains("[91mA stack overflow occurred.[m")
|
||||||
.contains("[93m┌─ [0;1;35m")
|
.contains("[93m┌─ [0;1;35m")
|
||||||
.contains("[m repetitions of:")
|
.contains("[m repetitions of:")
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
@@ -22,13 +37,15 @@ class EvaluateExpressionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate expression`() {
|
fun `evaluate expression`() {
|
||||||
val program = """
|
val program =
|
||||||
|
"""
|
||||||
res1 = 1
|
res1 = 1
|
||||||
res2 {
|
res2 {
|
||||||
res3 = 3
|
res3 = 3
|
||||||
res4 = 4
|
res4 = 4
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
assertThat(evaluate(program, "res1")).isEqualTo(1L)
|
assertThat(evaluate(program, "res1")).isEqualTo(1L)
|
||||||
val res2 = evaluate(program, "res2")
|
val res2 = evaluate(program, "res2")
|
||||||
assertThat(res2).isInstanceOf(PObject::class.java)
|
assertThat(res2).isInstanceOf(PObject::class.java)
|
||||||
@@ -39,18 +56,25 @@ class EvaluateExpressionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate subpath`() {
|
fun `evaluate subpath`() {
|
||||||
val resp = evaluate("""
|
val resp =
|
||||||
|
evaluate(
|
||||||
|
"""
|
||||||
foo {
|
foo {
|
||||||
bar = 2
|
bar = 2
|
||||||
}
|
}
|
||||||
""".trimIndent(), "foo.bar")
|
"""
|
||||||
|
.trimIndent(),
|
||||||
|
"foo.bar"
|
||||||
|
)
|
||||||
|
|
||||||
assertThat(resp).isEqualTo(2L)
|
assertThat(resp).isEqualTo(2L)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate output text`() {
|
fun `evaluate output text`() {
|
||||||
val result = evaluate("""
|
val result =
|
||||||
|
evaluate(
|
||||||
|
"""
|
||||||
foo {
|
foo {
|
||||||
bar = 2
|
bar = 2
|
||||||
}
|
}
|
||||||
@@ -58,13 +82,20 @@ class EvaluateExpressionTest {
|
|||||||
output {
|
output {
|
||||||
renderer = new YamlRenderer {}
|
renderer = new YamlRenderer {}
|
||||||
}
|
}
|
||||||
""".trimIndent(), "output.text")
|
"""
|
||||||
|
.trimIndent(),
|
||||||
|
"output.text"
|
||||||
|
)
|
||||||
|
|
||||||
assertThat(result).isEqualTo("""
|
assertThat(result)
|
||||||
|
.isEqualTo(
|
||||||
|
"""
|
||||||
foo:
|
foo:
|
||||||
bar: 2
|
bar: 2
|
||||||
|
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -76,10 +107,7 @@ class EvaluateExpressionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate import expression`() {
|
fun `evaluate import expression`() {
|
||||||
val result = evaluate(
|
val result = evaluate("", """import("pkl:release").current.documentation.homepage""")
|
||||||
"",
|
|
||||||
"""import("pkl:release").current.documentation.homepage"""
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(result as String).startsWith("https://pkl-lang.org/")
|
assertThat(result as String).startsWith("https://pkl-lang.org/")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* 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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.pkl.core.ModuleSource.text
|
|
||||||
import org.assertj.core.api.Assertions.*
|
import org.assertj.core.api.Assertions.*
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.assertThrows
|
import org.junit.jupiter.api.assertThrows
|
||||||
|
import org.pkl.core.ModuleSource.text
|
||||||
|
|
||||||
class EvaluateMultipleFileOutputTest {
|
class EvaluateMultipleFileOutputTest {
|
||||||
|
|
||||||
@@ -11,7 +26,8 @@ class EvaluateMultipleFileOutputTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `output files`() {
|
fun `output files`() {
|
||||||
val program = """
|
val program =
|
||||||
|
"""
|
||||||
output {
|
output {
|
||||||
files {
|
files {
|
||||||
["foo.yml"] {
|
["foo.yml"] {
|
||||||
@@ -28,14 +44,10 @@ class EvaluateMultipleFileOutputTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
val output = evaluator.evaluateOutputFiles(text(program))
|
val output = evaluator.evaluateOutputFiles(text(program))
|
||||||
assertThat(output.keys).isEqualTo(setOf(
|
assertThat(output.keys).isEqualTo(setOf("foo.yml", "bar.yml", "bar/biz.yml", "bar/../bark.yml"))
|
||||||
"foo.yml",
|
|
||||||
"bar.yml",
|
|
||||||
"bar/biz.yml",
|
|
||||||
"bar/../bark.yml"
|
|
||||||
))
|
|
||||||
assertThat(output["foo.yml"]?.text).isEqualTo("foo: foo text")
|
assertThat(output["foo.yml"]?.text).isEqualTo("foo: foo text")
|
||||||
assertThat(output["bar.yml"]?.text).isEqualTo("bar: bar text")
|
assertThat(output["bar.yml"]?.text).isEqualTo("bar: bar text")
|
||||||
assertThat(output["bar/biz.yml"]?.text).isEqualTo("biz: bar biz")
|
assertThat(output["bar/biz.yml"]?.text).isEqualTo("biz: bar biz")
|
||||||
@@ -45,7 +57,8 @@ class EvaluateMultipleFileOutputTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `using a renderer`() {
|
fun `using a renderer`() {
|
||||||
val evaluator = Evaluator.preconfigured()
|
val evaluator = Evaluator.preconfigured()
|
||||||
val program = """
|
val program =
|
||||||
|
"""
|
||||||
output {
|
output {
|
||||||
files {
|
files {
|
||||||
["foo.json"] {
|
["foo.json"] {
|
||||||
@@ -57,21 +70,27 @@ class EvaluateMultipleFileOutputTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
val output = evaluator.evaluateOutputFiles(text(program))
|
val output = evaluator.evaluateOutputFiles(text(program))
|
||||||
assertThat(output["foo.json"]?.text).isEqualTo("""
|
assertThat(output["foo.json"]?.text)
|
||||||
|
.isEqualTo(
|
||||||
|
"""
|
||||||
{
|
{
|
||||||
"foo": "fooey",
|
"foo": "fooey",
|
||||||
"bar": "barrey"
|
"bar": "barrey"
|
||||||
}
|
}
|
||||||
|
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `reading files after the evaluator is closed`() {
|
fun `reading files after the evaluator is closed`() {
|
||||||
val evaluator = Evaluator.preconfigured()
|
val evaluator = Evaluator.preconfigured()
|
||||||
val program = """
|
val program =
|
||||||
|
"""
|
||||||
output {
|
output {
|
||||||
files {
|
files {
|
||||||
["foo.json"] {
|
["foo.json"] {
|
||||||
@@ -83,7 +102,8 @@ class EvaluateMultipleFileOutputTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
val output = evaluator.evaluateOutputFiles(text(program))
|
val output = evaluator.evaluateOutputFiles(text(program))
|
||||||
evaluator.close()
|
evaluator.close()
|
||||||
assertThrows<PklException> { output["foo.json"]!!.text }
|
assertThrows<PklException> { output["foo.json"]!!.text }
|
||||||
|
|||||||
@@ -1,8 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* 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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.pkl.core.util.IoUtils
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.pkl.core.util.IoUtils
|
||||||
|
|
||||||
// tests language-internal renderers
|
// tests language-internal renderers
|
||||||
// uses same input/output files as Pcf/Json/Yaml/PListRendererTest
|
// uses same input/output files as Pcf/Json/Yaml/PListRendererTest
|
||||||
@@ -28,13 +43,10 @@ class EvaluateOutputTextTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkRenderedOutput(format: OutputFormat) {
|
private fun checkRenderedOutput(format: OutputFormat) {
|
||||||
val evaluator = EvaluatorBuilder.preconfigured()
|
val evaluator = EvaluatorBuilder.preconfigured().setOutputFormat(format).build()
|
||||||
.setOutputFormat(format)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val output = evaluator.evaluateOutputText(
|
val output =
|
||||||
ModuleSource.modulePath("org/pkl/core/rendererTest.pkl")
|
evaluator.evaluateOutputText(ModuleSource.modulePath("org/pkl/core/rendererTest.pkl"))
|
||||||
)
|
|
||||||
val expected = IoUtils.readClassPathResourceAsString(javaClass, "rendererTest.$format")
|
val expected = IoUtils.readClassPathResourceAsString(javaClass, "rendererTest.$format")
|
||||||
|
|
||||||
assertThat(output.trim()).isEqualTo(expected.trim())
|
assertThat(output.trim()).isEqualTo(expected.trim())
|
||||||
|
|||||||
@@ -1,10 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* 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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.pkl.core.ModuleSource.*
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.AfterEach
|
import org.junit.jupiter.api.AfterEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.pkl.core.ModuleSource.*
|
||||||
import org.pkl.core.runtime.BaseModule
|
import org.pkl.core.runtime.BaseModule
|
||||||
|
|
||||||
class EvaluateSchemaTest {
|
class EvaluateSchemaTest {
|
||||||
@@ -17,9 +32,7 @@ class EvaluateSchemaTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate test schema`() {
|
fun `evaluate test schema`() {
|
||||||
val module = evaluator.evaluateSchema(
|
val module = evaluator.evaluateSchema(modulePath("org/pkl/core/EvaluateSchemaTest.pkl"))
|
||||||
modulePath("org/pkl/core/EvaluateSchemaTest.pkl")
|
|
||||||
)
|
|
||||||
|
|
||||||
checkModuleMetadata(module)
|
checkModuleMetadata(module)
|
||||||
|
|
||||||
@@ -35,28 +48,27 @@ class EvaluateSchemaTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `evaluate pkl_base schema`() {
|
fun `evaluate pkl_base schema`() {
|
||||||
val module = evaluator.evaluateSchema(uri(URI("pkl:base")))
|
val module = evaluator.evaluateSchema(uri(URI("pkl:base")))
|
||||||
assertThat(module.moduleClass.superclass)
|
assertThat(module.moduleClass.superclass).isEqualTo(BaseModule.getModuleClass().export())
|
||||||
.isEqualTo(BaseModule.getModuleClass().export())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `does not export local classes`() {
|
fun `does not export local classes`() {
|
||||||
val module = evaluator.evaluateSchema(
|
val module =
|
||||||
text(
|
evaluator.evaluateSchema(
|
||||||
"""
|
text(
|
||||||
|
"""
|
||||||
class Foo {}
|
class Foo {}
|
||||||
local class Baz {}
|
local class Baz {}
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(module.classes.keys)
|
assertThat(module.classes.keys).containsExactly("Foo")
|
||||||
.containsExactly("Foo")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkModuleMetadata(module: ModuleSchema) {
|
private fun checkModuleMetadata(module: ModuleSchema) {
|
||||||
assertThat(module.moduleUri)
|
assertThat(module.moduleUri).isEqualTo(URI("modulepath:/org/pkl/core/EvaluateSchemaTest.pkl"))
|
||||||
.isEqualTo(URI("modulepath:/org/pkl/core/EvaluateSchemaTest.pkl"))
|
|
||||||
|
|
||||||
assertThat(module.moduleName).isEqualTo("test")
|
assertThat(module.moduleName).isEqualTo("test")
|
||||||
|
|
||||||
@@ -79,9 +91,8 @@ class EvaluateSchemaTest {
|
|||||||
val paramType = propertyb2.type
|
val paramType = propertyb2.type
|
||||||
assertThat(paramType).isInstanceOf(PType.Class::class.java)
|
assertThat(paramType).isInstanceOf(PType.Class::class.java)
|
||||||
paramType as PType.Class
|
paramType as PType.Class
|
||||||
assertThat(paramType.pClass)
|
assertThat(paramType.pClass).isEqualTo(BaseModule.getIntClass().export())
|
||||||
.isEqualTo(BaseModule.getIntClass().export())
|
|
||||||
|
|
||||||
val propertyb3 = properties.getValue("propertyb3")
|
val propertyb3 = properties.getValue("propertyb3")
|
||||||
assertThat(propertyb3.sourceLocation.startLine).isEqualTo(24)
|
assertThat(propertyb3.sourceLocation.startLine).isEqualTo(24)
|
||||||
assertThat(propertyb3.sourceLocation.endLine).isEqualTo(24)
|
assertThat(propertyb3.sourceLocation.endLine).isEqualTo(24)
|
||||||
@@ -106,10 +117,8 @@ class EvaluateSchemaTest {
|
|||||||
val paramBaseType = paramType.baseType
|
val paramBaseType = paramType.baseType
|
||||||
assertThat(paramBaseType).isInstanceOf(PType.Class::class.java)
|
assertThat(paramBaseType).isInstanceOf(PType.Class::class.java)
|
||||||
paramBaseType as PType.Class
|
paramBaseType as PType.Class
|
||||||
assertThat(paramBaseType.pClass)
|
assertThat(paramBaseType.pClass).isEqualTo(BaseModule.getStringClass().export())
|
||||||
.isEqualTo(BaseModule.getStringClass().export())
|
assertThat(paramType.constraints).isEqualTo(listOf("!isEmpty", "startsWith(\"a\")"))
|
||||||
assertThat(paramType.constraints)
|
|
||||||
.isEqualTo(listOf("!isEmpty", "startsWith(\"a\")"))
|
|
||||||
|
|
||||||
val returnType = methodb2.returnType
|
val returnType = methodb2.returnType
|
||||||
assertThat(returnType).isInstanceOf(PType.Constrained::class.java)
|
assertThat(returnType).isInstanceOf(PType.Constrained::class.java)
|
||||||
@@ -119,7 +128,7 @@ class EvaluateSchemaTest {
|
|||||||
returnBaseType as PType.Class
|
returnBaseType as PType.Class
|
||||||
assertThat(returnBaseType.pClass).isEqualTo(BaseModule.getIntClass().export())
|
assertThat(returnBaseType.pClass).isEqualTo(BaseModule.getIntClass().export())
|
||||||
assertThat(returnType.constraints).isEqualTo(listOf("isPositive"))
|
assertThat(returnType.constraints).isEqualTo(listOf("isPositive"))
|
||||||
|
|
||||||
val methodb3 = methods.getValue("methodb3")
|
val methodb3 = methods.getValue("methodb3")
|
||||||
assertThat(methodb3.sourceLocation.startLine).isEqualTo(26)
|
assertThat(methodb3.sourceLocation.startLine).isEqualTo(26)
|
||||||
assertThat(methodb3.sourceLocation.endLine).isEqualTo(26)
|
assertThat(methodb3.sourceLocation.endLine).isEqualTo(26)
|
||||||
@@ -141,10 +150,8 @@ class EvaluateSchemaTest {
|
|||||||
assertThat(supermodule).isNotNull
|
assertThat(supermodule).isNotNull
|
||||||
assertThat(supermodule!!.supermodule).isNull()
|
assertThat(supermodule!!.supermodule).isNull()
|
||||||
|
|
||||||
assertThat(module.moduleClass.superclass)
|
assertThat(module.moduleClass.superclass).isEqualTo(supermodule.moduleClass)
|
||||||
.isEqualTo(supermodule.moduleClass)
|
assertThat(supermodule.moduleClass.superclass).isEqualTo(BaseModule.getModuleClass().export())
|
||||||
assertThat(supermodule.moduleClass.superclass)
|
|
||||||
.isEqualTo(BaseModule.getModuleClass().export())
|
|
||||||
|
|
||||||
assertThat(supermodule.moduleUri)
|
assertThat(supermodule.moduleUri)
|
||||||
.isEqualTo(URI("modulepath:/org/pkl/core/EvaluateSchemaTestBaseModule.pkl"))
|
.isEqualTo(URI("modulepath:/org/pkl/core/EvaluateSchemaTestBaseModule.pkl"))
|
||||||
|
|||||||
@@ -1,15 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* 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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.pkl.commons.createTempFile
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.createFile
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Assertions.assertFalse
|
import org.junit.jupiter.api.Assertions.assertFalse
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.io.TempDir
|
import org.junit.jupiter.api.io.TempDir
|
||||||
|
import org.pkl.commons.createTempFile
|
||||||
import org.pkl.commons.writeString
|
import org.pkl.commons.writeString
|
||||||
import org.pkl.core.ModuleSource.*
|
import org.pkl.core.ModuleSource.*
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
|
||||||
import kotlin.io.path.createFile
|
|
||||||
|
|
||||||
class EvaluateTestsTest {
|
class EvaluateTestsTest {
|
||||||
|
|
||||||
@@ -17,7 +32,10 @@ class EvaluateTestsTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test successful module`() {
|
fun `test successful module`() {
|
||||||
val results = evaluator.evaluateTest(text("""
|
val results =
|
||||||
|
evaluator.evaluateTest(
|
||||||
|
text(
|
||||||
|
"""
|
||||||
amends "pkl:test"
|
amends "pkl:test"
|
||||||
|
|
||||||
facts {
|
facts {
|
||||||
@@ -26,7 +44,11 @@ class EvaluateTestsTest {
|
|||||||
"foo" == "foo"
|
"foo" == "foo"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent()), true)
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
assertThat(results.moduleName).isEqualTo("text")
|
assertThat(results.moduleName).isEqualTo("text")
|
||||||
assertThat(results.displayUri).isEqualTo("repl:text")
|
assertThat(results.displayUri).isEqualTo("repl:text")
|
||||||
@@ -38,9 +60,10 @@ class EvaluateTestsTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test module failure`() {
|
fun `test module failure`() {
|
||||||
val results = evaluator.evaluateTest(
|
val results =
|
||||||
text(
|
evaluator.evaluateTest(
|
||||||
"""
|
text(
|
||||||
|
"""
|
||||||
amends "pkl:test"
|
amends "pkl:test"
|
||||||
|
|
||||||
facts {
|
facts {
|
||||||
@@ -49,19 +72,20 @@ class EvaluateTestsTest {
|
|||||||
"foo" == "bar"
|
"foo" == "bar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
"""
|
||||||
),
|
.trimIndent()
|
||||||
true
|
),
|
||||||
)
|
true
|
||||||
|
)
|
||||||
|
|
||||||
assertThat(results.totalTests()).isEqualTo(1)
|
assertThat(results.totalTests()).isEqualTo(1)
|
||||||
assertThat(results.totalFailures()).isEqualTo(2)
|
assertThat(results.totalFailures()).isEqualTo(2)
|
||||||
assertThat(results.failed()).isTrue
|
assertThat(results.failed()).isTrue
|
||||||
|
|
||||||
val res = results.results[0]
|
val res = results.results[0]
|
||||||
assertThat(res.name).isEqualTo("should fail")
|
assertThat(res.name).isEqualTo("should fail")
|
||||||
assertThat(res.errors).isEmpty()
|
assertThat(res.errors).isEmpty()
|
||||||
|
|
||||||
val fail1 = res.failures[0]
|
val fail1 = res.failures[0]
|
||||||
assertThat(fail1.rendered).isEqualTo("1 == 2 ❌ (repl:text)")
|
assertThat(fail1.rendered).isEqualTo("1 == 2 ❌ (repl:text)")
|
||||||
|
|
||||||
@@ -71,9 +95,10 @@ class EvaluateTestsTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test module error`() {
|
fun `test module error`() {
|
||||||
val results = evaluator.evaluateTest(
|
val results =
|
||||||
text(
|
evaluator.evaluateTest(
|
||||||
"""
|
text(
|
||||||
|
"""
|
||||||
amends "pkl:test"
|
amends "pkl:test"
|
||||||
|
|
||||||
facts {
|
facts {
|
||||||
@@ -82,10 +107,11 @@ class EvaluateTestsTest {
|
|||||||
throw("got an error")
|
throw("got an error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
"""
|
||||||
),
|
.trimIndent()
|
||||||
true
|
),
|
||||||
)
|
true
|
||||||
|
)
|
||||||
|
|
||||||
assertThat(results.totalTests()).isEqualTo(1)
|
assertThat(results.totalTests()).isEqualTo(1)
|
||||||
assertThat(results.totalFailures()).isEqualTo(0)
|
assertThat(results.totalFailures()).isEqualTo(0)
|
||||||
@@ -95,10 +121,12 @@ class EvaluateTestsTest {
|
|||||||
assertThat(res.name).isEqualTo("text")
|
assertThat(res.name).isEqualTo("text")
|
||||||
assertThat(res.failures).isEmpty()
|
assertThat(res.failures).isEmpty()
|
||||||
assertThat(res.errors.size).isEqualTo(1)
|
assertThat(res.errors.size).isEqualTo(1)
|
||||||
|
|
||||||
val error = res.errors[0]
|
val error = res.errors[0]
|
||||||
assertThat(error.message).isEqualTo("got an error")
|
assertThat(error.message).isEqualTo("got an error")
|
||||||
assertThat(error.exception.message).isEqualTo("""
|
assertThat(error.exception.message)
|
||||||
|
.isEqualTo(
|
||||||
|
"""
|
||||||
–– Pkl Error ––
|
–– Pkl Error ––
|
||||||
got an error
|
got an error
|
||||||
|
|
||||||
@@ -110,13 +138,17 @@ class EvaluateTestsTest {
|
|||||||
^^^^^^^
|
^^^^^^^
|
||||||
at text#facts (repl:text)
|
at text#facts (repl:text)
|
||||||
|
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test successful example`(@TempDir tempDir: Path) {
|
fun `test successful example`(@TempDir tempDir: Path) {
|
||||||
val file = tempDir.createTempFile(prefix = "example", suffix = ".pkl")
|
val file = tempDir.createTempFile(prefix = "example", suffix = ".pkl")
|
||||||
Files.writeString(file, """
|
Files.writeString(
|
||||||
|
file,
|
||||||
|
"""
|
||||||
amends "pkl:test"
|
amends "pkl:test"
|
||||||
|
|
||||||
examples {
|
examples {
|
||||||
@@ -127,9 +159,13 @@ class EvaluateTestsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
Files.writeString(createExpected(file), """
|
)
|
||||||
|
|
||||||
|
Files.writeString(
|
||||||
|
createExpected(file),
|
||||||
|
"""
|
||||||
examples {
|
examples {
|
||||||
["user"] {
|
["user"] {
|
||||||
new {
|
new {
|
||||||
@@ -138,7 +174,9 @@ class EvaluateTestsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
val results = evaluator.evaluateTest(path(file), false)
|
val results = evaluator.evaluateTest(path(file), false)
|
||||||
assertThat(results.moduleName).startsWith("example")
|
assertThat(results.moduleName).startsWith("example")
|
||||||
@@ -151,7 +189,9 @@ class EvaluateTestsTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `test example failure`(@TempDir tempDir: Path) {
|
fun `test example failure`(@TempDir tempDir: Path) {
|
||||||
val file = tempDir.createTempFile(prefix = "example", suffix = ".pkl")
|
val file = tempDir.createTempFile(prefix = "example", suffix = ".pkl")
|
||||||
Files.writeString(file, """
|
Files.writeString(
|
||||||
|
file,
|
||||||
|
"""
|
||||||
amends "pkl:test"
|
amends "pkl:test"
|
||||||
|
|
||||||
examples {
|
examples {
|
||||||
@@ -162,9 +202,13 @@ class EvaluateTestsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
Files.writeString(createExpected(file), """
|
Files.writeString(
|
||||||
|
createExpected(file),
|
||||||
|
"""
|
||||||
examples {
|
examples {
|
||||||
["user"] {
|
["user"] {
|
||||||
new {
|
new {
|
||||||
@@ -173,7 +217,9 @@ class EvaluateTestsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
val results = evaluator.evaluateTest(path(file), false)
|
val results = evaluator.evaluateTest(path(file), false)
|
||||||
assertThat(results.moduleName).startsWith("example")
|
assertThat(results.moduleName).startsWith("example")
|
||||||
@@ -187,7 +233,9 @@ class EvaluateTestsTest {
|
|||||||
assertThat(res.errors.isEmpty()).isTrue
|
assertThat(res.errors.isEmpty()).isTrue
|
||||||
|
|
||||||
val fail1 = res.failures[0]
|
val fail1 = res.failures[0]
|
||||||
assertThat(fail1.rendered.stripFileAndLines(tempDir)).isEqualTo("""
|
assertThat(fail1.rendered.stripFileAndLines(tempDir))
|
||||||
|
.isEqualTo(
|
||||||
|
"""
|
||||||
(/tempDir/example.pkl)
|
(/tempDir/example.pkl)
|
||||||
Expected: (/tempDir/example.pkl-expected.pcf)
|
Expected: (/tempDir/example.pkl-expected.pcf)
|
||||||
new {
|
new {
|
||||||
@@ -199,13 +247,17 @@ class EvaluateTestsTest {
|
|||||||
name = "Bob"
|
name = "Bob"
|
||||||
age = 33
|
age = 33
|
||||||
}
|
}
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `written examples use custom string delimiters`(@TempDir tempDir: Path) {
|
fun `written examples use custom string delimiters`(@TempDir tempDir: Path) {
|
||||||
val file = tempDir.createTempFile(prefix = "example", suffix = ".pkl")
|
val file = tempDir.createTempFile(prefix = "example", suffix = ".pkl")
|
||||||
Files.writeString(file, """
|
Files.writeString(
|
||||||
|
file,
|
||||||
|
"""
|
||||||
amends "pkl:test"
|
amends "pkl:test"
|
||||||
|
|
||||||
examples {
|
examples {
|
||||||
@@ -213,25 +265,33 @@ class EvaluateTestsTest {
|
|||||||
"my \"string\""
|
"my \"string\""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
evaluator.evaluateTest(path(file), false)
|
evaluator.evaluateTest(path(file), false)
|
||||||
val expectedFile = file.parent.resolve(file.fileName.toString() + "-expected.pcf")
|
val expectedFile = file.parent.resolve(file.fileName.toString() + "-expected.pcf")
|
||||||
assertThat(expectedFile).exists()
|
assertThat(expectedFile).exists()
|
||||||
assertThat(expectedFile).hasContent("""
|
assertThat(expectedFile)
|
||||||
|
.hasContent(
|
||||||
|
"""
|
||||||
examples {
|
examples {
|
||||||
["myStr"] {
|
["myStr"] {
|
||||||
#"my "string""#
|
#"my "string""#
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// test for backwards compatibility
|
// test for backwards compatibility
|
||||||
@Test
|
@Test
|
||||||
fun `examples that don't use custom string delimiters still pass`(@TempDir tempDir: Path) {
|
fun `examples that don't use custom string delimiters still pass`(@TempDir tempDir: Path) {
|
||||||
val file = tempDir.createTempFile(prefix = "example", suffix = ".pkl")
|
val file = tempDir.createTempFile(prefix = "example", suffix = ".pkl")
|
||||||
Files.writeString(file, """
|
Files.writeString(
|
||||||
|
file,
|
||||||
|
"""
|
||||||
amends "pkl:test"
|
amends "pkl:test"
|
||||||
|
|
||||||
examples {
|
examples {
|
||||||
@@ -239,25 +299,28 @@ class EvaluateTestsTest {
|
|||||||
"my \"string\""
|
"my \"string\""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent())
|
"""
|
||||||
createExpected(file).writeString("""
|
.trimIndent()
|
||||||
|
)
|
||||||
|
createExpected(file)
|
||||||
|
.writeString(
|
||||||
|
"""
|
||||||
examples {
|
examples {
|
||||||
["myStr"] {
|
["myStr"] {
|
||||||
"my \"string\""
|
"my \"string\""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
val result = evaluator.evaluateTest(path(file), false)
|
val result = evaluator.evaluateTest(path(file), false)
|
||||||
assertFalse(result.failed())
|
assertFalse(result.failed())
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private fun createExpected(path: Path): Path {
|
private fun createExpected(path: Path): Path {
|
||||||
return path
|
return path.parent.resolve(path.fileName.toString() + "-expected.pcf").createFile()
|
||||||
.parent
|
|
||||||
.resolve(path.fileName.toString() + "-expected.pcf")
|
|
||||||
.createFile()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.stripFileAndLines(tmpDir: Path) =
|
private fun String.stripFileAndLines(tmpDir: Path) =
|
||||||
|
|||||||
@@ -1,11 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* 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.core
|
package org.pkl.core
|
||||||
|
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.time.Duration
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.assertThrows
|
import org.junit.jupiter.api.assertThrows
|
||||||
import org.pkl.core.project.Project
|
import org.pkl.core.project.Project
|
||||||
import java.nio.file.Path
|
|
||||||
import java.time.Duration
|
|
||||||
|
|
||||||
class EvaluatorBuilderTest {
|
class EvaluatorBuilderTest {
|
||||||
@Test
|
@Test
|
||||||
@@ -34,40 +49,32 @@ class EvaluatorBuilderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `enforces that security manager is set`() {
|
fun `enforces that security manager is set`() {
|
||||||
val e1 = assertThrows<IllegalStateException> {
|
val e1 =
|
||||||
EvaluatorBuilder.unconfigured()
|
assertThrows<IllegalStateException> {
|
||||||
.setStackFrameTransformer(StackFrameTransformers.empty)
|
EvaluatorBuilder.unconfigured()
|
||||||
.build()
|
.setStackFrameTransformer(StackFrameTransformers.empty)
|
||||||
}
|
.build()
|
||||||
|
}
|
||||||
assertThat(e1).hasMessage("No security manager set.")
|
assertThat(e1).hasMessage("No security manager set.")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `enforces that stack frame transformer is set`() {
|
fun `enforces that stack frame transformer is set`() {
|
||||||
val e1 = assertThrows<IllegalStateException> {
|
val e1 =
|
||||||
EvaluatorBuilder.unconfigured()
|
assertThrows<IllegalStateException> {
|
||||||
.setSecurityManager(SecurityManagers.defaultManager)
|
EvaluatorBuilder.unconfigured().setSecurityManager(SecurityManagers.defaultManager).build()
|
||||||
.build()
|
}
|
||||||
}
|
|
||||||
assertThat(e1).hasMessage("No stack frame transformer set.")
|
assertThat(e1).hasMessage("No stack frame transformer set.")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `sets evaluator settings from project`() {
|
fun `sets evaluator settings from project`() {
|
||||||
val projectPath = Path.of(javaClass.getResource("project/project1/PklProject")!!.toURI())
|
val projectPath = Path.of(javaClass.getResource("project/project1/PklProject")!!.toURI())
|
||||||
val project = Project.loadFromPath(
|
val project = Project.loadFromPath(projectPath, SecurityManagers.defaultManager, null)
|
||||||
projectPath,
|
|
||||||
SecurityManagers.defaultManager,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
val projectDir = Path.of(javaClass.getResource("project/project1/PklProject")!!.toURI()).parent
|
val projectDir = Path.of(javaClass.getResource("project/project1/PklProject")!!.toURI()).parent
|
||||||
val builder = EvaluatorBuilder
|
val builder = EvaluatorBuilder.unconfigured().applyFromProject(project)
|
||||||
.unconfigured()
|
assertThat(builder.allowedResources.map { it.pattern() }).isEqualTo(listOf("foo:", "bar:"))
|
||||||
.applyFromProject(project)
|
assertThat(builder.allowedModules.map { it.pattern() }).isEqualTo(listOf("baz:", "biz:"))
|
||||||
assertThat(builder.allowedResources.map { it.pattern() })
|
|
||||||
.isEqualTo(listOf("foo:", "bar:"))
|
|
||||||
assertThat(builder.allowedModules.map { it.pattern() })
|
|
||||||
.isEqualTo(listOf("baz:", "biz:"))
|
|
||||||
assertThat(builder.externalProperties).isEqualTo(mapOf("one" to "1"))
|
assertThat(builder.externalProperties).isEqualTo(mapOf("one" to "1"))
|
||||||
assertThat(builder.environmentVariables).isEqualTo(mapOf("two" to "2"))
|
assertThat(builder.environmentVariables).isEqualTo(mapOf("two" to "2"))
|
||||||
assertThat(builder.moduleCacheDir).isEqualTo(projectDir.resolve("my-cache-dir/"))
|
assertThat(builder.moduleCacheDir).isEqualTo(projectDir.resolve("my-cache-dir/"))
|
||||||
|
|||||||
@@ -1,32 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* 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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.pkl.commons.createParentDirectories
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
import java.nio.file.FileSystems
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
import java.util.*
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
import kotlin.io.path.writeText
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.assertj.core.api.Assertions.assertThatCode
|
import org.assertj.core.api.Assertions.assertThatCode
|
||||||
|
import org.junit.jupiter.api.AfterAll
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.assertThrows
|
import org.junit.jupiter.api.assertThrows
|
||||||
import org.junit.jupiter.api.io.TempDir
|
import org.junit.jupiter.api.io.TempDir
|
||||||
|
import org.pkl.commons.createParentDirectories
|
||||||
import org.pkl.commons.createTempFile
|
import org.pkl.commons.createTempFile
|
||||||
|
import org.pkl.commons.test.PackageServer
|
||||||
import org.pkl.commons.toPath
|
import org.pkl.commons.toPath
|
||||||
import org.pkl.commons.writeString
|
import org.pkl.commons.writeString
|
||||||
import org.pkl.core.ModuleSource.*
|
import org.pkl.core.ModuleSource.*
|
||||||
import org.pkl.core.util.IoUtils
|
|
||||||
import org.junit.jupiter.api.AfterAll
|
|
||||||
import org.pkl.commons.test.PackageServer
|
|
||||||
import org.pkl.core.module.ModuleKey
|
import org.pkl.core.module.ModuleKey
|
||||||
import org.pkl.core.module.ModuleKeyFactories
|
import org.pkl.core.module.ModuleKeyFactories
|
||||||
import org.pkl.core.module.ModuleKeyFactory
|
import org.pkl.core.module.ModuleKeyFactory
|
||||||
import org.pkl.core.module.ResolvedModuleKey
|
import org.pkl.core.module.ResolvedModuleKey
|
||||||
import org.pkl.core.project.Project
|
import org.pkl.core.project.Project
|
||||||
import java.nio.charset.StandardCharsets
|
import org.pkl.core.util.IoUtils
|
||||||
import java.nio.file.FileSystems
|
|
||||||
import java.util.*
|
|
||||||
import java.util.regex.Pattern
|
|
||||||
import kotlin.io.path.writeText
|
|
||||||
|
|
||||||
class EvaluatorTest {
|
class EvaluatorTest {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -50,8 +65,10 @@ class EvaluatorTest {
|
|||||||
|
|
||||||
override fun getUri(): URI = uri
|
override fun getUri(): URI = uri
|
||||||
|
|
||||||
override fun loadSource(): String = javaClass.classLoader.getResourceAsStream(uri.path.drop(1))!!.use { it.readAllBytes().toString(
|
override fun loadSource(): String =
|
||||||
StandardCharsets.UTF_8) }
|
javaClass.classLoader.getResourceAsStream(uri.path.drop(1))!!.use {
|
||||||
|
it.readAllBytes().toString(StandardCharsets.UTF_8)
|
||||||
|
}
|
||||||
|
|
||||||
override fun resolve(securityManager: SecurityManager): ResolvedModuleKey = this
|
override fun resolve(securityManager: SecurityManager): ResolvedModuleKey = this
|
||||||
}
|
}
|
||||||
@@ -71,28 +88,20 @@ class EvaluatorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate text with relative import`() {
|
fun `evaluate text with relative import`() {
|
||||||
val e = assertThrows<PklException> {
|
val e = assertThrows<PklException> { evaluator.evaluate(text("import \"foo.bar\"")) }
|
||||||
evaluator.evaluate(text("import \"foo.bar\""))
|
assertThat(e).hasMessageContaining("Module `repl:text` cannot have a relative import URI.")
|
||||||
}
|
|
||||||
assertThat(e)
|
|
||||||
.hasMessageContaining("Module `repl:text` cannot have a relative import URI.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate named module`() {
|
fun `evaluate named module`() {
|
||||||
val module = evaluator.evaluate(
|
val module = evaluator.evaluate(modulePath("org/pkl/core/EvaluatorTest.pkl"))
|
||||||
modulePath("org/pkl/core/EvaluatorTest.pkl")
|
|
||||||
)
|
|
||||||
checkModule(module)
|
checkModule(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate non-existing named module`() {
|
fun `evaluate non-existing named module`() {
|
||||||
val e = assertThrows<PklException> {
|
val e = assertThrows<PklException> { evaluator.evaluate(modulePath("non/existing.pkl")) }
|
||||||
evaluator.evaluate(modulePath("non/existing.pkl"))
|
assertThat(e).hasMessageContaining("Cannot find module `modulepath:/non/existing.pkl`.")
|
||||||
}
|
|
||||||
assertThat(e)
|
|
||||||
.hasMessageContaining("Cannot find module `modulepath:/non/existing.pkl`.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -107,11 +116,8 @@ class EvaluatorTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `evaluate non-existing file`() {
|
fun `evaluate non-existing file`() {
|
||||||
val file = File("/non/existing")
|
val file = File("/non/existing")
|
||||||
val e = assertThrows<PklException> {
|
val e = assertThrows<PklException> { evaluator.evaluate(file(file)) }
|
||||||
evaluator.evaluate(file(file))
|
assertThat(e).hasMessageContaining("Cannot find module `${file.toPath().toUri()}`.")
|
||||||
}
|
|
||||||
assertThat(e)
|
|
||||||
.hasMessageContaining("Cannot find module `${file.toPath().toUri()}`.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -126,11 +132,8 @@ class EvaluatorTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `evaluate non-existing path`() {
|
fun `evaluate non-existing path`() {
|
||||||
val path = "/non/existing".toPath()
|
val path = "/non/existing".toPath()
|
||||||
val e = assertThrows<PklException> {
|
val e = assertThrows<PklException> { evaluator.evaluate(path(path)) }
|
||||||
evaluator.evaluate(path(path))
|
assertThat(e).hasMessageContaining("Cannot find module `${path.toUri()}`.")
|
||||||
}
|
|
||||||
assertThat(e)
|
|
||||||
.hasMessageContaining("Cannot find module `${path.toUri()}`.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -150,9 +153,7 @@ class EvaluatorTest {
|
|||||||
// cast required to compile on JDK 14+ (which adds new overload)
|
// cast required to compile on JDK 14+ (which adds new overload)
|
||||||
FileSystems.newFileSystem(zipFile, null as ClassLoader?).use { zipFs ->
|
FileSystems.newFileSystem(zipFile, null as ClassLoader?).use { zipFs ->
|
||||||
val file = zipFs.getPath("non/existing")
|
val file = zipFs.getPath("non/existing")
|
||||||
val e = assertThrows<PklException> {
|
val e = assertThrows<PklException> { evaluator.evaluate(path(file)) }
|
||||||
evaluator.evaluate(path(file))
|
|
||||||
}
|
|
||||||
assertThat(e)
|
assertThat(e)
|
||||||
.hasMessageContaining("Cannot find module `jar:file:")
|
.hasMessageContaining("Cannot find module `jar:file:")
|
||||||
.hasMessageContaining("non/existing")
|
.hasMessageContaining("non/existing")
|
||||||
@@ -170,11 +171,9 @@ class EvaluatorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate non-existing URI`() {
|
fun `evaluate non-existing URI`() {
|
||||||
val e = assertThrows<PklException> {
|
val e =
|
||||||
evaluator.evaluate(uri(URI("https://localhost/non/existing")))
|
assertThrows<PklException> { evaluator.evaluate(uri(URI("https://localhost/non/existing"))) }
|
||||||
}
|
assertThat(e).hasMessageContaining("I/O error loading module `https://localhost/non/existing`.")
|
||||||
assertThat(e)
|
|
||||||
.hasMessageContaining("I/O error loading module `https://localhost/non/existing`.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -187,112 +186,117 @@ class EvaluatorTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `evaluate jar URI with non-existing archive`() {
|
fun `evaluate jar URI with non-existing archive`() {
|
||||||
val moduleUri = URI("jar:file:///non/existing!/bar.pkl")
|
val moduleUri = URI("jar:file:///non/existing!/bar.pkl")
|
||||||
val e = assertThrows<PklException> {
|
val e = assertThrows<PklException> { evaluator.evaluate(uri(moduleUri)) }
|
||||||
evaluator.evaluate(uri(moduleUri))
|
assertThat(e).hasMessageContaining("Cannot find module `$moduleUri`.")
|
||||||
}
|
|
||||||
assertThat(e)
|
|
||||||
.hasMessageContaining("Cannot find module `$moduleUri`.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate jar URI with non-existing archive path`(@TempDir tempDir: Path) {
|
fun `evaluate jar URI with non-existing archive path`(@TempDir tempDir: Path) {
|
||||||
val zipFile = createModulesZip(tempDir)
|
val zipFile = createModulesZip(tempDir)
|
||||||
val moduleUri = URI("jar:${zipFile.toUri()}!/non/existing")
|
val moduleUri = URI("jar:${zipFile.toUri()}!/non/existing")
|
||||||
val e = assertThrows<PklException> {
|
val e = assertThrows<PklException> { evaluator.evaluate(uri(moduleUri)) }
|
||||||
evaluator.evaluate(uri(moduleUri))
|
assertThat(e).hasMessageContaining("Cannot find module `$moduleUri`.")
|
||||||
}
|
|
||||||
assertThat(e)
|
|
||||||
.hasMessageContaining("Cannot find module `$moduleUri`.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate module with relative URI`() {
|
fun `evaluate module with relative URI`() {
|
||||||
val e = assertThrows<PklException> {
|
val e = assertThrows<PklException> { evaluator.evaluate(create(URI("foo.bar"), "")) }
|
||||||
evaluator.evaluate(create(URI("foo.bar"), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThat(e)
|
assertThat(e).hasMessageContaining("Cannot evaluate relative module URI `foo.bar`.")
|
||||||
.hasMessageContaining("Cannot evaluate relative module URI `foo.bar`.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluating a broken module multiple times results in the same error every time`() {
|
fun `evaluating a broken module multiple times results in the same error every time`() {
|
||||||
val e1 = assertThrows<PklException> {
|
val e1 =
|
||||||
evaluator.evaluate(modulePath("org/pkl/core/brokenModule1.pkl"))
|
assertThrows<PklException> {
|
||||||
}
|
evaluator.evaluate(modulePath("org/pkl/core/brokenModule1.pkl"))
|
||||||
val e2 = assertThrows<PklException> {
|
}
|
||||||
evaluator.evaluate(modulePath("org/pkl/core/brokenModule1.pkl"))
|
val e2 =
|
||||||
}
|
assertThrows<PklException> {
|
||||||
|
evaluator.evaluate(modulePath("org/pkl/core/brokenModule1.pkl"))
|
||||||
|
}
|
||||||
assertThat(e2.message).isEqualTo(e1.message)
|
assertThat(e2.message).isEqualTo(e1.message)
|
||||||
|
|
||||||
val e3 = assertThrows<PklException> {
|
val e3 =
|
||||||
evaluator.evaluate(modulePath("org/pkl/core/brokenModule2.pkl"))
|
assertThrows<PklException> {
|
||||||
}
|
evaluator.evaluate(modulePath("org/pkl/core/brokenModule2.pkl"))
|
||||||
val e4 = assertThrows<PklException> {
|
}
|
||||||
evaluator.evaluate(modulePath("org/pkl/core/brokenModule2.pkl"))
|
val e4 =
|
||||||
}
|
assertThrows<PklException> {
|
||||||
|
evaluator.evaluate(modulePath("org/pkl/core/brokenModule2.pkl"))
|
||||||
|
}
|
||||||
assertThat(e4.message).isEqualTo(e3.message)
|
assertThat(e4.message).isEqualTo(e3.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluation timeout`() {
|
fun `evaluation timeout`() {
|
||||||
val evaluator = EvaluatorBuilder.preconfigured()
|
val evaluator =
|
||||||
.setTimeout(java.time.Duration.ofMillis(100))
|
EvaluatorBuilder.preconfigured().setTimeout(java.time.Duration.ofMillis(100)).build()
|
||||||
.build()
|
val e =
|
||||||
val e = assertThrows<PklException> {
|
assertThrows<PklException> {
|
||||||
evaluator.evaluate(text(
|
evaluator.evaluate(
|
||||||
"""
|
text(
|
||||||
|
"""
|
||||||
function fib(n) = if (n < 2) 0 else fib(n - 1) + fib(n - 2)
|
function fib(n) = if (n < 2) 0 else fib(n - 1) + fib(n - 2)
|
||||||
x = fib(100)
|
x = fib(100)
|
||||||
""".trimIndent()
|
"""
|
||||||
))
|
.trimIndent()
|
||||||
}
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
assertThat(e.message).contains("timed out")
|
assertThat(e.message).contains("timed out")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `stack overflow`() {
|
fun `stack overflow`() {
|
||||||
val evaluator = Evaluator.preconfigured()
|
val evaluator = Evaluator.preconfigured()
|
||||||
val e = assertThrows<PklException> {
|
val e =
|
||||||
evaluator.evaluate(text("""
|
assertThrows<PklException> {
|
||||||
|
evaluator.evaluate(
|
||||||
|
text(
|
||||||
|
"""
|
||||||
a = b
|
a = b
|
||||||
b = c
|
b = c
|
||||||
c = a
|
c = a
|
||||||
""".trimIndent()))
|
"""
|
||||||
}
|
.trimIndent()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
assertThat(e.message).contains("A stack overflow occurred.")
|
assertThat(e.message).contains("A stack overflow occurred.")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `cannot import module located outside root dir`(@TempDir tempDir: Path) {
|
fun `cannot import module located outside root dir`(@TempDir tempDir: Path) {
|
||||||
val evaluator = EvaluatorBuilder.preconfigured()
|
val evaluator =
|
||||||
.setSecurityManager(
|
EvaluatorBuilder.preconfigured()
|
||||||
SecurityManagers.standard(
|
.setSecurityManager(
|
||||||
SecurityManagers.defaultAllowedModules,
|
SecurityManagers.standard(
|
||||||
SecurityManagers.defaultAllowedResources,
|
SecurityManagers.defaultAllowedModules,
|
||||||
SecurityManagers.defaultTrustLevels,
|
SecurityManagers.defaultAllowedResources,
|
||||||
tempDir
|
SecurityManagers.defaultTrustLevels,
|
||||||
|
tempDir
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
.build()
|
||||||
.build()
|
|
||||||
|
|
||||||
val module = tempDir.resolve("test.pkl")
|
val module = tempDir.resolve("test.pkl")
|
||||||
module.writeString(
|
module.writeString(
|
||||||
"""
|
"""
|
||||||
amends "/non/existing.pkl"
|
amends "/non/existing.pkl"
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
)
|
)
|
||||||
|
|
||||||
val e = assertThrows<PklException> {
|
val e = assertThrows<PklException> { evaluator.evaluate(path(module)) }
|
||||||
evaluator.evaluate(path(module))
|
|
||||||
}
|
|
||||||
assertThat(e.message).contains("Refusing to load module `file:///non/existing.pkl`")
|
assertThat(e.message).contains("Refusing to load module `file:///non/existing.pkl`")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `multiple-file output`() {
|
fun `multiple-file output`() {
|
||||||
val evaluator = Evaluator.preconfigured()
|
val evaluator = Evaluator.preconfigured()
|
||||||
val program = """
|
val program =
|
||||||
|
"""
|
||||||
output {
|
output {
|
||||||
files {
|
files {
|
||||||
["foo.yml"] {
|
["foo.yml"] {
|
||||||
@@ -309,14 +313,10 @@ class EvaluatorTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
val output = evaluator.evaluateOutputFiles(ModuleSource.text(program))
|
val output = evaluator.evaluateOutputFiles(ModuleSource.text(program))
|
||||||
assertThat(output.keys).isEqualTo(setOf(
|
assertThat(output.keys).isEqualTo(setOf("foo.yml", "bar.yml", "bar/biz.yml", "bar/../bark.yml"))
|
||||||
"foo.yml",
|
|
||||||
"bar.yml",
|
|
||||||
"bar/biz.yml",
|
|
||||||
"bar/../bark.yml"
|
|
||||||
))
|
|
||||||
assertThat(output["foo.yml"]?.text).isEqualTo("foo: foo text")
|
assertThat(output["foo.yml"]?.text).isEqualTo("foo: foo text")
|
||||||
assertThat(output["bar.yml"]?.text).isEqualTo("bar: bar text")
|
assertThat(output["bar.yml"]?.text).isEqualTo("bar: bar text")
|
||||||
assertThat(output["bar/biz.yml"]?.text).isEqualTo("biz: bar biz")
|
assertThat(output["bar/biz.yml"]?.text).isEqualTo("biz: bar biz")
|
||||||
@@ -328,10 +328,13 @@ class EvaluatorTest {
|
|||||||
PackageServer.populateCacheDir(cacheDir)
|
PackageServer.populateCacheDir(cacheDir)
|
||||||
val evaluatorBuilder = EvaluatorBuilder.preconfigured().setModuleCacheDir(cacheDir)
|
val evaluatorBuilder = EvaluatorBuilder.preconfigured().setModuleCacheDir(cacheDir)
|
||||||
val project = Project.load(modulePath("/org/pkl/core/project/project5/PklProject"))
|
val project = Project.load(modulePath("/org/pkl/core/project/project5/PklProject"))
|
||||||
val result = evaluatorBuilder.setProjectDependencies(project.dependencies).build().use { evaluator ->
|
val result =
|
||||||
evaluator.evaluateOutputText(modulePath("/org/pkl/core/project/project5/main.pkl"))
|
evaluatorBuilder.setProjectDependencies(project.dependencies).build().use { evaluator ->
|
||||||
}
|
evaluator.evaluateOutputText(modulePath("/org/pkl/core/project/project5/main.pkl"))
|
||||||
assertThat(result).isEqualTo("""
|
}
|
||||||
|
assertThat(result)
|
||||||
|
.isEqualTo(
|
||||||
|
"""
|
||||||
prop1 {
|
prop1 {
|
||||||
name = "Apple"
|
name = "Apple"
|
||||||
}
|
}
|
||||||
@@ -339,30 +342,37 @@ class EvaluatorTest {
|
|||||||
res = 1
|
res = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `project set from custom ModuleKeyFactory`(@TempDir cacheDir: Path) {
|
fun `project set from custom ModuleKeyFactory`(@TempDir cacheDir: Path) {
|
||||||
PackageServer.populateCacheDir(cacheDir)
|
PackageServer.populateCacheDir(cacheDir)
|
||||||
val evaluatorBuilder = with(EvaluatorBuilder.preconfigured()) {
|
val evaluatorBuilder =
|
||||||
setAllowedModules(SecurityManagers.defaultAllowedModules + Pattern.compile("custom:"))
|
with(EvaluatorBuilder.preconfigured()) {
|
||||||
setAllowedResources(SecurityManagers.defaultAllowedResources + Pattern.compile("custom:"))
|
setAllowedModules(SecurityManagers.defaultAllowedModules + Pattern.compile("custom:"))
|
||||||
setModuleCacheDir(cacheDir)
|
setAllowedResources(SecurityManagers.defaultAllowedResources + Pattern.compile("custom:"))
|
||||||
setModuleKeyFactories(
|
setModuleCacheDir(cacheDir)
|
||||||
listOf(
|
setModuleKeyFactories(
|
||||||
CustomModuleKeyFactory,
|
listOf(
|
||||||
ModuleKeyFactories.standardLibrary,
|
CustomModuleKeyFactory,
|
||||||
ModuleKeyFactories.pkg,
|
ModuleKeyFactories.standardLibrary,
|
||||||
ModuleKeyFactories.projectpackage,
|
ModuleKeyFactories.pkg,
|
||||||
ModuleKeyFactories.file
|
ModuleKeyFactories.projectpackage,
|
||||||
|
ModuleKeyFactories.file
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
}
|
val project =
|
||||||
val project = evaluatorBuilder.build().use { Project.load(it, uri("custom:/org/pkl/core/project/project5/PklProject")) }
|
evaluatorBuilder.build().use {
|
||||||
|
Project.load(it, uri("custom:/org/pkl/core/project/project5/PklProject"))
|
||||||
|
}
|
||||||
|
|
||||||
val evaluator = evaluatorBuilder.setProjectDependencies(project.dependencies).build()
|
val evaluator = evaluatorBuilder.setProjectDependencies(project.dependencies).build()
|
||||||
val output = evaluator.use { it.evaluateOutputText(uri("custom:/org/pkl/core/project/project5/main.pkl")) }
|
val output =
|
||||||
|
evaluator.use { it.evaluateOutputText(uri("custom:/org/pkl/core/project/project5/main.pkl")) }
|
||||||
assertThat(output)
|
assertThat(output)
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
"""
|
"""
|
||||||
@@ -382,45 +392,55 @@ class EvaluatorTest {
|
|||||||
fun `project base path set to non-hierarchical scheme`() {
|
fun `project base path set to non-hierarchical scheme`() {
|
||||||
class FooBarModuleKey(val moduleUri: URI) : ModuleKey, ResolvedModuleKey {
|
class FooBarModuleKey(val moduleUri: URI) : ModuleKey, ResolvedModuleKey {
|
||||||
override fun hasHierarchicalUris(): Boolean = false
|
override fun hasHierarchicalUris(): Boolean = false
|
||||||
|
|
||||||
override fun isGlobbable(): Boolean = false
|
override fun isGlobbable(): Boolean = false
|
||||||
|
|
||||||
override fun getOriginal(): ModuleKey = this
|
override fun getOriginal(): ModuleKey = this
|
||||||
|
|
||||||
override fun getUri(): URI = moduleUri
|
override fun getUri(): URI = moduleUri
|
||||||
|
|
||||||
override fun loadSource(): String =
|
override fun loadSource(): String =
|
||||||
if (uri.schemeSpecificPart.endsWith("PklProject")) {
|
if (uri.schemeSpecificPart.endsWith("PklProject")) {
|
||||||
"""
|
"""
|
||||||
amends "pkl:Project"
|
amends "pkl:Project"
|
||||||
""".trimIndent()
|
"""
|
||||||
} else """
|
.trimIndent()
|
||||||
|
} else
|
||||||
|
"""
|
||||||
birds = import("@birds/catalog/Ostritch.pkl")
|
birds = import("@birds/catalog/Ostritch.pkl")
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
|
||||||
override fun resolve(securityManager: SecurityManager): ResolvedModuleKey {
|
override fun resolve(securityManager: SecurityManager): ResolvedModuleKey {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val fooBayModuleKeyFactory = ModuleKeyFactory { uri ->
|
val fooBayModuleKeyFactory = ModuleKeyFactory { uri ->
|
||||||
if (uri.scheme == "foobar") Optional.of(FooBarModuleKey(uri))
|
if (uri.scheme == "foobar") Optional.of(FooBarModuleKey(uri)) else Optional.empty()
|
||||||
else Optional.empty()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val evaluatorBuilder = with(EvaluatorBuilder.preconfigured()) {
|
val evaluatorBuilder =
|
||||||
setAllowedModules(SecurityManagers.defaultAllowedModules + Pattern.compile("foobar:"))
|
with(EvaluatorBuilder.preconfigured()) {
|
||||||
setAllowedResources(SecurityManagers.defaultAllowedResources + Pattern.compile("foobar:"))
|
setAllowedModules(SecurityManagers.defaultAllowedModules + Pattern.compile("foobar:"))
|
||||||
setModuleKeyFactories(
|
setAllowedResources(SecurityManagers.defaultAllowedResources + Pattern.compile("foobar:"))
|
||||||
listOf(
|
setModuleKeyFactories(
|
||||||
fooBayModuleKeyFactory,
|
listOf(
|
||||||
ModuleKeyFactories.standardLibrary,
|
fooBayModuleKeyFactory,
|
||||||
ModuleKeyFactories.pkg,
|
ModuleKeyFactories.standardLibrary,
|
||||||
ModuleKeyFactories.projectpackage,
|
ModuleKeyFactories.pkg,
|
||||||
ModuleKeyFactories.file
|
ModuleKeyFactories.projectpackage,
|
||||||
|
ModuleKeyFactories.file
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val project = evaluatorBuilder.build().use { Project.load(it, uri("foobar:foo/PklProject")) }
|
val project = evaluatorBuilder.build().use { Project.load(it, uri("foobar:foo/PklProject")) }
|
||||||
val evaluator = evaluatorBuilder.setProjectDependencies(project.dependencies).build()
|
val evaluator = evaluatorBuilder.setProjectDependencies(project.dependencies).build()
|
||||||
assertThatCode { evaluator.use { it.evaluateOutputText(uri("foobar:baz")) } }
|
assertThatCode { evaluator.use { it.evaluateOutputText(uri("foobar:baz")) } }
|
||||||
.hasMessageContaining("Cannot import dependency because project URI `foobar:foo/PklProject` does not have a hierarchical path.")
|
.hasMessageContaining(
|
||||||
|
"Cannot import dependency because project URI `foobar:foo/PklProject` does not have a hierarchical path."
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -430,22 +450,34 @@ class EvaluatorTest {
|
|||||||
val project = Project.load(modulePath("/org/pkl/core/project/project6/PklProject"))
|
val project = Project.load(modulePath("/org/pkl/core/project/project6/PklProject"))
|
||||||
evaluatorBuilder.setProjectDependencies(project.dependencies).build().use { evaluator ->
|
evaluatorBuilder.setProjectDependencies(project.dependencies).build().use { evaluator ->
|
||||||
assertThatCode {
|
assertThatCode {
|
||||||
evaluator.evaluateOutputText(modulePath("/org/pkl/core/project/project6/globWithinDependency.pkl"))
|
evaluator.evaluateOutputText(
|
||||||
}.hasMessageContaining("""
|
modulePath("/org/pkl/core/project/project6/globWithinDependency.pkl")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.hasMessageContaining(
|
||||||
|
"""
|
||||||
Cannot resolve import in local dependency because scheme `modulepath` is not globbable.
|
Cannot resolve import in local dependency because scheme `modulepath` is not globbable.
|
||||||
|
|
||||||
1 | res = import*("*.pkl")
|
1 | res = import*("*.pkl")
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
assertThatCode {
|
assertThatCode {
|
||||||
evaluator.evaluateOutputText(modulePath("/org/pkl/core/project/project6/globIntoDependency.pkl"))
|
evaluator.evaluateOutputText(
|
||||||
}.hasMessageContaining("""
|
modulePath("/org/pkl/core/project/project6/globIntoDependency.pkl")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.hasMessageContaining(
|
||||||
|
"""
|
||||||
–– Pkl Error ––
|
–– Pkl Error ––
|
||||||
Cannot resolve import in local dependency because scheme `modulepath` is not globbable.
|
Cannot resolve import in local dependency because scheme `modulepath` is not globbable.
|
||||||
|
|
||||||
1 | import* "@project7/*.pkl" as proj7Files
|
1 | import* "@project7/*.pkl" as proj7Files
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,13 +492,16 @@ class EvaluatorTest {
|
|||||||
val module1 = modulesDir.resolve("foo/bar/module1.pkl").createParentDirectories()
|
val module1 = modulesDir.resolve("foo/bar/module1.pkl").createParentDirectories()
|
||||||
val module2 = modulesDir.resolve("foo/baz/module2.pkl").createParentDirectories()
|
val module2 = modulesDir.resolve("foo/baz/module2.pkl").createParentDirectories()
|
||||||
|
|
||||||
module1.writeText("""
|
module1.writeText(
|
||||||
|
"""
|
||||||
// verify that relative import is resolved correctly
|
// verify that relative import is resolved correctly
|
||||||
import "../baz/module2.pkl"
|
import "../baz/module2.pkl"
|
||||||
|
|
||||||
name = module2.name
|
name = module2.name
|
||||||
age = module2.age
|
age = module2.age
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
module2.writeText(sourceText)
|
module2.writeText(sourceText)
|
||||||
|
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
@@ -12,9 +27,7 @@ class JsonRendererTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `render document`() {
|
fun `render document`() {
|
||||||
val evaluator = Evaluator.preconfigured()
|
val evaluator = Evaluator.preconfigured()
|
||||||
val module = evaluator.evaluate(
|
val module = evaluator.evaluate(ModuleSource.modulePath("org/pkl/core/rendererTest.pkl"))
|
||||||
ModuleSource.modulePath("org/pkl/core/rendererTest.pkl")
|
|
||||||
)
|
|
||||||
val writer = StringWriter()
|
val writer = StringWriter()
|
||||||
val renderer = ValueRenderers.json(writer, " ", true)
|
val renderer = ValueRenderers.json(writer, " ", true)
|
||||||
|
|
||||||
@@ -23,14 +36,13 @@ class JsonRendererTest {
|
|||||||
val expected = IoUtils.readClassPathResourceAsString(javaClass, "rendererTest.json")
|
val expected = IoUtils.readClassPathResourceAsString(javaClass, "rendererTest.json")
|
||||||
|
|
||||||
assertThat(output).isEqualTo(expected)
|
assertThat(output).isEqualTo(expected)
|
||||||
assertThatCode { JsonParser(object : JsonHandler<Any, Any>() {}).parse(output) }.doesNotThrowAnyException()
|
assertThatCode { JsonParser(object : JsonHandler<Any, Any>() {}).parse(output) }
|
||||||
|
.doesNotThrowAnyException()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `rendered document ends in newline`() {
|
fun `rendered document ends in newline`() {
|
||||||
val module: PModule = Evaluator
|
val module: PModule = Evaluator.preconfigured().evaluate(ModuleSource.text("foo { bar = 0 }"))
|
||||||
.preconfigured()
|
|
||||||
.evaluate(ModuleSource.text("foo { bar = 0 }"))
|
|
||||||
|
|
||||||
for (omitNullProperties in listOf(false, true)) {
|
for (omitNullProperties in listOf(false, true)) {
|
||||||
val writer = StringWriter()
|
val writer = StringWriter()
|
||||||
|
|||||||
@@ -1,18 +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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.junit.platform.commons.annotation.Testable
|
import org.junit.platform.commons.annotation.Testable
|
||||||
|
|
||||||
@Testable
|
@Testable class LanguageSnippetTests
|
||||||
class LanguageSnippetTests
|
|
||||||
|
|
||||||
@Testable
|
@Testable class MacLanguageSnippetTests
|
||||||
class MacLanguageSnippetTests
|
|
||||||
|
|
||||||
@Testable
|
@Testable class LinuxLanguageSnippetTests
|
||||||
class LinuxLanguageSnippetTests
|
|
||||||
|
|
||||||
@Testable
|
@Testable class AlpineLanguageSnippetTests
|
||||||
class AlpineLanguageSnippetTests
|
|
||||||
|
|
||||||
@Testable
|
@Testable class WindowsLanguageSnippetTests
|
||||||
class WindowsLanguageSnippetTests
|
|
||||||
|
|||||||
@@ -1,5 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* 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.core
|
package org.pkl.core
|
||||||
|
|
||||||
|
import java.io.PrintWriter
|
||||||
|
import java.io.StringWriter
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.exists
|
||||||
|
import kotlin.io.path.isRegularFile
|
||||||
|
import kotlin.reflect.KClass
|
||||||
import org.junit.platform.engine.EngineDiscoveryRequest
|
import org.junit.platform.engine.EngineDiscoveryRequest
|
||||||
import org.junit.platform.engine.TestDescriptor
|
import org.junit.platform.engine.TestDescriptor
|
||||||
import org.junit.platform.engine.UniqueId
|
import org.junit.platform.engine.UniqueId
|
||||||
@@ -11,13 +33,6 @@ import org.pkl.commons.test.PklExecutablePaths
|
|||||||
import org.pkl.core.http.HttpClient
|
import org.pkl.core.http.HttpClient
|
||||||
import org.pkl.core.project.Project
|
import org.pkl.core.project.Project
|
||||||
import org.pkl.core.util.IoUtils
|
import org.pkl.core.util.IoUtils
|
||||||
import java.io.PrintWriter
|
|
||||||
import java.io.StringWriter
|
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
|
||||||
import kotlin.io.path.exists
|
|
||||||
import kotlin.io.path.isRegularFile
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
abstract class AbstractLanguageSnippetTestsEngine : InputOutputTestEngine() {
|
abstract class AbstractLanguageSnippetTestsEngine : InputOutputTestEngine() {
|
||||||
private val lineNumberRegex = Regex("(?m)^(( ║ )*)(\\d+) \\|")
|
private val lineNumberRegex = Regex("(?m)^(( ║ )*)(\\d+) \\|")
|
||||||
@@ -31,17 +46,17 @@ abstract class AbstractLanguageSnippetTestsEngine : InputOutputTestEngine() {
|
|||||||
private val expectedOutputDir: Path = snippetsDir.resolve("output")
|
private val expectedOutputDir: Path = snippetsDir.resolve("output")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience for development; this selects which snippet test(s) to run.
|
* Convenience for development; this selects which snippet test(s) to run. There is a
|
||||||
* There is a (non-language-snippet) test to make sure this is `""` before commit.
|
* (non-language-snippet) test to make sure this is `""` before commit.
|
||||||
*/
|
*/
|
||||||
//language=regexp
|
// language=regexp
|
||||||
internal val selection: String = ""
|
internal val selection: String = ""
|
||||||
|
|
||||||
protected val packageServer: PackageServer = PackageServer()
|
protected val packageServer: PackageServer = PackageServer()
|
||||||
|
|
||||||
override val includedTests: List<Regex> = listOf(Regex(".*$selection\\.pkl"))
|
override val includedTests: List<Regex> = listOf(Regex(".*$selection\\.pkl"))
|
||||||
|
|
||||||
override val excludedTests: List<Regex> = buildList {
|
override val excludedTests: List<Regex> = buildList {
|
||||||
add(Regex(".*/native/.*"))
|
add(Regex(".*/native/.*"))
|
||||||
if (IoUtils.isWindows()) {
|
if (IoUtils.isWindows()) {
|
||||||
addAll(windowsExcludedTests)
|
addAll(windowsExcludedTests)
|
||||||
@@ -53,8 +68,7 @@ abstract class AbstractLanguageSnippetTestsEngine : InputOutputTestEngine() {
|
|||||||
override val isInputFile: (Path) -> Boolean = { it.isRegularFile() }
|
override val isInputFile: (Path) -> Boolean = { it.isRegularFile() }
|
||||||
|
|
||||||
protected tailrec fun Path.getProjectDir(): Path? =
|
protected tailrec fun Path.getProjectDir(): Path? =
|
||||||
if (Files.exists(this.resolve("PklProject"))) this
|
if (Files.exists(this.resolve("PklProject"))) this else parent?.getProjectDir()
|
||||||
else parent?.getProjectDir()
|
|
||||||
|
|
||||||
override fun expectedOutputFileFor(inputFile: Path): Path {
|
override fun expectedOutputFileFor(inputFile: Path): Path {
|
||||||
val relativePath = IoUtils.relativize(inputFile, inputDir).toString()
|
val relativePath = IoUtils.relativize(inputFile, inputDir).toString()
|
||||||
@@ -75,17 +89,19 @@ abstract class AbstractLanguageSnippetTestsEngine : InputOutputTestEngine() {
|
|||||||
|
|
||||||
private val replacement by lazy {
|
private val replacement by lazy {
|
||||||
if (snippetsDir.root.toString() != "/") "\$snippetsDir" else "/\$snippetsDir"
|
if (snippetsDir.root.toString() != "/") "\$snippetsDir" else "/\$snippetsDir"
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun String.stripFilePaths(): String =
|
protected fun String.stripFilePaths(): String =
|
||||||
replace(IoUtils.toNormalizedPathString(snippetsDir), replacement)
|
replace(IoUtils.toNormalizedPathString(snippetsDir), replacement)
|
||||||
|
|
||||||
protected fun String.stripLineNumbers() = replace(lineNumberRegex) { result ->
|
protected fun String.stripLineNumbers() =
|
||||||
// replace line number with equivalent number of 'x' characters to keep formatting intact
|
replace(lineNumberRegex) { result ->
|
||||||
(result.groups[1]!!.value) + "x".repeat(result.groups[3]!!.value.length) + " |"
|
// replace line number with equivalent number of 'x' characters to keep formatting intact
|
||||||
}
|
(result.groups[1]!!.value) + "x".repeat(result.groups[3]!!.value.length) + " |"
|
||||||
|
}
|
||||||
|
|
||||||
protected fun String.stripWebsite() = replace(Release.current().documentation().homepage(), "https://\$pklWebsite/")
|
protected fun String.stripWebsite() =
|
||||||
|
replace(Release.current().documentation().homepage(), "https://\$pklWebsite/")
|
||||||
|
|
||||||
// can't think of a better solution right now
|
// can't think of a better solution right now
|
||||||
protected fun String.stripVersionCheckErrorMessage() =
|
protected fun String.stripVersionCheckErrorMessage() =
|
||||||
@@ -103,8 +119,7 @@ abstract class AbstractLanguageSnippetTestsEngine : InputOutputTestEngine() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected fun String.withUnixLineEndings(): String {
|
protected fun String.withUnixLineEndings(): String {
|
||||||
return if (System.lineSeparator() == "\r\n") replace("\r\n", "\n")
|
return if (System.lineSeparator() == "\r\n") replace("\r\n", "\n") else this
|
||||||
else this
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,16 +138,16 @@ class LanguageSnippetTestsEngine : AbstractLanguageSnippetTestsEngine() {
|
|||||||
"file:///foo/bar" to "file:///foo/bar"
|
"file:///foo/bar" to "file:///foo/bar"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.setExternalProperties(mapOf(
|
.setExternalProperties(
|
||||||
"name1" to "value1",
|
mapOf("name1" to "value1", "name2" to "value2", "/foo/bar" to "foobar")
|
||||||
"name2" to "value2",
|
)
|
||||||
"/foo/bar" to "foobar"
|
|
||||||
))
|
|
||||||
.setModuleCacheDir(null)
|
.setModuleCacheDir(null)
|
||||||
.setHttpClient(HttpClient.builder()
|
.setHttpClient(
|
||||||
.setTestPort(packageServer.port)
|
HttpClient.builder()
|
||||||
.addCertificates(FileTestUtils.selfSignedCertificate)
|
.setTestPort(packageServer.port)
|
||||||
.buildLazily())
|
.addCertificates(FileTestUtils.selfSignedCertificate)
|
||||||
|
.buildLazily()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val testClass: KClass<*> = LanguageSnippetTests::class
|
override val testClass: KClass<*> = LanguageSnippetTests::class
|
||||||
@@ -140,60 +155,65 @@ class LanguageSnippetTestsEngine : AbstractLanguageSnippetTestsEngine() {
|
|||||||
override fun generateOutputFor(inputFile: Path): kotlin.Pair<Boolean, String> {
|
override fun generateOutputFor(inputFile: Path): kotlin.Pair<Boolean, String> {
|
||||||
val logWriter = StringWriter()
|
val logWriter = StringWriter()
|
||||||
|
|
||||||
val (success, output) = try {
|
val (success, output) =
|
||||||
val evaluator = evaluatorBuilder()
|
try {
|
||||||
.setLogger(Loggers.writer(PrintWriter(logWriter)))
|
val evaluator =
|
||||||
.apply {
|
evaluatorBuilder()
|
||||||
if (inputFile.startsWith(projectsDir)) {
|
.setLogger(Loggers.writer(PrintWriter(logWriter)))
|
||||||
val projectDir = inputFile.getProjectDir() ?: return@apply
|
.apply {
|
||||||
val project = Project.loadFromPath(
|
if (inputFile.startsWith(projectsDir)) {
|
||||||
projectDir.resolve("PklProject"),
|
val projectDir = inputFile.getProjectDir() ?: return@apply
|
||||||
SecurityManagers.defaultManager,
|
val project =
|
||||||
null,
|
Project.loadFromPath(
|
||||||
StackFrameTransformers.empty,
|
projectDir.resolve("PklProject"),
|
||||||
mapOf()
|
SecurityManagers.defaultManager,
|
||||||
)
|
null,
|
||||||
securityManager = null
|
StackFrameTransformers.empty,
|
||||||
applyFromProject(project)
|
mapOf()
|
||||||
}
|
)
|
||||||
}
|
securityManager = null
|
||||||
.build()
|
applyFromProject(project)
|
||||||
evaluator.use { true to it.evaluateOutputText(ModuleSource.path(inputFile)) }
|
}
|
||||||
} catch (e: PklBugException) {
|
}
|
||||||
false to e.stackTraceToString()
|
.build()
|
||||||
} catch (e: PklException) {
|
evaluator.use { true to it.evaluateOutputText(ModuleSource.path(inputFile)) }
|
||||||
false to e.message!!
|
} catch (e: PklBugException) {
|
||||||
.stripLineNumbers()
|
false to e.stackTraceToString()
|
||||||
.stripVersionCheckErrorMessage()
|
} catch (e: PklException) {
|
||||||
}
|
false to e.message!!.stripLineNumbers().stripVersionCheckErrorMessage()
|
||||||
|
}
|
||||||
|
|
||||||
val stderr = logWriter.toString().withUnixLineEndings()
|
val stderr = logWriter.toString().withUnixLineEndings()
|
||||||
|
|
||||||
return (success && stderr.isBlank()) to (output + stderr).stripFilePaths().stripWebsite().stripStdlibLocationSha()
|
return (success && stderr.isBlank()) to
|
||||||
|
(output + stderr).stripFilePaths().stripWebsite().stripStdlibLocationSha()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class AbstractNativeLanguageSnippetTestsEngine : AbstractLanguageSnippetTestsEngine() {
|
abstract class AbstractNativeLanguageSnippetTestsEngine : AbstractLanguageSnippetTestsEngine() {
|
||||||
abstract val pklExecutablePath: Path
|
abstract val pklExecutablePath: Path
|
||||||
|
|
||||||
override val excludedTests: List<Regex> = listOf(
|
override val excludedTests: List<Regex> =
|
||||||
// exclude test that loads module from class path (there is no class path when using native executable)
|
listOf(
|
||||||
// on the other hand, don't exclude /native/
|
// exclude test that loads module from class path (there is no class path when using native
|
||||||
Regex(".*/import1b\\.pkl"),
|
// executable)
|
||||||
)
|
// on the other hand, don't exclude /native/
|
||||||
|
Regex(".*/import1b\\.pkl"),
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/** Avoid running tests for native binaries when those native binaries have not been built. */
|
||||||
* Avoid running tests for native binaries when those native binaries have not been built.
|
override fun discover(
|
||||||
*/
|
discoveryRequest: EngineDiscoveryRequest,
|
||||||
override fun discover(discoveryRequest: EngineDiscoveryRequest, uniqueId: UniqueId): TestDescriptor {
|
uniqueId: UniqueId
|
||||||
|
): TestDescriptor {
|
||||||
if (!pklExecutablePath.exists()) {
|
if (!pklExecutablePath.exists()) {
|
||||||
// return empty descriptor w/o children
|
// return empty descriptor w/o children
|
||||||
return EngineDescriptor(uniqueId, javaClass.simpleName)
|
return EngineDescriptor(uniqueId, javaClass.simpleName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.discover(discoveryRequest, uniqueId)
|
return super.discover(discoveryRequest, uniqueId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateOutputFor(inputFile: Path): kotlin.Pair<Boolean, String> {
|
override fun generateOutputFor(inputFile: Path): kotlin.Pair<Boolean, String> {
|
||||||
val args = buildList {
|
val args = buildList {
|
||||||
add(pklExecutablePath.toString())
|
add(pklExecutablePath.toString())
|
||||||
@@ -234,20 +254,22 @@ abstract class AbstractNativeLanguageSnippetTestsEngine : AbstractLanguageSnippe
|
|||||||
add(inputFile.toString())
|
add(inputFile.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
val builder = ProcessBuilder()
|
val builder = ProcessBuilder().command(args)
|
||||||
.command(args)
|
|
||||||
|
|
||||||
val process = builder.start()
|
val process = builder.start()
|
||||||
return try {
|
return try {
|
||||||
val (out, err) = listOf(process.inputStream, process.errorStream)
|
val (out, err) =
|
||||||
.map { it.reader().readText().withUnixLineEndings() }
|
listOf(process.inputStream, process.errorStream).map {
|
||||||
|
it.reader().readText().withUnixLineEndings()
|
||||||
|
}
|
||||||
val success = process.waitFor() == 0 && err.isBlank()
|
val success = process.waitFor() == 0 && err.isBlank()
|
||||||
success to (out + err)
|
success to
|
||||||
.stripFilePaths()
|
(out + err)
|
||||||
.stripLineNumbers()
|
.stripFilePaths()
|
||||||
.stripWebsite()
|
.stripLineNumbers()
|
||||||
.stripVersionCheckErrorMessage()
|
.stripWebsite()
|
||||||
.stripStdlibLocationSha()
|
.stripVersionCheckErrorMessage()
|
||||||
|
.stripStdlibLocationSha()
|
||||||
} finally {
|
} finally {
|
||||||
process.destroy()
|
process.destroy()
|
||||||
}
|
}
|
||||||
@@ -280,11 +302,12 @@ class AlpineLanguageSnippetTestsEngine : AbstractNativeLanguageSnippetTestsEngin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// error message contains different file path on Windows
|
// error message contains different file path on Windows
|
||||||
private val windowsExcludedTests get() = listOf(Regex(".*missingProjectDeps/bug\\.pkl"))
|
private val windowsExcludedTests
|
||||||
|
get() = listOf(Regex(".*missingProjectDeps/bug\\.pkl"))
|
||||||
|
|
||||||
class WindowsLanguageSnippetTestsEngine : AbstractNativeLanguageSnippetTestsEngine() {
|
class WindowsLanguageSnippetTestsEngine : AbstractNativeLanguageSnippetTestsEngine() {
|
||||||
override val pklExecutablePath: Path = PklExecutablePaths.windowsAmd64
|
override val pklExecutablePath: Path = PklExecutablePaths.windowsAmd64
|
||||||
override val testClass: KClass<*> = WindowsLanguageSnippetTests::class
|
override val testClass: KClass<*> = WindowsLanguageSnippetTests::class
|
||||||
override val excludedTests: List<Regex>
|
override val excludedTests: List<Regex>
|
||||||
get() = super.excludedTests + windowsExcludedTests
|
get() = super.excludedTests + windowsExcludedTests
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* 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.core
|
package org.pkl.core
|
||||||
|
|
||||||
|
import java.net.URI
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.net.URI
|
|
||||||
|
|
||||||
class PClassInfoTest {
|
class PClassInfoTest {
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -1,13 +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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
import javax.xml.parsers.DocumentBuilderFactory
|
import javax.xml.parsers.DocumentBuilderFactory
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.pkl.core.util.IoUtils
|
||||||
import org.xml.sax.ErrorHandler
|
import org.xml.sax.ErrorHandler
|
||||||
import org.xml.sax.InputSource
|
import org.xml.sax.InputSource
|
||||||
import org.xml.sax.SAXParseException
|
import org.xml.sax.SAXParseException
|
||||||
import org.pkl.core.util.IoUtils
|
|
||||||
|
|
||||||
class PListRendererTest {
|
class PListRendererTest {
|
||||||
@Test
|
@Test
|
||||||
@@ -28,8 +43,7 @@ class PListRendererTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `rendered document ends in newline`() {
|
fun `rendered document ends in newline`() {
|
||||||
val module = Evaluator.preconfigured()
|
val module = Evaluator.preconfigured().evaluate(ModuleSource.text("foo { bar = 0 }"))
|
||||||
.evaluate(ModuleSource.text("foo { bar = 0 }"))
|
|
||||||
|
|
||||||
val writer = StringWriter()
|
val writer = StringWriter()
|
||||||
ValueRenderers.plist(writer, " ").renderDocument(module)
|
ValueRenderers.plist(writer, " ").renderDocument(module)
|
||||||
@@ -37,28 +51,29 @@ class PListRendererTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun parseAndValidateRenderedDocument(output: String) {
|
private fun parseAndValidateRenderedDocument(output: String) {
|
||||||
val builderFactory = DocumentBuilderFactory.newInstance().apply {
|
val builderFactory = DocumentBuilderFactory.newInstance().apply { isValidating = true }
|
||||||
isValidating = true
|
|
||||||
}
|
|
||||||
|
|
||||||
val builder = builderFactory.newDocumentBuilder().apply {
|
val builder =
|
||||||
setEntityResolver { _, _ ->
|
builderFactory.newDocumentBuilder().apply {
|
||||||
InputSource(PListRendererTest::class.java.getResourceAsStream("PropertyList-1.0.dtd"))
|
setEntityResolver { _, _ ->
|
||||||
|
InputSource(PListRendererTest::class.java.getResourceAsStream("PropertyList-1.0.dtd"))
|
||||||
|
}
|
||||||
|
setErrorHandler(
|
||||||
|
object : ErrorHandler {
|
||||||
|
override fun warning(exception: SAXParseException) {
|
||||||
|
throw exception
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun error(exception: SAXParseException) {
|
||||||
|
throw exception
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fatalError(exception: SAXParseException) {
|
||||||
|
throw exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
setErrorHandler(object : ErrorHandler {
|
|
||||||
override fun warning(exception: SAXParseException) {
|
|
||||||
throw exception
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun error(exception: SAXParseException) {
|
|
||||||
throw exception
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fatalError(exception: SAXParseException) {
|
|
||||||
throw exception
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.parse(output.byteInputStream())
|
builder.parse(output.byteInputStream())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
@@ -25,14 +40,12 @@ class PModuleTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get unknown property`() {
|
fun `get unknown property`() {
|
||||||
val e = assertThrows<NoSuchPropertyException> {
|
val e = assertThrows<NoSuchPropertyException> { pigeon.getProperty("other") }
|
||||||
pigeon.getProperty("other")
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThat(e)
|
assertThat(e)
|
||||||
.hasMessage(
|
.hasMessage(
|
||||||
"Module `test.module` does not have a property " +
|
"Module `test.module` does not have a property " +
|
||||||
"named `other`. Available properties: [name, age]"
|
"named `other`. Available properties: [name, age]"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,15 +61,16 @@ class PModuleTest {
|
|||||||
var objectVisited = false
|
var objectVisited = false
|
||||||
var moduleVisited = false
|
var moduleVisited = false
|
||||||
|
|
||||||
val visitor = object : ValueVisitor {
|
val visitor =
|
||||||
override fun visitObject(value: PObject) {
|
object : ValueVisitor {
|
||||||
objectVisited = true
|
override fun visitObject(value: PObject) {
|
||||||
}
|
objectVisited = true
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitModule(value: PModule) {
|
override fun visitModule(value: PModule) {
|
||||||
moduleVisited = true
|
moduleVisited = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pigeon.accept(visitor)
|
pigeon.accept(visitor)
|
||||||
|
|
||||||
@@ -69,12 +83,7 @@ class PModuleTest {
|
|||||||
assertThat(pigeon).isEqualTo(pigeon)
|
assertThat(pigeon).isEqualTo(pigeon)
|
||||||
assertThat(pigeon.hashCode()).isEqualTo(pigeon.hashCode())
|
assertThat(pigeon.hashCode()).isEqualTo(pigeon.hashCode())
|
||||||
|
|
||||||
val pigeon2 = PModule(
|
val pigeon2 = PModule(moduleUri, moduleName, classInfo, HashMap(properties))
|
||||||
moduleUri,
|
|
||||||
moduleName,
|
|
||||||
classInfo,
|
|
||||||
HashMap(properties)
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(pigeon2).isEqualTo(pigeon)
|
assertThat(pigeon2).isEqualTo(pigeon)
|
||||||
assertThat(pigeon2.hashCode()).isEqualTo(pigeon.hashCode())
|
assertThat(pigeon2.hashCode()).isEqualTo(pigeon.hashCode())
|
||||||
@@ -82,12 +91,7 @@ class PModuleTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `non-equal - different module uri`() {
|
fun `non-equal - different module uri`() {
|
||||||
val pigeon2 = PModule(
|
val pigeon2 = PModule(URI("other/module"), moduleName, classInfo, properties)
|
||||||
URI("other/module"),
|
|
||||||
moduleName,
|
|
||||||
classInfo,
|
|
||||||
properties
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(pigeon2).isNotEqualTo(pigeon)
|
assertThat(pigeon2).isNotEqualTo(pigeon)
|
||||||
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
||||||
@@ -95,12 +99,7 @@ class PModuleTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `non-equal - different module name`() {
|
fun `non-equal - different module name`() {
|
||||||
val pigeon2 = PModule(
|
val pigeon2 = PModule(moduleUri, "other.module", classInfo, properties)
|
||||||
moduleUri,
|
|
||||||
"other.module",
|
|
||||||
classInfo,
|
|
||||||
properties
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(pigeon2).isNotEqualTo(pigeon)
|
assertThat(pigeon2).isNotEqualTo(pigeon)
|
||||||
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
||||||
@@ -108,12 +107,7 @@ class PModuleTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `non-equal - different property value`() {
|
fun `non-equal - different property value`() {
|
||||||
val pigeon2 = PModule(
|
val pigeon2 = PModule(moduleUri, moduleName, classInfo, mapOf("name" to "Pigeon", "age" to 21))
|
||||||
moduleUri,
|
|
||||||
moduleName,
|
|
||||||
classInfo,
|
|
||||||
mapOf("name" to "Pigeon", "age" to 21)
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(pigeon2).isNotEqualTo(pigeon)
|
assertThat(pigeon2).isNotEqualTo(pigeon)
|
||||||
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
||||||
@@ -121,12 +115,7 @@ class PModuleTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `non-equal - missing property`() {
|
fun `non-equal - missing property`() {
|
||||||
val pigeon2 = PModule(
|
val pigeon2 = PModule(moduleUri, moduleName, classInfo, mapOf("name" to "Pigeon"))
|
||||||
moduleUri,
|
|
||||||
moduleName,
|
|
||||||
classInfo,
|
|
||||||
mapOf("name" to "Pigeon")
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(pigeon2).isNotEqualTo(pigeon)
|
assertThat(pigeon2).isNotEqualTo(pigeon)
|
||||||
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
||||||
@@ -134,12 +123,13 @@ class PModuleTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `non-equal - extra property`() {
|
fun `non-equal - extra property`() {
|
||||||
val pigeon2 = PModule(
|
val pigeon2 =
|
||||||
moduleUri,
|
PModule(
|
||||||
moduleName,
|
moduleUri,
|
||||||
classInfo,
|
moduleName,
|
||||||
mapOf("name" to "Pigeon", "age" to 42, "other" to true)
|
classInfo,
|
||||||
)
|
mapOf("name" to "Pigeon", "age" to 42, "other" to true)
|
||||||
|
)
|
||||||
|
|
||||||
assertThat(pigeon2).isNotEqualTo(pigeon)
|
assertThat(pigeon2).isNotEqualTo(pigeon)
|
||||||
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
||||||
@@ -147,7 +137,6 @@ class PModuleTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `toString()`() {
|
fun `toString()`() {
|
||||||
assertThat(pigeon.toString())
|
assertThat(pigeon.toString()).isEqualTo("test.module { name = Pigeon; age = 42 }")
|
||||||
.isEqualTo("test.module { name = Pigeon; age = 42 }")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
|||||||
@@ -1,9 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* 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.core
|
package org.pkl.core
|
||||||
|
|
||||||
|
import java.net.URI
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.assertThrows
|
import org.junit.jupiter.api.assertThrows
|
||||||
import java.net.URI
|
|
||||||
|
|
||||||
class PObjectTest {
|
class PObjectTest {
|
||||||
private val testUri = URI("repl:test")
|
private val testUri = URI("repl:test")
|
||||||
@@ -29,14 +44,12 @@ class PObjectTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get unknown property`() {
|
fun `get unknown property`() {
|
||||||
val e = assertThrows<NoSuchPropertyException> {
|
val e = assertThrows<NoSuchPropertyException> { pigeon.getProperty("other") }
|
||||||
pigeon.getProperty("other")
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThat(e)
|
assertThat(e)
|
||||||
.hasMessage(
|
.hasMessage(
|
||||||
"Object of type `test#Person` does not have a property " +
|
"Object of type `test#Person` does not have a property " +
|
||||||
"named `other`. Available properties: [name, age]"
|
"named `other`. Available properties: [name, age]"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,15 +65,16 @@ class PObjectTest {
|
|||||||
var objectVisited = false
|
var objectVisited = false
|
||||||
var moduleVisited = false
|
var moduleVisited = false
|
||||||
|
|
||||||
val visitor = object : ValueVisitor {
|
val visitor =
|
||||||
override fun visitObject(value: PObject) {
|
object : ValueVisitor {
|
||||||
objectVisited = true
|
override fun visitObject(value: PObject) {
|
||||||
}
|
objectVisited = true
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitModule(value: PModule) {
|
override fun visitModule(value: PModule) {
|
||||||
moduleVisited = true
|
moduleVisited = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pigeon.accept(visitor)
|
pigeon.accept(visitor)
|
||||||
|
|
||||||
@@ -73,10 +87,7 @@ class PObjectTest {
|
|||||||
assertThat(pigeon).isEqualTo(pigeon)
|
assertThat(pigeon).isEqualTo(pigeon)
|
||||||
assertThat(pigeon.hashCode()).isEqualTo(pigeon.hashCode())
|
assertThat(pigeon.hashCode()).isEqualTo(pigeon.hashCode())
|
||||||
|
|
||||||
val pigeon2 = PObject(
|
val pigeon2 = PObject(PClassInfo.get("test", "Person", URI("repl:test")), HashMap(properties))
|
||||||
PClassInfo.get("test", "Person", URI("repl:test")),
|
|
||||||
HashMap(properties)
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(pigeon2).isEqualTo(pigeon)
|
assertThat(pigeon2).isEqualTo(pigeon)
|
||||||
assertThat(pigeon2.hashCode()).isEqualTo(pigeon.hashCode())
|
assertThat(pigeon2.hashCode()).isEqualTo(pigeon.hashCode())
|
||||||
@@ -84,10 +95,7 @@ class PObjectTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `non-equal - different type`() {
|
fun `non-equal - different type`() {
|
||||||
val pigeon2 = PObject(
|
val pigeon2 = PObject(PClassInfo.get("test", "Other", URI("repl:Other")), properties)
|
||||||
PClassInfo.get("test", "Other", URI("repl:Other")),
|
|
||||||
properties
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(pigeon2).isNotEqualTo(pigeon)
|
assertThat(pigeon2).isNotEqualTo(pigeon)
|
||||||
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
||||||
@@ -95,10 +103,11 @@ class PObjectTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `non-equal - different property value`() {
|
fun `non-equal - different property value`() {
|
||||||
val pigeon2 = PObject(
|
val pigeon2 =
|
||||||
PClassInfo.get("test", "Person", URI("repl:test")),
|
PObject(
|
||||||
mapOf("name" to "Pigeon", "age" to 21)
|
PClassInfo.get("test", "Person", URI("repl:test")),
|
||||||
)
|
mapOf("name" to "Pigeon", "age" to 21)
|
||||||
|
)
|
||||||
|
|
||||||
assertThat(pigeon2).isNotEqualTo(pigeon)
|
assertThat(pigeon2).isNotEqualTo(pigeon)
|
||||||
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
||||||
@@ -106,10 +115,8 @@ class PObjectTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `non-equal - missing property`() {
|
fun `non-equal - missing property`() {
|
||||||
val pigeon2 = PObject(
|
val pigeon2 =
|
||||||
PClassInfo.get("test", "Person", URI("repl:test")),
|
PObject(PClassInfo.get("test", "Person", URI("repl:test")), mapOf("name" to "Pigeon"))
|
||||||
mapOf("name" to "Pigeon")
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(pigeon2).isNotEqualTo(pigeon)
|
assertThat(pigeon2).isNotEqualTo(pigeon)
|
||||||
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
||||||
@@ -117,10 +124,11 @@ class PObjectTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `non-equal - extra property`() {
|
fun `non-equal - extra property`() {
|
||||||
val pigeon2 = PObject(
|
val pigeon2 =
|
||||||
PClassInfo.get("test", "Person", URI("repl:test")),
|
PObject(
|
||||||
mapOf("name" to "Pigeon", "age" to 42, "other" to true)
|
PClassInfo.get("test", "Person", URI("repl:test")),
|
||||||
)
|
mapOf("name" to "Pigeon", "age" to 42, "other" to true)
|
||||||
|
)
|
||||||
|
|
||||||
assertThat(pigeon2).isNotEqualTo(pigeon)
|
assertThat(pigeon2).isNotEqualTo(pigeon)
|
||||||
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
assertThat(pigeon2.hashCode()).isNotEqualTo(pigeon.hashCode())
|
||||||
@@ -128,7 +136,6 @@ class PObjectTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `toString()`() {
|
fun `toString()`() {
|
||||||
assertThat(pigeon.toString())
|
assertThat(pigeon.toString()).isEqualTo("test#Person { name = Pigeon; age = 42 }")
|
||||||
.isEqualTo("test#Person { name = Pigeon; age = 42 }")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
@@ -21,14 +36,13 @@ class PcfRendererTest {
|
|||||||
assertThat(output.trim()).isEqualTo(expected.trim())
|
assertThat(output.trim()).isEqualTo(expected.trim())
|
||||||
|
|
||||||
// TODO: make pcf a pkl subset again
|
// TODO: make pcf a pkl subset again
|
||||||
//assertThatCode { evaluator.evaluateText(output) }.doesNotThrowAnyException()
|
// assertThatCode { evaluator.evaluateText(output) }.doesNotThrowAnyException()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `rendered document ends in newline`() {
|
fun `rendered document ends in newline`() {
|
||||||
val module = EvaluatorBuilder.preconfigured()
|
val module =
|
||||||
.build()
|
EvaluatorBuilder.preconfigured().build().evaluate(ModuleSource.text("foo { bar = 0 }"))
|
||||||
.evaluate(ModuleSource.text("foo { bar = 0 }"))
|
|
||||||
|
|
||||||
val writer = StringWriter()
|
val writer = StringWriter()
|
||||||
ValueRenderers.pcf(writer, " ", false, false).renderDocument(module)
|
ValueRenderers.pcf(writer, " ", false, false).renderDocument(module)
|
||||||
@@ -37,16 +51,19 @@ class PcfRendererTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `rendering with and without null properties`() {
|
fun `rendering with and without null properties`() {
|
||||||
val cases = listOf(
|
val cases =
|
||||||
true to """
|
listOf(
|
||||||
|
true to
|
||||||
|
"""
|
||||||
baz {
|
baz {
|
||||||
qux = 42
|
qux = 42
|
||||||
corge = List(null, 1337, null, "Hello World")
|
corge = List(null, 1337, null, "Hello World")
|
||||||
grault = Map("garply", null, "waldo", 42, "pigeon", null)
|
grault = Map("garply", null, "waldo", 42, "pigeon", null)
|
||||||
}
|
}
|
||||||
""".trimIndent(),
|
"""
|
||||||
|
.trimIndent(),
|
||||||
false to """
|
false to
|
||||||
|
"""
|
||||||
foo = null
|
foo = null
|
||||||
bar = null
|
bar = null
|
||||||
baz {
|
baz {
|
||||||
@@ -55,12 +72,15 @@ class PcfRendererTest {
|
|||||||
corge = List(null, 1337, null, "Hello World")
|
corge = List(null, 1337, null, "Hello World")
|
||||||
grault = Map("garply", null, "waldo", 42, "pigeon", null)
|
grault = Map("garply", null, "waldo", 42, "pigeon", null)
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
|
|
||||||
val module = Evaluator.preconfigured().evaluate(
|
|
||||||
ModuleSource.text(
|
|
||||||
"""
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
val module =
|
||||||
|
Evaluator.preconfigured()
|
||||||
|
.evaluate(
|
||||||
|
ModuleSource.text(
|
||||||
|
"""
|
||||||
foo = null
|
foo = null
|
||||||
bar = null
|
bar = null
|
||||||
baz {
|
baz {
|
||||||
@@ -78,9 +98,10 @@ class PcfRendererTest {
|
|||||||
["pigeon"] = null
|
["pigeon"] = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
"""
|
||||||
)
|
.trimIndent()
|
||||||
)
|
)
|
||||||
|
)
|
||||||
for ((omitNullProperties, expected) in cases) {
|
for ((omitNullProperties, expected) in cases) {
|
||||||
val writer = StringWriter()
|
val writer = StringWriter()
|
||||||
ValueRenderers.pcf(writer, " ", omitNullProperties, false).renderDocument(module)
|
ValueRenderers.pcf(writer, " ", omitNullProperties, false).renderDocument(module)
|
||||||
@@ -90,7 +111,7 @@ class PcfRendererTest {
|
|||||||
|
|
||||||
// TODO: ada
|
// TODO: ada
|
||||||
// can happen in REPL or when rendering manually constructed container
|
// can happen in REPL or when rendering manually constructed container
|
||||||
/* @Test
|
/* @Test
|
||||||
fun `render container with unevaluated element`() {
|
fun `render container with unevaluated element`() {
|
||||||
renderer.renderValue(PObject(PClassInfo.Mapping, mapOf("one" to 1L, "two" to null)))
|
renderer.renderValue(PObject(PClassInfo.Mapping, mapOf("one" to 1L, "two" to null)))
|
||||||
|
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.*
|
import org.assertj.core.api.Assertions.*
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.*
|
import org.assertj.core.api.Assertions.*
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
@@ -10,23 +25,31 @@ class PropertiesRendererTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `render document`() {
|
fun `render document`() {
|
||||||
val evaluator = Evaluator.preconfigured()
|
val evaluator = Evaluator.preconfigured()
|
||||||
val module = evaluator.evaluate(ModuleSource.modulePath("org/pkl/core/propertiesRendererTest.pkl"))
|
val module =
|
||||||
|
evaluator.evaluate(ModuleSource.modulePath("org/pkl/core/propertiesRendererTest.pkl"))
|
||||||
val writer = StringWriter()
|
val writer = StringWriter()
|
||||||
val renderer = ValueRenderers.properties(writer, true, false)
|
val renderer = ValueRenderers.properties(writer, true, false)
|
||||||
|
|
||||||
renderer.renderDocument(module)
|
renderer.renderDocument(module)
|
||||||
val output = writer.toString()
|
val output = writer.toString()
|
||||||
val expected = IoUtils.readClassPathResourceAsString(javaClass, "propertiesRendererTest.properties")
|
val expected =
|
||||||
|
IoUtils.readClassPathResourceAsString(javaClass, "propertiesRendererTest.properties")
|
||||||
|
|
||||||
assertThat(output).isEqualTo(expected)
|
assertThat(output).isEqualTo(expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `render unsupported document values`() {
|
fun `render unsupported document values`() {
|
||||||
val unsupportedValues = listOf(
|
val unsupportedValues =
|
||||||
"List()", "new Listing {}", "Map()", "new Mapping {}", "Set()",
|
listOf(
|
||||||
"new PropertiesRenderer {}", "new Dynamic {}"
|
"List()",
|
||||||
)
|
"new Listing {}",
|
||||||
|
"Map()",
|
||||||
|
"new Mapping {}",
|
||||||
|
"Set()",
|
||||||
|
"new PropertiesRenderer {}",
|
||||||
|
"new Dynamic {}"
|
||||||
|
)
|
||||||
|
|
||||||
unsupportedValues.forEach {
|
unsupportedValues.forEach {
|
||||||
val evaluator = Evaluator.preconfigured()
|
val evaluator = Evaluator.preconfigured()
|
||||||
@@ -39,13 +62,13 @@ class PropertiesRendererTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `rendered document ends in newline`() {
|
fun `rendered document ends in newline`() {
|
||||||
val module = Evaluator.preconfigured()
|
val module = Evaluator.preconfigured().evaluate(ModuleSource.text("foo { bar = 0 }"))
|
||||||
.evaluate(ModuleSource.text("foo { bar = 0 }"))
|
|
||||||
|
|
||||||
for (omitNullProperties in listOf(false, true)) {
|
for (omitNullProperties in listOf(false, true)) {
|
||||||
for (restrictCharSet in listOf(false, true)) {
|
for (restrictCharSet in listOf(false, true)) {
|
||||||
val writer = StringWriter()
|
val writer = StringWriter()
|
||||||
ValueRenderers.properties(writer, omitNullProperties, restrictCharSet).renderDocument(module)
|
ValueRenderers.properties(writer, omitNullProperties, restrictCharSet)
|
||||||
|
.renderDocument(module)
|
||||||
assertThat(writer.toString()).endsWith("\n")
|
assertThat(writer.toString()).endsWith("\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.*
|
import org.assertj.core.api.Assertions.*
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
@@ -11,36 +26,30 @@ import org.pkl.core.repl.ReplServer
|
|||||||
import org.pkl.core.resource.ResourceReaders
|
import org.pkl.core.resource.ResourceReaders
|
||||||
|
|
||||||
class ReplServerTest {
|
class ReplServerTest {
|
||||||
private val server = ReplServer(
|
private val server =
|
||||||
SecurityManagers.defaultManager,
|
ReplServer(
|
||||||
HttpClient.dummyClient(),
|
SecurityManagers.defaultManager,
|
||||||
Loggers.stdErr(),
|
HttpClient.dummyClient(),
|
||||||
listOf(
|
Loggers.stdErr(),
|
||||||
ModuleKeyFactories.standardLibrary,
|
listOf(
|
||||||
ModuleKeyFactories.classPath(this::class.java.classLoader),
|
ModuleKeyFactories.standardLibrary,
|
||||||
ModuleKeyFactories.file
|
ModuleKeyFactories.classPath(this::class.java.classLoader),
|
||||||
),
|
ModuleKeyFactories.file
|
||||||
listOf(
|
),
|
||||||
ResourceReaders.environmentVariable(),
|
listOf(ResourceReaders.environmentVariable(), ResourceReaders.externalProperty()),
|
||||||
ResourceReaders.externalProperty()
|
mapOf("NAME1" to "value1", "NAME2" to "value2"),
|
||||||
),
|
mapOf("name1" to "value1", "name2" to "value2"),
|
||||||
mapOf("NAME1" to "value1", "NAME2" to "value2"),
|
null,
|
||||||
mapOf("name1" to "value1", "name2" to "value2"),
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
"/".toPath(),
|
||||||
null,
|
StackFrameTransformers.defaultTransformer
|
||||||
"/".toPath(),
|
)
|
||||||
StackFrameTransformers.defaultTransformer
|
|
||||||
)
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `complete members of local property`() {
|
fun `complete members of local property`() {
|
||||||
server.handleRequest(
|
server.handleRequest(ReplRequest.Eval("id", "local foo = new { bar = 10 }", false, false))
|
||||||
ReplRequest.Eval("id", "local foo = new { bar = 10 }", false, false)
|
val responses = server.handleRequest(ReplRequest.Completion("id", "foo"))
|
||||||
)
|
|
||||||
val responses = server.handleRequest(
|
|
||||||
ReplRequest.Completion("id", "foo")
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(responses.size).isEqualTo(1)
|
assertThat(responses.size).isEqualTo(1)
|
||||||
|
|
||||||
@@ -51,9 +60,18 @@ class ReplServerTest {
|
|||||||
assertThat(completionResponse.members.toSortedSet())
|
assertThat(completionResponse.members.toSortedSet())
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
sortedSetOf(
|
sortedSetOf(
|
||||||
"default", "bar", "toList()", "toMap()", "getProperty(",
|
"default",
|
||||||
"getPropertyOrNull(", "hasProperty(", "ifNonNull(",
|
"bar",
|
||||||
"length()", "getClass()", "toString()", "toTyped("
|
"toList()",
|
||||||
|
"toMap()",
|
||||||
|
"getProperty(",
|
||||||
|
"getPropertyOrNull(",
|
||||||
|
"hasProperty(",
|
||||||
|
"ifNonNull(",
|
||||||
|
"length()",
|
||||||
|
"getClass()",
|
||||||
|
"toString()",
|
||||||
|
"toTyped("
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -61,9 +79,7 @@ class ReplServerTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `complete members of module import`() {
|
fun `complete members of module import`() {
|
||||||
server.handleRequest(ReplRequest.Eval("id", "import \"pkl:test\"", false, false))
|
server.handleRequest(ReplRequest.Eval("id", "import \"pkl:test\"", false, false))
|
||||||
val responses = server.handleRequest(
|
val responses = server.handleRequest(ReplRequest.Completion("id", "test"))
|
||||||
ReplRequest.Completion("id", "test")
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(responses.size).isEqualTo(1)
|
assertThat(responses.size).isEqualTo(1)
|
||||||
|
|
||||||
@@ -79,14 +95,11 @@ class ReplServerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `complete members of 'this' expression`() {
|
fun `complete members of 'this' expression`() {
|
||||||
val responses1 = server.handleRequest(
|
val responses1 =
|
||||||
ReplRequest.Eval("id", "x = 1; function f() = 3", false, false)
|
server.handleRequest(ReplRequest.Eval("id", "x = 1; function f() = 3", false, false))
|
||||||
)
|
|
||||||
assertThat(responses1.size).isEqualTo(0)
|
assertThat(responses1.size).isEqualTo(0)
|
||||||
|
|
||||||
val responses2 = server.handleRequest(
|
val responses2 = server.handleRequest(ReplRequest.Completion("id", "this"))
|
||||||
ReplRequest.Completion("id", "this")
|
|
||||||
)
|
|
||||||
assertThat(responses2.size).isEqualTo(1)
|
assertThat(responses2.size).isEqualTo(1)
|
||||||
|
|
||||||
val response = responses2[0]
|
val response = responses2[0]
|
||||||
@@ -96,8 +109,18 @@ class ReplServerTest {
|
|||||||
assertThat(completionResponse.members.toSortedSet())
|
assertThat(completionResponse.members.toSortedSet())
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
sortedSetOf(
|
sortedSetOf(
|
||||||
"output", "toDynamic()", "toMap()", "f()", "x", "ifNonNull(", "getClass()",
|
"output",
|
||||||
"getProperty(", "getPropertyOrNull(", "hasProperty(", "relativePathTo(", "toString()"
|
"toDynamic()",
|
||||||
|
"toMap()",
|
||||||
|
"f()",
|
||||||
|
"x",
|
||||||
|
"ifNonNull(",
|
||||||
|
"getClass()",
|
||||||
|
"getProperty(",
|
||||||
|
"getPropertyOrNull(",
|
||||||
|
"hasProperty(",
|
||||||
|
"relativePathTo(",
|
||||||
|
"toString()"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -156,7 +179,10 @@ class ReplServerTest {
|
|||||||
val result2 = makeEvalRequest("""greet(42)""")
|
val result2 = makeEvalRequest("""greet(42)""")
|
||||||
assertThat(result2).isEqualTo("\"Hello, 42!\"")
|
assertThat(result2).isEqualTo("\"Hello, 42!\"")
|
||||||
|
|
||||||
val result3 = makeEvalRequest("function greet(name: String): String = \"Hello, \\(name)!\"; greet(\"Pigeon\") ")
|
val result3 =
|
||||||
|
makeEvalRequest(
|
||||||
|
"function greet(name: String): String = \"Hello, \\(name)!\"; greet(\"Pigeon\") "
|
||||||
|
)
|
||||||
assertThat(result3).isEqualTo("\"Hello, Pigeon!\"")
|
assertThat(result3).isEqualTo("\"Hello, Pigeon!\"")
|
||||||
|
|
||||||
val result4 = makeFailingEvalRequest("""greet(44)""")
|
val result4 = makeFailingEvalRequest("""greet(44)""")
|
||||||
@@ -164,8 +190,7 @@ class ReplServerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun makeEvalRequest(text: String): String {
|
private fun makeEvalRequest(text: String): String {
|
||||||
val responses =
|
val responses = server.handleRequest(ReplRequest.Eval("id", text, false, false))
|
||||||
server.handleRequest(ReplRequest.Eval("id", text, false, false))
|
|
||||||
|
|
||||||
assertThat(responses).hasSize(1)
|
assertThat(responses).hasSize(1)
|
||||||
val response = responses[0]
|
val response = responses[0]
|
||||||
@@ -176,8 +201,7 @@ class ReplServerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun makeFailingEvalRequest(text: String): String {
|
private fun makeFailingEvalRequest(text: String): String {
|
||||||
val responses =
|
val responses = server.handleRequest(ReplRequest.Eval("id", text, false, false))
|
||||||
server.handleRequest(ReplRequest.Eval("id", text, false, false))
|
|
||||||
|
|
||||||
assertThat(responses).hasSize(1)
|
assertThat(responses).hasSize(1)
|
||||||
val response = responses[0]
|
val response = responses[0]
|
||||||
|
|||||||
@@ -1,13 +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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.pkl.commons.test.FileTestUtils
|
|
||||||
import org.pkl.commons.walk
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.util.stream.Collectors
|
import java.util.stream.Collectors
|
||||||
import kotlin.io.path.extension
|
import kotlin.io.path.extension
|
||||||
import kotlin.io.path.isRegularFile
|
import kotlin.io.path.isRegularFile
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.pkl.commons.test.FileTestUtils
|
||||||
|
import org.pkl.commons.walk
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These tests don't assert Pkl's implementation correctness, but rather that no debugging settings
|
* These tests don't assert Pkl's implementation correctness, but rather that no debugging settings
|
||||||
@@ -22,18 +37,24 @@ class RepositoryHygiene {
|
|||||||
@Test
|
@Test
|
||||||
fun `no output files exists for language snippets without an input`() {
|
fun `no output files exists for language snippets without an input`() {
|
||||||
val input = snippetsFolder.resolve("input")
|
val input = snippetsFolder.resolve("input")
|
||||||
val inputs = input.walk().filter {
|
val inputs =
|
||||||
it.extension == "pkl"
|
input
|
||||||
}.map {
|
.walk()
|
||||||
val path = input.relativize(it).toString()
|
.filter { it.extension == "pkl" }
|
||||||
inputRegex.replace(path, "$1$2")
|
.map {
|
||||||
}.collect(Collectors.toSet())
|
val path = input.relativize(it).toString()
|
||||||
|
inputRegex.replace(path, "$1$2")
|
||||||
|
}
|
||||||
|
.collect(Collectors.toSet())
|
||||||
|
|
||||||
val output = snippetsFolder.resolve("output")
|
val output = snippetsFolder.resolve("output")
|
||||||
output.walk().filter { it.isRegularFile() }.forEach {
|
output
|
||||||
val out = output.relativize(it).toString()
|
.walk()
|
||||||
checkOutputHasInput(inputs, out)
|
.filter { it.isRegularFile() }
|
||||||
}
|
.forEach {
|
||||||
|
val out = output.relativize(it).toString()
|
||||||
|
checkOutputHasInput(inputs, out)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkOutputHasInput(inputs: Set<String>, output: String) {
|
private fun checkOutputHasInput(inputs: Set<String>, output: String) {
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
@@ -12,116 +27,84 @@ import org.junit.jupiter.api.io.TempDir
|
|||||||
import org.pkl.commons.toPath
|
import org.pkl.commons.toPath
|
||||||
|
|
||||||
class SecurityManagersTest {
|
class SecurityManagersTest {
|
||||||
private val manager = SecurityManagers.standard(
|
private val manager =
|
||||||
listOf(Pattern.compile("test:foo/bar")),
|
SecurityManagers.standard(
|
||||||
listOf(Pattern.compile("env:FOO_BAR")),
|
listOf(Pattern.compile("test:foo/bar")),
|
||||||
{ uri -> if (uri.scheme == "one") 1 else if (uri.scheme == "two") 2 else 0 },
|
listOf(Pattern.compile("env:FOO_BAR")),
|
||||||
null
|
{ uri -> if (uri.scheme == "one") 1 else if (uri.scheme == "two") 2 else 0 },
|
||||||
)
|
null
|
||||||
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `checkResolveModule() - complete match`() {
|
fun `checkResolveModule() - complete match`() {
|
||||||
val e = catchThrowable {
|
val e = catchThrowable { manager.checkResolveModule(URI("test:foo/bar")) }
|
||||||
manager.checkResolveModule(URI("test:foo/bar"))
|
|
||||||
}
|
|
||||||
assertThat(e).doesNotThrowAnyException()
|
assertThat(e).doesNotThrowAnyException()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `checkResolveModule() - partial match from start`() {
|
fun `checkResolveModule() - partial match from start`() {
|
||||||
val e = catchThrowable {
|
val e = catchThrowable { manager.checkResolveModule(URI("test:foo/bar/baz")) }
|
||||||
manager.checkResolveModule(URI("test:foo/bar/baz"))
|
|
||||||
}
|
|
||||||
assertThat(e).doesNotThrowAnyException()
|
assertThat(e).doesNotThrowAnyException()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `checkResolveModule() - partial match not from start`() {
|
fun `checkResolveModule() - partial match not from start`() {
|
||||||
assertThrows<SecurityManagerException> {
|
assertThrows<SecurityManagerException> { manager.checkResolveModule(URI("other:test:foo/bar")) }
|
||||||
manager.checkResolveModule(URI("other:test:foo/bar"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `checkResolveModule() - no match`() {
|
fun `checkResolveModule() - no match`() {
|
||||||
assertThrows<SecurityManagerException> {
|
assertThrows<SecurityManagerException> { manager.checkResolveModule(URI("other:uri")) }
|
||||||
manager.checkResolveModule(URI("other:uri"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `checkResolveModule() - no match #2`() {
|
fun `checkResolveModule() - no match #2`() {
|
||||||
assertThrows<SecurityManagerException> {
|
assertThrows<SecurityManagerException> { manager.checkResolveModule(URI("test:foo/baz")) }
|
||||||
manager.checkResolveModule(URI("test:foo/baz"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `checkReadResource() - complete match`() {
|
fun `checkReadResource() - complete match`() {
|
||||||
val e = catchThrowable {
|
val e = catchThrowable { manager.checkReadResource(URI("env:FOO_BAR")) }
|
||||||
manager.checkReadResource(URI("env:FOO_BAR"))
|
|
||||||
}
|
|
||||||
assertThat(e).doesNotThrowAnyException()
|
assertThat(e).doesNotThrowAnyException()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `checkReadResource() - partial match from start`() {
|
fun `checkReadResource() - partial match from start`() {
|
||||||
val e = catchThrowable {
|
val e = catchThrowable { manager.checkReadResource(URI("env:FOO_BAR_BAZ")) }
|
||||||
manager.checkReadResource(URI("env:FOO_BAR_BAZ"))
|
|
||||||
}
|
|
||||||
assertThat(e).doesNotThrowAnyException()
|
assertThat(e).doesNotThrowAnyException()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `checkReadResource() - partial match not from start`() {
|
fun `checkReadResource() - partial match not from start`() {
|
||||||
assertThrows<SecurityManagerException> {
|
assertThrows<SecurityManagerException> { manager.checkReadResource(URI("other:env:FOO_BAR")) }
|
||||||
manager.checkReadResource(URI("other:env:FOO_BAR"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `checkReadResource() - no match`() {
|
fun `checkReadResource() - no match`() {
|
||||||
assertThrows<SecurityManagerException> {
|
assertThrows<SecurityManagerException> { manager.checkReadResource(URI("other:uri")) }
|
||||||
manager.checkReadResource(URI("other:uri"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `checkReadResource() - no match #2`() {
|
fun `checkReadResource() - no match #2`() {
|
||||||
assertThrows<SecurityManagerException> {
|
assertThrows<SecurityManagerException> { manager.checkReadResource(URI("env:FOO_BAZ")) }
|
||||||
manager.checkReadResource(URI("env:FOO_BAZ"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `checkImportModule() - same trust level`() {
|
fun `checkImportModule() - same trust level`() {
|
||||||
val e = catchThrowable {
|
val e = catchThrowable { manager.checkImportModule(URI("one:foo"), URI("one:bar")) }
|
||||||
manager.checkImportModule(
|
|
||||||
URI("one:foo"),
|
|
||||||
URI("one:bar")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
assertThat(e).doesNotThrowAnyException()
|
assertThat(e).doesNotThrowAnyException()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `checkImportModule() - higher trust level`() {
|
fun `checkImportModule() - higher trust level`() {
|
||||||
assertThrows<SecurityManagerException> {
|
assertThrows<SecurityManagerException> {
|
||||||
manager.checkImportModule(
|
manager.checkImportModule(URI("one:foo"), URI("two:bar"))
|
||||||
URI("one:foo"),
|
|
||||||
URI("two:bar")
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `checkImportModule() - lower trust level`() {
|
fun `checkImportModule() - lower trust level`() {
|
||||||
val e = catchThrowable {
|
val e = catchThrowable { manager.checkImportModule(URI("two:foo"), URI("one:bar")) }
|
||||||
manager.checkImportModule(
|
|
||||||
URI("two:foo"),
|
|
||||||
URI("one:bar")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
assertThat(e).doesNotThrowAnyException()
|
assertThat(e).doesNotThrowAnyException()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,12 +137,13 @@ class SecurityManagersTest {
|
|||||||
val rootDir = tempDir.resolve("root")
|
val rootDir = tempDir.resolve("root")
|
||||||
Files.createDirectory(rootDir)
|
Files.createDirectory(rootDir)
|
||||||
|
|
||||||
val manager = SecurityManagers.standard(
|
val manager =
|
||||||
listOf(Pattern.compile("file")),
|
SecurityManagers.standard(
|
||||||
listOf(Pattern.compile("file")),
|
listOf(Pattern.compile("file")),
|
||||||
SecurityManagers.defaultTrustLevels,
|
listOf(Pattern.compile("file")),
|
||||||
rootDir
|
SecurityManagers.defaultTrustLevels,
|
||||||
)
|
rootDir
|
||||||
|
)
|
||||||
|
|
||||||
val path = rootDir.resolve("baz.pkl")
|
val path = rootDir.resolve("baz.pkl")
|
||||||
Files.createFile(path)
|
Files.createFile(path)
|
||||||
@@ -174,12 +158,13 @@ class SecurityManagersTest {
|
|||||||
fun `can resolve modules and resources under root dir - files don't exist`() {
|
fun `can resolve modules and resources under root dir - files don't exist`() {
|
||||||
val rootDir = "/foo/bar".toPath()
|
val rootDir = "/foo/bar".toPath()
|
||||||
|
|
||||||
val manager = SecurityManagers.standard(
|
val manager =
|
||||||
listOf(Pattern.compile("file")),
|
SecurityManagers.standard(
|
||||||
listOf(Pattern.compile("file")),
|
listOf(Pattern.compile("file")),
|
||||||
SecurityManagers.defaultTrustLevels,
|
listOf(Pattern.compile("file")),
|
||||||
rootDir
|
SecurityManagers.defaultTrustLevels,
|
||||||
)
|
rootDir
|
||||||
|
)
|
||||||
|
|
||||||
manager.checkResolveModule(Path.of("/foo/bar/baz.pkl").toUri())
|
manager.checkResolveModule(Path.of("/foo/bar/baz.pkl").toUri())
|
||||||
manager.checkReadResource(Path.of("/foo/bar/baz.pkl").toUri())
|
manager.checkReadResource(Path.of("/foo/bar/baz.pkl").toUri())
|
||||||
@@ -189,48 +174,44 @@ class SecurityManagersTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `cannot resolve modules and resources outside root dir - files do exist`(@TempDir tempDir: Path) {
|
fun `cannot resolve modules and resources outside root dir - files do exist`(
|
||||||
|
@TempDir tempDir: Path
|
||||||
|
) {
|
||||||
val rootDir = tempDir.resolve("root")
|
val rootDir = tempDir.resolve("root")
|
||||||
Files.createDirectory(rootDir)
|
Files.createDirectory(rootDir)
|
||||||
|
|
||||||
val manager = SecurityManagers.standard(
|
val manager =
|
||||||
listOf(Pattern.compile("file")),
|
SecurityManagers.standard(
|
||||||
listOf(Pattern.compile("file")),
|
listOf(Pattern.compile("file")),
|
||||||
SecurityManagers.defaultTrustLevels,
|
listOf(Pattern.compile("file")),
|
||||||
rootDir
|
SecurityManagers.defaultTrustLevels,
|
||||||
)
|
rootDir
|
||||||
|
)
|
||||||
|
|
||||||
val path = rootDir.resolve("../baz.pkl")
|
val path = rootDir.resolve("../baz.pkl")
|
||||||
Files.createFile(path)
|
Files.createFile(path)
|
||||||
assertThrows<SecurityManagerException> {
|
assertThrows<SecurityManagerException> { manager.checkResolveModule(path.toUri()) }
|
||||||
manager.checkResolveModule(path.toUri())
|
assertThrows<SecurityManagerException> { manager.checkReadResource(path.toUri()) }
|
||||||
}
|
|
||||||
assertThrows<SecurityManagerException> {
|
|
||||||
manager.checkReadResource(path.toUri())
|
|
||||||
}
|
|
||||||
|
|
||||||
val symlink = rootDir.resolve("qux")
|
val symlink = rootDir.resolve("qux")
|
||||||
Files.createSymbolicLink(symlink, tempDir)
|
Files.createSymbolicLink(symlink, tempDir)
|
||||||
val path2 = symlink.resolve("baz2.pkl")
|
val path2 = symlink.resolve("baz2.pkl")
|
||||||
Files.createFile(path2)
|
Files.createFile(path2)
|
||||||
assertThrows<SecurityManagerException> {
|
assertThrows<SecurityManagerException> { manager.checkResolveModule(path2.toUri()) }
|
||||||
manager.checkResolveModule(path2.toUri())
|
assertThrows<SecurityManagerException> { manager.checkReadResource(path2.toUri()) }
|
||||||
}
|
|
||||||
assertThrows<SecurityManagerException> {
|
|
||||||
manager.checkReadResource(path2.toUri())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `cannot resolve modules and resources outside root dir - files don't exist`() {
|
fun `cannot resolve modules and resources outside root dir - files don't exist`() {
|
||||||
val rootDir = "/foo/bar".toPath()
|
val rootDir = "/foo/bar".toPath()
|
||||||
|
|
||||||
val manager = SecurityManagers.standard(
|
val manager =
|
||||||
listOf(Pattern.compile("file")),
|
SecurityManagers.standard(
|
||||||
listOf(Pattern.compile("file")),
|
listOf(Pattern.compile("file")),
|
||||||
SecurityManagers.defaultTrustLevels,
|
listOf(Pattern.compile("file")),
|
||||||
rootDir
|
SecurityManagers.defaultTrustLevels,
|
||||||
)
|
rootDir
|
||||||
|
)
|
||||||
|
|
||||||
assertThrows<SecurityManagerException> {
|
assertThrows<SecurityManagerException> {
|
||||||
manager.checkResolveModule(Path.of("/foo/baz.pkl").toUri())
|
manager.checkResolveModule(Path.of("/foo/baz.pkl").toUri())
|
||||||
|
|||||||
@@ -1,9 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* 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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.pkl.commons.test.PackageServer
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Disabled
|
import org.junit.jupiter.api.Disabled
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.pkl.commons.test.PackageServer
|
||||||
import org.pkl.core.http.HttpClient
|
import org.pkl.core.http.HttpClient
|
||||||
|
|
||||||
class StackFrameTransformersTest {
|
class StackFrameTransformersTest {
|
||||||
@@ -13,21 +28,13 @@ class StackFrameTransformersTest {
|
|||||||
fun replacePackageUriWithSourceCodeUrl() {
|
fun replacePackageUriWithSourceCodeUrl() {
|
||||||
PackageServer().use { server ->
|
PackageServer().use { server ->
|
||||||
val httpClient = HttpClient.builder().setTestPort(server.port).build()
|
val httpClient = HttpClient.builder().setTestPort(server.port).build()
|
||||||
EvaluatorBuilder.preconfigured()
|
EvaluatorBuilder.preconfigured().setHttpClient(httpClient).build().use {
|
||||||
.setHttpClient(httpClient)
|
val frame =
|
||||||
.build().use {
|
StackFrame("package://localhost:0/birds@0.5.0#/Bird.pkl", null, listOf(), 1, 1, 2, 2)
|
||||||
val frame = StackFrame(
|
val transformed = StackFrameTransformers.replacePackageUriWithSourceCodeUrl.apply(frame)
|
||||||
"package://localhost:0/birds@0.5.0#/Bird.pkl",
|
assertThat(transformed.moduleUri)
|
||||||
null,
|
.isEqualTo("https://example.com/birds/v0.5.0/blob/Bird.pkl#L1-L2")
|
||||||
listOf(),
|
}
|
||||||
1,
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
2)
|
|
||||||
val transformed =
|
|
||||||
StackFrameTransformers.replacePackageUriWithSourceCodeUrl.apply(frame)
|
|
||||||
assertThat(transformed.moduleUri).isEqualTo("https://example.com/birds/v0.5.0/blob/Bird.pkl#L1-L2")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
@@ -37,23 +52,16 @@ class VersionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `parse invalid version`() {
|
fun `parse invalid version`() {
|
||||||
assertThat(Version.parseOrNull("not a version number"))
|
assertThat(Version.parseOrNull("not a version number")).isNull()
|
||||||
.isNull()
|
|
||||||
|
|
||||||
assertThrows<IllegalArgumentException> {
|
assertThrows<IllegalArgumentException> { Version.parse("not a version number") }
|
||||||
Version.parse("not a version number")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `parse too large version`() {
|
fun `parse too large version`() {
|
||||||
assertThrows<IllegalArgumentException> {
|
assertThrows<IllegalArgumentException> { Version.parse("not a version number") }
|
||||||
Version.parse("not a version number")
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThrows<IllegalArgumentException> {
|
assertThrows<IllegalArgumentException> { Version.parse("999999999999999.0.0") }
|
||||||
Version.parse("999999999999999.0.0")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -66,137 +74,80 @@ class VersionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun withMethods() {
|
fun withMethods() {
|
||||||
val version = Version.parse("0.0.0")
|
val version =
|
||||||
.withMajor(1)
|
Version.parse("0.0.0")
|
||||||
.withMinor(2)
|
.withMajor(1)
|
||||||
.withPatch(3)
|
.withMinor(2)
|
||||||
.withPreRelease("rc.1")
|
.withPatch(3)
|
||||||
.withBuild("456.789")
|
.withPreRelease("rc.1")
|
||||||
|
.withBuild("456.789")
|
||||||
|
|
||||||
assertThat(version).isEqualTo(Version.parse("1.2.3-rc.1+456.789"))
|
assertThat(version).isEqualTo(Version.parse("1.2.3-rc.1+456.789"))
|
||||||
|
|
||||||
val version2 = Version.parse("0.0.0")
|
val version2 =
|
||||||
.withBuild("456.789")
|
Version.parse("0.0.0")
|
||||||
.withPreRelease("rc.1")
|
.withBuild("456.789")
|
||||||
.withPatch(3)
|
.withPreRelease("rc.1")
|
||||||
.withMinor(2)
|
.withPatch(3)
|
||||||
.withMajor(1)
|
.withMinor(2)
|
||||||
|
.withMajor(1)
|
||||||
|
|
||||||
assertThat(version2).isEqualTo(version)
|
assertThat(version2).isEqualTo(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `compareTo()`() {
|
fun `compareTo()`() {
|
||||||
assertThat(
|
assertThat(Version(1, 2, 3, null, null).compareTo(Version(1, 2, 3, null, null))).isEqualTo(0)
|
||||||
Version(1, 2, 3, null, null).compareTo(
|
assertThat(Version(1, 2, 3, "SNAPSHOT", null).compareTo(Version(1, 2, 3, "SNAPSHOT", null)))
|
||||||
Version(1, 2, 3, null, null)
|
.isEqualTo(0)
|
||||||
)
|
assertThat(Version(1, 2, 3, "alpha", null).compareTo(Version(1, 2, 3, "alpha", null)))
|
||||||
).isEqualTo(0)
|
.isEqualTo(0)
|
||||||
assertThat(
|
assertThat(Version(1, 2, 3, "alpha", null).compareTo(Version(1, 2, 3, "alpha", "build123")))
|
||||||
Version(1, 2, 3, "SNAPSHOT", null).compareTo(
|
.isEqualTo(0)
|
||||||
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(
|
assertThat(Version(1, 2, 3, null, null).compareTo(Version(2, 2, 3, null, null))).isLessThan(0)
|
||||||
Version(1, 2, 3, null, null).compareTo(
|
assertThat(Version(1, 2, 3, null, null).compareTo(Version(1, 3, 3, null, null))).isLessThan(0)
|
||||||
Version(2, 2, 3, null, null)
|
assertThat(Version(1, 2, 3, null, null).compareTo(Version(1, 2, 4, null, null))).isLessThan(0)
|
||||||
)
|
|
||||||
).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(
|
assertThat(Version(2, 2, 3, null, null).compareTo(Version(1, 2, 3, null, null)))
|
||||||
Version(2, 2, 3, null, null).compareTo(
|
.isGreaterThan(0)
|
||||||
Version(1, 2, 3, null, null)
|
assertThat(Version(1, 3, 3, null, null).compareTo(Version(1, 2, 3, null, null)))
|
||||||
)
|
.isGreaterThan(0)
|
||||||
).isGreaterThan(0)
|
assertThat(Version(1, 2, 4, null, null).compareTo(Version(1, 2, 3, null, null)))
|
||||||
assertThat(
|
.isGreaterThan(0)
|
||||||
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(
|
assertThat(Version(1, 2, 3, "SNAPSHOT", null).compareTo(Version(1, 2, 3, null, null)))
|
||||||
Version(1, 2, 3, "SNAPSHOT", null).compareTo(
|
.isLessThan(0)
|
||||||
Version(1, 2, 3, null, null)
|
assertThat(Version(1, 2, 3, "alpha", null).compareTo(Version(1, 2, 3, "beta", null)))
|
||||||
)
|
.isLessThan(0)
|
||||||
).isLessThan(0)
|
assertThat(Version(1, 2, 3, "alpha", "build123").compareTo(Version(1, 2, 3, "beta", null)))
|
||||||
assertThat(
|
.isLessThan(0)
|
||||||
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(
|
assertThat(Version(1, 2, 3, null, null).compareTo(Version(1, 2, 3, "SNAPSHOT", null)))
|
||||||
Version(1, 2, 3, null, null).compareTo(
|
.isGreaterThan(0)
|
||||||
Version(1, 2, 3, "SNAPSHOT", null)
|
assertThat(Version(1, 2, 3, "beta", null).compareTo(Version(1, 2, 3, "alpha", "build123")))
|
||||||
)
|
.isGreaterThan(0)
|
||||||
).isGreaterThan(0)
|
|
||||||
assertThat(
|
|
||||||
Version(1, 2, 3, "beta", null).compareTo(
|
|
||||||
Version(1, 2, 3, "alpha", "build123")
|
|
||||||
)
|
|
||||||
).isGreaterThan(0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `compare version with too large numeric pre-release identifier`() {
|
fun `compare version with too large numeric pre-release identifier`() {
|
||||||
// error is deferred until compareTo(), but should be good enough
|
// error is deferred until compareTo(), but should be good enough
|
||||||
assertThrows<IllegalArgumentException> {
|
assertThrows<IllegalArgumentException> {
|
||||||
Version(1, 2, 3, "999", null).compareTo(
|
Version(1, 2, 3, "999", null).compareTo(Version(1, 2, 3, "9999999999999999999", null))
|
||||||
Version(1, 2, 3, "9999999999999999999", null)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `equals()`() {
|
fun `equals()`() {
|
||||||
assertThat(Version(1, 2, 3, null, null))
|
assertThat(Version(1, 2, 3, null, null)).isEqualTo(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, "SNAPSHOT", null))
|
assertThat(Version(1, 2, 3, "alpha", null)).isEqualTo(Version(1, 2, 3, "alpha", null))
|
||||||
.isEqualTo(Version(1, 2, 3, "SNAPSHOT", null))
|
assertThat(Version(1, 2, 3, "beta", "build123")).isEqualTo(Version(1, 2, 3, "beta", "build456"))
|
||||||
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))
|
assertThat(Version(1, 3, 3, null, null)).isNotEqualTo(Version(1, 2, 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, 4, null, null))
|
assertThat(Version(1, 2, 3, "SNAPSHOT", null)).isNotEqualTo(Version(1, 2, 3, null, 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, 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
|
@Test
|
||||||
|
|||||||
@@ -1,12 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* 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.core
|
package org.pkl.core
|
||||||
|
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.assertj.core.api.Assertions.assertThatCode
|
import org.assertj.core.api.Assertions.assertThatCode
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.pkl.core.util.IoUtils
|
||||||
import org.snakeyaml.engine.v2.api.Load
|
import org.snakeyaml.engine.v2.api.Load
|
||||||
import org.snakeyaml.engine.v2.api.LoadSettings
|
import org.snakeyaml.engine.v2.api.LoadSettings
|
||||||
import org.pkl.core.util.IoUtils
|
|
||||||
|
|
||||||
class YamlRendererTest {
|
class YamlRendererTest {
|
||||||
@Test
|
@Test
|
||||||
@@ -21,15 +36,17 @@ class YamlRendererTest {
|
|||||||
val expected = IoUtils.readClassPathResourceAsString(javaClass, "rendererTest.yaml")
|
val expected = IoUtils.readClassPathResourceAsString(javaClass, "rendererTest.yaml")
|
||||||
|
|
||||||
assertThat(output.trim()).isEqualTo(expected.trim())
|
assertThat(output.trim()).isEqualTo(expected.trim())
|
||||||
assertThatCode { Load(LoadSettings.builder().build()).loadFromString(output) }.doesNotThrowAnyException()
|
assertThatCode { Load(LoadSettings.builder().build()).loadFromString(output) }
|
||||||
|
.doesNotThrowAnyException()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `render YAML stream`() {
|
fun `render YAML stream`() {
|
||||||
val evaluator = Evaluator.preconfigured()
|
val evaluator = Evaluator.preconfigured()
|
||||||
val module = evaluator.evaluate(
|
val module =
|
||||||
ModuleSource.text(
|
evaluator.evaluate(
|
||||||
"""
|
ModuleSource.text(
|
||||||
|
"""
|
||||||
stream = new Listing {
|
stream = new Listing {
|
||||||
new Dynamic {
|
new Dynamic {
|
||||||
name = "Pigeon"
|
name = "Pigeon"
|
||||||
@@ -48,9 +65,10 @@ class YamlRendererTest {
|
|||||||
"Blue Rock Ltd."
|
"Blue Rock Ltd."
|
||||||
12345
|
12345
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
val writer = StringWriter()
|
val writer = StringWriter()
|
||||||
val renderer = ValueRenderers.yaml(writer, 2, true, true)
|
val renderer = ValueRenderers.yaml(writer, 2, true, true)
|
||||||
@@ -58,8 +76,9 @@ class YamlRendererTest {
|
|||||||
renderer.renderDocument(module.getProperty("stream"))
|
renderer.renderDocument(module.getProperty("stream"))
|
||||||
val output = writer.toString()
|
val output = writer.toString()
|
||||||
|
|
||||||
assertThat(output.trim()).isEqualTo(
|
assertThat(output.trim())
|
||||||
"""
|
.isEqualTo(
|
||||||
|
"""
|
||||||
name: Pigeon
|
name: Pigeon
|
||||||
age: 42
|
age: 42
|
||||||
---
|
---
|
||||||
@@ -72,14 +91,14 @@ class YamlRendererTest {
|
|||||||
three: 3
|
three: 3
|
||||||
--- Blue Rock Ltd.
|
--- Blue Rock Ltd.
|
||||||
--- 12345
|
--- 12345
|
||||||
""".trimIndent()
|
"""
|
||||||
)
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `rendered document ends in newline`() {
|
fun `rendered document ends in newline`() {
|
||||||
val module = Evaluator.preconfigured()
|
val module = Evaluator.preconfigured().evaluate(ModuleSource.text("foo { bar = 0 }"))
|
||||||
.evaluate(ModuleSource.text("foo { bar = 0 }"))
|
|
||||||
|
|
||||||
for (omitNullProperties in listOf(false, true)) {
|
for (omitNullProperties in listOf(false, true)) {
|
||||||
for (isStream in listOf(false, true)) {
|
for (isStream in listOf(false, true)) {
|
||||||
@@ -93,18 +112,20 @@ class YamlRendererTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `render truthy strings, octals and number-like strings`() {
|
fun `render truthy strings, octals and number-like strings`() {
|
||||||
val evaluator = Evaluator.preconfigured()
|
val evaluator = Evaluator.preconfigured()
|
||||||
val module = evaluator.evaluate(
|
val module =
|
||||||
ModuleSource.text(
|
evaluator.evaluate(
|
||||||
"""
|
ModuleSource.text(
|
||||||
|
"""
|
||||||
num1 = "50"
|
num1 = "50"
|
||||||
num2 = "50.123"
|
num2 = "50.123"
|
||||||
`60.123` = "60.123"
|
`60.123` = "60.123"
|
||||||
yes = "yes"
|
yes = "yes"
|
||||||
truth = "true"
|
truth = "true"
|
||||||
octalNumber = "0777"
|
octalNumber = "0777"
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
val writer = StringWriter()
|
val writer = StringWriter()
|
||||||
val renderer = ValueRenderers.yaml(writer, 2, true, false)
|
val renderer = ValueRenderers.yaml(writer, 2, true, false)
|
||||||
@@ -112,15 +133,17 @@ class YamlRendererTest {
|
|||||||
renderer.renderDocument(module)
|
renderer.renderDocument(module)
|
||||||
val output = writer.toString()
|
val output = writer.toString()
|
||||||
|
|
||||||
assertThat(output.trim()).isEqualTo(
|
assertThat(output.trim())
|
||||||
"""
|
.isEqualTo(
|
||||||
|
"""
|
||||||
num1: '50'
|
num1: '50'
|
||||||
num2: '50.123'
|
num2: '50.123'
|
||||||
'60.123': '60.123'
|
'60.123': '60.123'
|
||||||
'yes': 'yes'
|
'yes': 'yes'
|
||||||
truth: 'true'
|
truth: 'true'
|
||||||
octalNumber: '0777'
|
octalNumber: '0777'
|
||||||
""".trimIndent()
|
"""
|
||||||
)
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.ast.builder
|
package org.pkl.core.ast.builder
|
||||||
|
|
||||||
import org.pkl.core.SecurityManagers
|
import java.net.URI
|
||||||
import org.pkl.core.module.ModuleKeys
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.net.URI
|
import org.pkl.core.SecurityManagers
|
||||||
|
import org.pkl.core.module.ModuleKeys
|
||||||
|
|
||||||
class ImportsAndReadsParserTest {
|
class ImportsAndReadsParserTest {
|
||||||
@Test
|
@Test
|
||||||
fun parse() {
|
fun parse() {
|
||||||
val moduleText = """
|
val moduleText =
|
||||||
|
"""
|
||||||
amends "foo.pkl"
|
amends "foo.pkl"
|
||||||
|
|
||||||
import "bar.pkl"
|
import "bar.pkl"
|
||||||
@@ -27,18 +43,23 @@ class ImportsAndReadsParserTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
val moduleKey = ModuleKeys.synthetic(URI("repl:text"), moduleText)
|
val moduleKey = ModuleKeys.synthetic(URI("repl:text"), moduleText)
|
||||||
val imports = ImportsAndReadsParser.parse(moduleKey, moduleKey.resolve(SecurityManagers.defaultManager))
|
val imports =
|
||||||
assertThat(imports?.map { it.first }).hasSameElementsAs(listOf(
|
ImportsAndReadsParser.parse(moduleKey, moduleKey.resolve(SecurityManagers.defaultManager))
|
||||||
"foo.pkl",
|
assertThat(imports?.map { it.first })
|
||||||
"bar.pkl",
|
.hasSameElementsAs(
|
||||||
"bazzy/buz.pkl",
|
listOf(
|
||||||
"qux.pkl",
|
"foo.pkl",
|
||||||
"qux/*.pkl",
|
"bar.pkl",
|
||||||
"/some/dir/chown.txt",
|
"bazzy/buz.pkl",
|
||||||
"/some/dir/chowner.txt",
|
"qux.pkl",
|
||||||
"/some/dir/*.txt"
|
"qux/*.pkl",
|
||||||
))
|
"/some/dir/chown.txt",
|
||||||
|
"/some/dir/chowner.txt",
|
||||||
|
"/some/dir/*.txt"
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.http
|
package org.pkl.core.http
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.junit.jupiter.api.assertDoesNotThrow
|
|
||||||
import org.junit.jupiter.api.assertThrows
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.net.http.HttpRequest
|
import java.net.http.HttpRequest
|
||||||
import java.net.http.HttpResponse
|
import java.net.http.HttpResponse
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.assertDoesNotThrow
|
||||||
|
import org.junit.jupiter.api.assertThrows
|
||||||
|
|
||||||
class DummyHttpClientTest {
|
class DummyHttpClientTest {
|
||||||
@Test
|
@Test
|
||||||
@@ -13,13 +28,9 @@ class DummyHttpClientTest {
|
|||||||
val client = HttpClient.dummyClient()
|
val client = HttpClient.dummyClient()
|
||||||
val request = HttpRequest.newBuilder(URI("https://example.com")).build()
|
val request = HttpRequest.newBuilder(URI("https://example.com")).build()
|
||||||
|
|
||||||
assertThrows<AssertionError> {
|
assertThrows<AssertionError> { client.send(request, HttpResponse.BodyHandlers.discarding()) }
|
||||||
client.send(request, HttpResponse.BodyHandlers.discarding())
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThrows<AssertionError> {
|
assertThrows<AssertionError> { client.send(request, HttpResponse.BodyHandlers.discarding()) }
|
||||||
client.send(request, HttpResponse.BodyHandlers.discarding())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.http
|
package org.pkl.core.http
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.junit.jupiter.api.assertDoesNotThrow
|
|
||||||
import org.junit.jupiter.api.assertThrows
|
|
||||||
import org.junit.jupiter.api.io.TempDir
|
|
||||||
import org.pkl.commons.test.FileTestUtils
|
|
||||||
import org.pkl.core.Release
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.net.http.HttpRequest
|
import java.net.http.HttpRequest
|
||||||
import java.net.http.HttpResponse
|
import java.net.http.HttpResponse
|
||||||
@@ -14,19 +22,25 @@ import java.nio.file.Path
|
|||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import kotlin.io.path.createFile
|
import kotlin.io.path.createFile
|
||||||
import kotlin.io.path.readBytes
|
import kotlin.io.path.readBytes
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.assertDoesNotThrow
|
||||||
|
import org.junit.jupiter.api.assertThrows
|
||||||
|
import org.junit.jupiter.api.io.TempDir
|
||||||
|
import org.pkl.commons.test.FileTestUtils
|
||||||
|
import org.pkl.core.Release
|
||||||
|
|
||||||
class HttpClientTest {
|
class HttpClientTest {
|
||||||
@Test
|
@Test
|
||||||
fun `can build default client`() {
|
fun `can build default client`() {
|
||||||
val client = assertDoesNotThrow {
|
val client = assertDoesNotThrow { HttpClient.builder().build() }
|
||||||
HttpClient.builder().build()
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThat(client).isInstanceOf(RequestRewritingClient::class.java)
|
assertThat(client).isInstanceOf(RequestRewritingClient::class.java)
|
||||||
client as RequestRewritingClient
|
client as RequestRewritingClient
|
||||||
|
|
||||||
val release = Release.current()
|
val release = Release.current()
|
||||||
assertThat(client.userAgent).isEqualTo("Pkl/${release.version()} (${release.os()}; ${release.flavor()})")
|
assertThat(client.userAgent)
|
||||||
|
.isEqualTo("Pkl/${release.version()} (${release.os()}; ${release.flavor()})")
|
||||||
assertThat(client.requestTimeout).isEqualTo(Duration.ofSeconds(60))
|
assertThat(client.requestTimeout).isEqualTo(Duration.ofSeconds(60))
|
||||||
|
|
||||||
assertThat(client.delegate).isInstanceOf(JdkHttpClient::class.java)
|
assertThat(client.delegate).isInstanceOf(JdkHttpClient::class.java)
|
||||||
@@ -37,11 +51,12 @@ class HttpClientTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `can build custom client`() {
|
fun `can build custom client`() {
|
||||||
val client = HttpClient.builder()
|
val client =
|
||||||
.setUserAgent("Agent 1")
|
HttpClient.builder()
|
||||||
.setRequestTimeout(Duration.ofHours(86))
|
.setUserAgent("Agent 1")
|
||||||
.setConnectTimeout(Duration.ofMinutes(42))
|
.setRequestTimeout(Duration.ofHours(86))
|
||||||
.build() as RequestRewritingClient
|
.setConnectTimeout(Duration.ofMinutes(42))
|
||||||
|
.build() as RequestRewritingClient
|
||||||
|
|
||||||
assertThat(client.userAgent).isEqualTo("Agent 1")
|
assertThat(client.userAgent).isEqualTo("Agent 1")
|
||||||
assertThat(client.requestTimeout).isEqualTo(Duration.ofHours(86))
|
assertThat(client.requestTimeout).isEqualTo(Duration.ofHours(86))
|
||||||
@@ -68,27 +83,24 @@ class HttpClientTest {
|
|||||||
fun `certificate file cannot be empty`(@TempDir tempDir: Path) {
|
fun `certificate file cannot be empty`(@TempDir tempDir: Path) {
|
||||||
val file = tempDir.resolve("certs.pem").createFile()
|
val file = tempDir.resolve("certs.pem").createFile()
|
||||||
|
|
||||||
val e = assertThrows<HttpClientInitException> {
|
val e =
|
||||||
HttpClient.builder().addCertificates(file).build()
|
assertThrows<HttpClientInitException> { HttpClient.builder().addCertificates(file).build() }
|
||||||
}
|
|
||||||
|
|
||||||
assertThat(e).hasMessageContaining("empty")
|
assertThat(e).hasMessageContaining("empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `can load built-in certificates`() {
|
fun `can load built-in certificates`() {
|
||||||
assertDoesNotThrow {
|
assertDoesNotThrow { HttpClient.builder().build() }
|
||||||
HttpClient.builder().build()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `can be closed multiple times`() {
|
fun `can be closed multiple times`() {
|
||||||
val client = HttpClient.builder().build()
|
val client = HttpClient.builder().build()
|
||||||
|
|
||||||
assertDoesNotThrow {
|
assertDoesNotThrow {
|
||||||
client.close()
|
client.close()
|
||||||
client.close()
|
client.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,37 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.http
|
package org.pkl.core.http
|
||||||
|
|
||||||
|
import java.net.URI
|
||||||
|
import java.net.http.HttpRequest
|
||||||
|
import java.net.http.HttpResponse.BodyHandlers
|
||||||
|
import java.nio.file.Path
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.assertDoesNotThrow
|
import org.junit.jupiter.api.assertDoesNotThrow
|
||||||
import org.junit.jupiter.api.assertThrows
|
import org.junit.jupiter.api.assertThrows
|
||||||
import org.junit.jupiter.api.io.TempDir
|
import org.junit.jupiter.api.io.TempDir
|
||||||
import org.pkl.commons.createTempFile
|
import org.pkl.commons.createTempFile
|
||||||
import org.pkl.commons.writeString
|
import org.pkl.commons.writeString
|
||||||
import java.net.URI
|
|
||||||
import java.net.http.HttpRequest
|
|
||||||
import java.net.http.HttpResponse.BodyHandlers
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
class LazyHttpClientTest {
|
class LazyHttpClientTest {
|
||||||
@Test
|
@Test
|
||||||
fun `builds underlying client on first send`(@TempDir tempDir: Path) {
|
fun `builds underlying client on first send`(@TempDir tempDir: Path) {
|
||||||
val certFile = tempDir.resolve("cert.pem").apply { writeString("broken") }
|
val certFile = tempDir.resolve("cert.pem").apply { writeString("broken") }
|
||||||
val client = HttpClient.builder()
|
val client = HttpClient.builder().addCertificates(certFile).buildLazily()
|
||||||
.addCertificates(certFile)
|
|
||||||
.buildLazily()
|
|
||||||
val request = HttpRequest.newBuilder(URI("https://example.com")).build()
|
val request = HttpRequest.newBuilder(URI("https://example.com")).build()
|
||||||
|
|
||||||
assertThrows<HttpClientInitException> {
|
assertThrows<HttpClientInitException> { client.send(request, BodyHandlers.discarding()) }
|
||||||
client.send(request, BodyHandlers.discarding())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `does not build underlying client unnecessarily`(@TempDir tempDir: Path) {
|
fun `does not build underlying client unnecessarily`(@TempDir tempDir: Path) {
|
||||||
val certFile = tempDir.createTempFile().apply { writeString("broken") }
|
val certFile = tempDir.createTempFile().apply { writeString("broken") }
|
||||||
val client = HttpClient.builder()
|
val client = HttpClient.builder().addCertificates(certFile).buildLazily()
|
||||||
.addCertificates(certFile)
|
|
||||||
.buildLazily()
|
|
||||||
|
|
||||||
assertDoesNotThrow {
|
assertDoesNotThrow {
|
||||||
client.close()
|
client.close()
|
||||||
client.close()
|
client.close()
|
||||||
|
|||||||
@@ -1,9 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.http
|
package org.pkl.core.http
|
||||||
|
|
||||||
|
import java.net.URI
|
||||||
import org.junit.jupiter.api.Assertions.assertFalse
|
import org.junit.jupiter.api.Assertions.assertFalse
|
||||||
import org.junit.jupiter.api.Assertions.assertTrue
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.net.URI
|
|
||||||
|
|
||||||
@Suppress("HttpUrlsUsage")
|
@Suppress("HttpUrlsUsage")
|
||||||
class NoProxyRuleTest {
|
class NoProxyRuleTest {
|
||||||
@@ -44,7 +59,7 @@ class NoProxyRuleTest {
|
|||||||
assertFalse(noProxyRule.matches(URI("https://ooofoo.com")))
|
assertFalse(noProxyRule.matches(URI("https://ooofoo.com")))
|
||||||
assertFalse(noProxyRule.matches(URI("pkl:foo.com")))
|
assertFalse(noProxyRule.matches(URI("pkl:foo.com")))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `hostname matching, with port`() {
|
fun `hostname matching, with port`() {
|
||||||
val noProxyRule = NoProxyRule("foo.com:5000")
|
val noProxyRule = NoProxyRule("foo.com:5000")
|
||||||
@@ -52,7 +67,7 @@ class NoProxyRuleTest {
|
|||||||
assertFalse(noProxyRule.matches(URI("https://foo.com")))
|
assertFalse(noProxyRule.matches(URI("https://foo.com")))
|
||||||
assertFalse(noProxyRule.matches(URI("https://foo.com:3000")))
|
assertFalse(noProxyRule.matches(URI("https://foo.com:3000")))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `ipv4 address literal matching`() {
|
fun `ipv4 address literal matching`() {
|
||||||
val noProxyRule = NoProxyRule("192.168.1.1")
|
val noProxyRule = NoProxyRule("192.168.1.1")
|
||||||
@@ -95,7 +110,7 @@ class NoProxyRuleTest {
|
|||||||
assertFalse(noProxyRule.matches(URI("https://[::2]")))
|
assertFalse(noProxyRule.matches(URI("https://[::2]")))
|
||||||
assertFalse(noProxyRule.matches(URI("https://[::2]:5000")))
|
assertFalse(noProxyRule.matches(URI("https://[::2]:5000")))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `ipv4 port from protocol`() {
|
fun `ipv4 port from protocol`() {
|
||||||
val noProxyRuleHttp = NoProxyRule("192.168.1.1:80")
|
val noProxyRuleHttp = NoProxyRule("192.168.1.1:80")
|
||||||
@@ -104,7 +119,7 @@ class NoProxyRuleTest {
|
|||||||
assertTrue(noProxyRuleHttp.matches(URI("https://192.168.1.1:80")))
|
assertTrue(noProxyRuleHttp.matches(URI("https://192.168.1.1:80")))
|
||||||
assertFalse(noProxyRuleHttp.matches(URI("https://192.168.1.1")))
|
assertFalse(noProxyRuleHttp.matches(URI("https://192.168.1.1")))
|
||||||
assertFalse(noProxyRuleHttp.matches(URI("https://192.168.1.1:5000")))
|
assertFalse(noProxyRuleHttp.matches(URI("https://192.168.1.1:5000")))
|
||||||
|
|
||||||
val noProxyRuleHttps = NoProxyRule("192.168.1.1:443")
|
val noProxyRuleHttps = NoProxyRule("192.168.1.1:443")
|
||||||
assertTrue(noProxyRuleHttps.matches(URI("https://192.168.1.1")))
|
assertTrue(noProxyRuleHttps.matches(URI("https://192.168.1.1")))
|
||||||
assertTrue(noProxyRuleHttps.matches(URI("http://192.168.1.1:443")))
|
assertTrue(noProxyRuleHttps.matches(URI("http://192.168.1.1:443")))
|
||||||
|
|||||||
@@ -1,12 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.http
|
package org.pkl.core.http
|
||||||
|
|
||||||
import org.pkl.commons.test.FakeHttpResponse
|
|
||||||
import java.net.http.HttpRequest
|
import java.net.http.HttpRequest
|
||||||
import java.net.http.HttpResponse
|
import java.net.http.HttpResponse
|
||||||
|
import org.pkl.commons.test.FakeHttpResponse
|
||||||
|
|
||||||
class RequestCapturingClient : HttpClient {
|
class RequestCapturingClient : HttpClient {
|
||||||
lateinit var request: HttpRequest
|
lateinit var request: HttpRequest
|
||||||
|
|
||||||
override fun <T : Any> send(
|
override fun <T : Any> send(
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
responseBodyHandler: HttpResponse.BodyHandler<T>
|
responseBodyHandler: HttpResponse.BodyHandler<T>
|
||||||
|
|||||||
@@ -1,14 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.http
|
package org.pkl.core.http
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
|
||||||
import org.assertj.core.api.Assertions.assertThatList
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
import java.net.http.HttpClient as JdkHttpClient
|
||||||
import java.net.http.HttpRequest
|
import java.net.http.HttpRequest
|
||||||
import java.net.http.HttpRequest.BodyPublishers
|
import java.net.http.HttpRequest.BodyPublishers
|
||||||
import java.net.http.HttpResponse.BodyHandlers
|
import java.net.http.HttpResponse.BodyHandlers
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.net.http.HttpClient as JdkHttpClient
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.assertj.core.api.Assertions.assertThatList
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
class RequestRewritingClientTest {
|
class RequestRewritingClientTest {
|
||||||
private val captured = RequestCapturingClient()
|
private val captured = RequestCapturingClient()
|
||||||
@@ -19,17 +34,18 @@ class RequestRewritingClientTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `fills in missing User-Agent header`() {
|
fun `fills in missing User-Agent header`() {
|
||||||
client.send(exampleRequest, BodyHandlers.discarding())
|
client.send(exampleRequest, BodyHandlers.discarding())
|
||||||
|
|
||||||
assertThatList(captured.request.headers().allValues("User-Agent")).containsOnly("Pkl")
|
assertThatList(captured.request.headers().allValues("User-Agent")).containsOnly("Pkl")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `overrides existing User-Agent headers`() {
|
fun `overrides existing User-Agent headers`() {
|
||||||
val request = HttpRequest.newBuilder(exampleUri)
|
val request =
|
||||||
.header("User-Agent", "Agent 1")
|
HttpRequest.newBuilder(exampleUri)
|
||||||
.header("User-Agent", "Agent 2")
|
.header("User-Agent", "Agent 1")
|
||||||
.build()
|
.header("User-Agent", "Agent 2")
|
||||||
|
.build()
|
||||||
|
|
||||||
client.send(request, BodyHandlers.discarding())
|
client.send(request, BodyHandlers.discarding())
|
||||||
|
|
||||||
assertThatList(captured.request.headers().allValues("User-Agent")).containsOnly("Pkl")
|
assertThatList(captured.request.headers().allValues("User-Agent")).containsOnly("Pkl")
|
||||||
@@ -38,16 +54,14 @@ class RequestRewritingClientTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `fills in missing request timeout`() {
|
fun `fills in missing request timeout`() {
|
||||||
client.send(exampleRequest, BodyHandlers.discarding())
|
client.send(exampleRequest, BodyHandlers.discarding())
|
||||||
|
|
||||||
assertThat(captured.request.timeout()).hasValue(Duration.ofSeconds(42))
|
assertThat(captured.request.timeout()).hasValue(Duration.ofSeconds(42))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `leaves existing request timeout intact`() {
|
fun `leaves existing request timeout intact`() {
|
||||||
val request = HttpRequest.newBuilder(exampleUri)
|
val request = HttpRequest.newBuilder(exampleUri).timeout(Duration.ofMinutes(33)).build()
|
||||||
.timeout(Duration.ofMinutes(33))
|
|
||||||
.build()
|
|
||||||
|
|
||||||
client.send(request, BodyHandlers.discarding())
|
client.send(request, BodyHandlers.discarding())
|
||||||
|
|
||||||
assertThat(captured.request.timeout()).hasValue(Duration.ofMinutes(33))
|
assertThat(captured.request.timeout()).hasValue(Duration.ofMinutes(33))
|
||||||
@@ -62,12 +76,10 @@ class RequestRewritingClientTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `leaves existing HTTP version intact`() {
|
fun `leaves existing HTTP version intact`() {
|
||||||
val request = HttpRequest.newBuilder(exampleUri)
|
val request = HttpRequest.newBuilder(exampleUri).version(JdkHttpClient.Version.HTTP_1_1).build()
|
||||||
.version(JdkHttpClient.Version.HTTP_1_1)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
client.send(request, BodyHandlers.discarding())
|
client.send(request, BodyHandlers.discarding())
|
||||||
|
|
||||||
assertThat(captured.request.version()).hasValue(JdkHttpClient.Version.HTTP_1_1)
|
assertThat(captured.request.version()).hasValue(JdkHttpClient.Version.HTTP_1_1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,30 +91,26 @@ class RequestRewritingClientTest {
|
|||||||
|
|
||||||
assertThat(captured.request.method()).isEqualTo("GET")
|
assertThat(captured.request.method()).isEqualTo("GET")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `leaves explicit method intact`() {
|
fun `leaves explicit method intact`() {
|
||||||
val request = HttpRequest.newBuilder(exampleUri)
|
val request = HttpRequest.newBuilder(exampleUri).DELETE().build()
|
||||||
.DELETE()
|
|
||||||
.build()
|
|
||||||
|
|
||||||
client.send(request, BodyHandlers.discarding())
|
client.send(request, BodyHandlers.discarding())
|
||||||
|
|
||||||
assertThat(captured.request.method()).isEqualTo("DELETE")
|
assertThat(captured.request.method()).isEqualTo("DELETE")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `leaves body publisher intact`() {
|
fun `leaves body publisher intact`() {
|
||||||
val publisher = BodyPublishers.ofString("body")
|
val publisher = BodyPublishers.ofString("body")
|
||||||
val request = HttpRequest.newBuilder(exampleUri)
|
val request = HttpRequest.newBuilder(exampleUri).PUT(publisher).build()
|
||||||
.PUT(publisher)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
client.send(request, BodyHandlers.discarding())
|
client.send(request, BodyHandlers.discarding())
|
||||||
|
|
||||||
assertThat(captured.request.bodyPublisher().get()).isSameAs(publisher)
|
assertThat(captured.request.bodyPublisher().get()).isSameAs(publisher)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `rewrites port 0 if test port is set`() {
|
fun `rewrites port 0 if test port is set`() {
|
||||||
val captured = RequestCapturingClient()
|
val captured = RequestCapturingClient()
|
||||||
@@ -113,15 +121,13 @@ class RequestRewritingClientTest {
|
|||||||
|
|
||||||
assertThat(captured.request.uri().port).isEqualTo(5000)
|
assertThat(captured.request.uri().port).isEqualTo(5000)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `leaves port 0 intact if no test port is set`() {
|
fun `leaves port 0 intact if no test port is set`() {
|
||||||
val request = HttpRequest.newBuilder(URI("https://example.com:0")).build()
|
val request = HttpRequest.newBuilder(URI("https://example.com:0")).build()
|
||||||
|
|
||||||
client.send(request, BodyHandlers.discarding())
|
client.send(request, BodyHandlers.discarding())
|
||||||
|
|
||||||
assertThat(captured.request.uri().port).isEqualTo(0)
|
assertThat(captured.request.uri().port).isEqualTo(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.module
|
package org.pkl.core.module
|
||||||
|
|
||||||
|
import java.net.URI
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.createDirectories
|
||||||
|
import kotlin.io.path.outputStream
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.io.TempDir
|
import org.junit.jupiter.api.io.TempDir
|
||||||
@@ -7,10 +26,6 @@ import org.pkl.commons.createParentDirectories
|
|||||||
import org.pkl.commons.toPath
|
import org.pkl.commons.toPath
|
||||||
import org.pkl.commons.writeString
|
import org.pkl.commons.writeString
|
||||||
import org.pkl.core.SecurityManagers
|
import org.pkl.core.SecurityManagers
|
||||||
import java.net.URI
|
|
||||||
import java.nio.file.Path
|
|
||||||
import kotlin.io.path.createDirectories
|
|
||||||
import kotlin.io.path.outputStream
|
|
||||||
|
|
||||||
class ModuleKeyFactoriesTest {
|
class ModuleKeyFactoriesTest {
|
||||||
@Test
|
@Test
|
||||||
@@ -78,9 +93,7 @@ class ModuleKeyFactoriesTest {
|
|||||||
fun `module path - jar files`(@TempDir tempDir: Path) {
|
fun `module path - jar files`(@TempDir tempDir: Path) {
|
||||||
val jarFile = tempDir.resolve("test.jar")
|
val jarFile = tempDir.resolve("test.jar")
|
||||||
jarFile.outputStream().use { outStream ->
|
jarFile.outputStream().use { outStream ->
|
||||||
javaClass.getResourceAsStream("test.jar")!!.use { inStream ->
|
javaClass.getResourceAsStream("test.jar")!!.use { inStream -> inStream.copyTo(outStream) }
|
||||||
inStream.copyTo(outStream)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val factory = ModuleKeyFactories.modulePath(ModulePathResolver(listOf(jarFile)))
|
val factory = ModuleKeyFactories.modulePath(ModulePathResolver(listOf(jarFile)))
|
||||||
|
|||||||
@@ -1,19 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.module
|
package org.pkl.core.module
|
||||||
|
|
||||||
import org.pkl.commons.createParentDirectories
|
|
||||||
import org.pkl.commons.toPath
|
|
||||||
import org.pkl.commons.writeString
|
|
||||||
import org.pkl.core.SecurityManagers
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.junit.jupiter.api.assertThrows
|
|
||||||
import org.junit.jupiter.api.io.TempDir
|
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.net.MalformedURLException
|
import java.net.MalformedURLException
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.net.URISyntaxException
|
import java.net.URISyntaxException
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import kotlin.io.path.createFile
|
import kotlin.io.path.createFile
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.assertThrows
|
||||||
|
import org.junit.jupiter.api.io.TempDir
|
||||||
|
import org.pkl.commons.createParentDirectories
|
||||||
|
import org.pkl.commons.toPath
|
||||||
|
import org.pkl.commons.writeString
|
||||||
|
import org.pkl.core.SecurityManagers
|
||||||
|
|
||||||
class ModuleKeysTest {
|
class ModuleKeysTest {
|
||||||
private val securityManager = SecurityManagers.defaultManager
|
private val securityManager = SecurityManagers.defaultManager
|
||||||
@@ -46,9 +61,7 @@ class ModuleKeysTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `standard library - wrong scheme`() {
|
fun `standard library - wrong scheme`() {
|
||||||
assertThrows<IllegalArgumentException> {
|
assertThrows<IllegalArgumentException> { ModuleKeys.standardLibrary(URI("other:base")) }
|
||||||
ModuleKeys.standardLibrary(URI("other:base"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -97,18 +110,18 @@ class ModuleKeysTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `class path - module not found`() {
|
fun `class path - module not found`() {
|
||||||
val key = ModuleKeys.classPath(URI("modulepath:/non/existing"), ModuleKeysTest::class.java.classLoader)
|
val key =
|
||||||
|
ModuleKeys.classPath(URI("modulepath:/non/existing"), ModuleKeysTest::class.java.classLoader)
|
||||||
|
|
||||||
assertThrows<FileNotFoundException> {
|
assertThrows<FileNotFoundException> { key.resolve(SecurityManagers.defaultManager) }
|
||||||
key.resolve(SecurityManagers.defaultManager)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `class path - missing leading slash`() {
|
fun `class path - missing leading slash`() {
|
||||||
val e = assertThrows<IllegalArgumentException> {
|
val e =
|
||||||
ModuleKeys.classPath(URI("modulepath:foo/bar.pkl"), ModuleKeysTest::class.java.classLoader)
|
assertThrows<IllegalArgumentException> {
|
||||||
}
|
ModuleKeys.classPath(URI("modulepath:foo/bar.pkl"), ModuleKeysTest::class.java.classLoader)
|
||||||
|
}
|
||||||
assertThat(e).hasMessageContaining("`/`")
|
assertThat(e).hasMessageContaining("`/`")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,10 +140,8 @@ class ModuleKeysTest {
|
|||||||
|
|
||||||
val resolvedKey = key.resolve(securityManager)
|
val resolvedKey = key.resolve(securityManager)
|
||||||
|
|
||||||
assertThat(resolvedKey.uri.scheme)
|
assertThat(resolvedKey.uri.scheme).isEqualTo("file")
|
||||||
.isEqualTo("file")
|
assertThat(resolvedKey.loadSource()).isEqualTo("age = 40")
|
||||||
assertThat(resolvedKey.loadSource())
|
|
||||||
.isEqualTo("age = 40")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -144,61 +155,55 @@ class ModuleKeysTest {
|
|||||||
fun `module path - module not found`() {
|
fun `module path - module not found`() {
|
||||||
val key = ModuleKeys.modulePath(URI("modulepath:/non/existing"), ModulePathResolver(listOf()))
|
val key = ModuleKeys.modulePath(URI("modulepath:/non/existing"), ModulePathResolver(listOf()))
|
||||||
|
|
||||||
assertThrows<FileNotFoundException> {
|
assertThrows<FileNotFoundException> { key.resolve(SecurityManagers.defaultManager) }
|
||||||
key.resolve(SecurityManagers.defaultManager)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `module path - missing leading slash`() {
|
fun `module path - missing leading slash`() {
|
||||||
val e = assertThrows<IllegalArgumentException> {
|
val e =
|
||||||
ModuleKeys.modulePath(URI("modulepath:foo/bar.pkl"), ModulePathResolver(listOf()))
|
assertThrows<IllegalArgumentException> {
|
||||||
}
|
ModuleKeys.modulePath(URI("modulepath:foo/bar.pkl"), ModulePathResolver(listOf()))
|
||||||
|
}
|
||||||
assertThat(e).hasMessageContaining("`/`")
|
assertThat(e).hasMessageContaining("`/`")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `package - no version`() {
|
fun `package - no version`() {
|
||||||
val e = assertThrows<URISyntaxException> {
|
val e =
|
||||||
ModuleKeys.pkg(URI("package://localhost:0/birds#/Bird.pkl"))
|
assertThrows<URISyntaxException> {
|
||||||
}
|
ModuleKeys.pkg(URI("package://localhost:0/birds#/Bird.pkl"))
|
||||||
|
}
|
||||||
assertThat(e).hasMessageContaining("A package URI must have its path suffixed by its version")
|
assertThat(e).hasMessageContaining("A package URI must have its path suffixed by its version")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `package - invalid semver`() {
|
fun `package - invalid semver`() {
|
||||||
val e = assertThrows<URISyntaxException> {
|
val e =
|
||||||
ModuleKeys.pkg(URI("package://localhost:0/birds@notAVersion#/Bird.pkl"))
|
assertThrows<URISyntaxException> {
|
||||||
}
|
ModuleKeys.pkg(URI("package://localhost:0/birds@notAVersion#/Bird.pkl"))
|
||||||
|
}
|
||||||
assertThat(e).hasMessageContaining("`notAVersion` could not be parsed")
|
assertThat(e).hasMessageContaining("`notAVersion` could not be parsed")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `package - missing leading slash`() {
|
fun `package - missing leading slash`() {
|
||||||
val e = assertThrows<URISyntaxException> {
|
val e = assertThrows<URISyntaxException> { ModuleKeys.pkg(URI("package:invalid")) }
|
||||||
ModuleKeys.pkg(URI("package:invalid"))
|
assertThat(e)
|
||||||
}
|
.hasMessageContaining("Module URI `package:invalid` is missing a `/` after `package:`")
|
||||||
assertThat(e).hasMessageContaining("Module URI `package:invalid` is missing a `/` after `package:`")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `package - missing authority`() {
|
fun `package - missing authority`() {
|
||||||
val e = assertThrows<URISyntaxException> {
|
val e = assertThrows<URISyntaxException> { ModuleKeys.pkg(URI("package:/not/a/valid/path")) }
|
||||||
ModuleKeys.pkg(URI("package:/not/a/valid/path"))
|
|
||||||
}
|
|
||||||
assertThat(e).hasMessageContaining("Package URIs must have an authority component")
|
assertThat(e).hasMessageContaining("Package URIs must have an authority component")
|
||||||
|
|
||||||
val e2 = assertThrows<URISyntaxException> {
|
val e2 = assertThrows<URISyntaxException> { ModuleKeys.pkg(URI("package:///not/a/valid/path")) }
|
||||||
ModuleKeys.pkg(URI("package:///not/a/valid/path"))
|
|
||||||
}
|
|
||||||
assertThat(e2).hasMessageContaining("Package URIs must have an authority component")
|
assertThat(e2).hasMessageContaining("Package URIs must have an authority component")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `package - missing path`() {
|
fun `package - missing path`() {
|
||||||
val e = assertThrows<URISyntaxException> {
|
val e = assertThrows<URISyntaxException> { ModuleKeys.pkg(URI("package://example.com")) }
|
||||||
ModuleKeys.pkg(URI("package://example.com"))
|
|
||||||
}
|
|
||||||
assertThat(e).hasMessageContaining("Package URIs must have a path component")
|
assertThat(e).hasMessageContaining("Package URIs must have a path component")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,11 +239,8 @@ class ModuleKeysTest {
|
|||||||
val uri = URI("repl:foo")
|
val uri = URI("repl:foo")
|
||||||
val key = ModuleKeys.genericUrl(uri)
|
val key = ModuleKeys.genericUrl(uri)
|
||||||
|
|
||||||
val e = assertThrows<MalformedURLException> {
|
val e = assertThrows<MalformedURLException> { key.resolve(securityManager) }
|
||||||
key.resolve(securityManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThat(e)
|
assertThat(e).hasMessage("unknown protocol: repl")
|
||||||
.hasMessage("unknown protocol: repl")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.core.module
|
package org.pkl.core.module
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThatCode
|
import org.assertj.core.api.Assertions.assertThatCode
|
||||||
|
|||||||
@@ -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.core.module
|
package org.pkl.core.module
|
||||||
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
@@ -26,9 +41,7 @@ class ResolvedModuleKeysTest {
|
|||||||
fun `url()`(@TempDir tempDir: Path) {
|
fun `url()`(@TempDir tempDir: Path) {
|
||||||
val path = tempDir.createTempFile().writeString("x = 1")
|
val path = tempDir.createTempFile().writeString("x = 1")
|
||||||
val resolvedUri = URI("test:resolved.uri")
|
val resolvedUri = URI("test:resolved.uri")
|
||||||
val resolved = ResolvedModuleKeys.url(
|
val resolved = ResolvedModuleKeys.url(module, resolvedUri, path.toUri().toURL())
|
||||||
module, resolvedUri, path.toUri().toURL()
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(resolved.original).isSameAs(module)
|
assertThat(resolved.original).isSameAs(module)
|
||||||
assertThat(resolved.uri).isEqualTo(resolvedUri)
|
assertThat(resolved.uri).isEqualTo(resolvedUri)
|
||||||
|
|||||||
@@ -1,28 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.module
|
package org.pkl.core.module
|
||||||
|
|
||||||
|
import java.net.URI
|
||||||
|
import org.assertj.core.api.Assertions
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
import org.pkl.core.Evaluator
|
import org.pkl.core.Evaluator
|
||||||
import org.pkl.core.ModuleSource
|
import org.pkl.core.ModuleSource
|
||||||
import org.pkl.core.PClassInfo
|
import org.pkl.core.PClassInfo
|
||||||
import org.pkl.core.PModule
|
import org.pkl.core.PModule
|
||||||
import org.assertj.core.api.Assertions
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import java.net.URI
|
|
||||||
|
|
||||||
class ServiceProviderTest {
|
class ServiceProviderTest {
|
||||||
@Test
|
@Test
|
||||||
fun `load module through service provider`() {
|
fun `load module through service provider`() {
|
||||||
val module = Evaluator
|
val module = Evaluator.preconfigured().evaluate(ModuleSource.uri(URI("test:foo")))
|
||||||
.preconfigured()
|
|
||||||
.evaluate(ModuleSource.uri(URI("test:foo")))
|
|
||||||
|
|
||||||
val uri = URI("modulepath:/org/pkl/core/module/testFactoryTest.pkl")
|
val uri = URI("modulepath:/org/pkl/core/module/testFactoryTest.pkl")
|
||||||
Assertions.assertThat(module).isEqualTo(
|
Assertions.assertThat(module)
|
||||||
PModule(
|
.isEqualTo(
|
||||||
uri,
|
PModule(
|
||||||
"testFactoryTest",
|
uri,
|
||||||
PClassInfo.forModuleClass("testFactoryTest", uri),
|
"testFactoryTest",
|
||||||
mapOf("name" to "Pigeon", "age" to 40L)
|
PClassInfo.forModuleClass("testFactoryTest", uri),
|
||||||
|
mapOf("name" to "Pigeon", "age" to 40L)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.core.module
|
package org.pkl.core.module
|
||||||
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|||||||
@@ -1,33 +1,54 @@
|
|||||||
package org.pkl.core.packages;
|
/**
|
||||||
|
* 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.core.packages
|
||||||
|
|
||||||
import org.pkl.core.Version
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.pkl.core.Version
|
||||||
|
|
||||||
class DependencyMetadataTest {
|
class DependencyMetadataTest {
|
||||||
private val dependencyMetadata = DependencyMetadata(
|
private val dependencyMetadata =
|
||||||
"my-proj-name",
|
DependencyMetadata(
|
||||||
PackageUri("package://example.com/my-proj-name@0.10.0"),
|
"my-proj-name",
|
||||||
Version.parse("0.10.0"),
|
PackageUri("package://example.com/my-proj-name@0.10.0"),
|
||||||
URI("https://example.com/foo/bar@0.5.3.zip"),
|
Version.parse("0.10.0"),
|
||||||
Checksums("abc123"),
|
URI("https://example.com/foo/bar@0.5.3.zip"),
|
||||||
mapOf(
|
Checksums("abc123"),
|
||||||
"foo" to Dependency.RemoteDependency(PackageUri("package://example.com/foo@0.5.3"), Checksums("abc123")),
|
mapOf(
|
||||||
),
|
"foo" to
|
||||||
"https://example.com/my/source/0.5.3/blob%{path}#L%{line}-L%{endLine}",
|
Dependency.RemoteDependency(
|
||||||
URI("https://example.com/my/source"),
|
PackageUri("package://example.com/foo@0.5.3"),
|
||||||
URI("https://example.com/my/docs"),
|
Checksums("abc123")
|
||||||
"MIT",
|
),
|
||||||
"The MIT License, you know it",
|
),
|
||||||
listOf("birdy@bird.com"),
|
"https://example.com/my/source/0.5.3/blob%{path}#L%{line}-L%{endLine}",
|
||||||
URI("https://example.com/issues"),
|
URI("https://example.com/my/source"),
|
||||||
"Some package description"
|
URI("https://example.com/my/docs"),
|
||||||
)
|
"MIT",
|
||||||
|
"The MIT License, you know it",
|
||||||
|
listOf("birdy@bird.com"),
|
||||||
|
URI("https://example.com/issues"),
|
||||||
|
"Some package description"
|
||||||
|
)
|
||||||
|
|
||||||
private val dependencyMetadataStr = """
|
private val dependencyMetadataStr =
|
||||||
|
"""
|
||||||
{
|
{
|
||||||
"name": "my-proj-name",
|
"name": "my-proj-name",
|
||||||
"packageUri": "package://example.com/my-proj-name@0.10.0",
|
"packageUri": "package://example.com/my-proj-name@0.10.0",
|
||||||
@@ -55,7 +76,8 @@ class DependencyMetadataTest {
|
|||||||
"issueTracker": "https://example.com/issues",
|
"issueTracker": "https://example.com/issues",
|
||||||
"description": "Some package description"
|
"description": "Some package description"
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parse() {
|
fun parse() {
|
||||||
@@ -64,10 +86,11 @@ class DependencyMetadataTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun writeTo(){
|
fun writeTo() {
|
||||||
val str = ByteArrayOutputStream()
|
val str =
|
||||||
.apply { dependencyMetadata.writeTo(this) }
|
ByteArrayOutputStream()
|
||||||
.toString(StandardCharsets.UTF_8)
|
.apply { dependencyMetadata.writeTo(this) }
|
||||||
|
.toString(StandardCharsets.UTF_8)
|
||||||
assertThat(str).isEqualTo(dependencyMetadataStr)
|
assertThat(str).isEqualTo(dependencyMetadataStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.packages
|
package org.pkl.core.packages
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException
|
||||||
|
import java.io.IOException
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
import kotlin.io.path.exists
|
||||||
|
import kotlin.io.path.readBytes
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.assertj.core.api.Assertions.assertThatCode
|
import org.assertj.core.api.Assertions.assertThatCode
|
||||||
import org.junit.jupiter.api.AfterAll
|
import org.junit.jupiter.api.AfterAll
|
||||||
@@ -11,31 +31,27 @@ import org.pkl.commons.readString
|
|||||||
import org.pkl.commons.test.FileTestUtils
|
import org.pkl.commons.test.FileTestUtils
|
||||||
import org.pkl.commons.test.PackageServer
|
import org.pkl.commons.test.PackageServer
|
||||||
import org.pkl.commons.test.listFilesRecursively
|
import org.pkl.commons.test.listFilesRecursively
|
||||||
import org.pkl.core.http.HttpClient
|
|
||||||
import org.pkl.core.SecurityManagers
|
import org.pkl.core.SecurityManagers
|
||||||
|
import org.pkl.core.http.HttpClient
|
||||||
import org.pkl.core.module.PathElement
|
import org.pkl.core.module.PathElement
|
||||||
import java.io.FileNotFoundException
|
|
||||||
import java.io.IOException
|
|
||||||
import java.nio.charset.StandardCharsets
|
|
||||||
import kotlin.io.path.exists
|
|
||||||
import kotlin.io.path.readBytes
|
|
||||||
|
|
||||||
class PackageResolversTest {
|
class PackageResolversTest {
|
||||||
abstract class AbstractPackageResolverTest {
|
abstract class AbstractPackageResolverTest {
|
||||||
|
|
||||||
abstract val resolver: PackageResolver
|
abstract val resolver: PackageResolver
|
||||||
|
|
||||||
private val packageRoot = FileTestUtils.rootProjectDir.resolve("pkl-commons-test/src/main/files/packages")
|
private val packageRoot =
|
||||||
|
FileTestUtils.rootProjectDir.resolve("pkl-commons-test/src/main/files/packages")
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val packageServer = PackageServer()
|
private val packageServer = PackageServer()
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@AfterAll
|
@AfterAll
|
||||||
fun afterAll() {
|
fun afterAll() {
|
||||||
packageServer.close()
|
packageServer.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
val httpClient: HttpClient by lazy {
|
val httpClient: HttpClient by lazy {
|
||||||
HttpClient.builder()
|
HttpClient.builder()
|
||||||
.addCertificates(FileTestUtils.selfSignedCertificate)
|
.addCertificates(FileTestUtils.selfSignedCertificate)
|
||||||
@@ -46,105 +62,107 @@ class PackageResolversTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get module bytes`() {
|
fun `get module bytes`() {
|
||||||
val expectedBirdModule = packageRoot.resolve("birds@0.5.0/package/Bird.pkl").readString(StandardCharsets.UTF_8)
|
val expectedBirdModule =
|
||||||
|
packageRoot.resolve("birds@0.5.0/package/Bird.pkl").readString(StandardCharsets.UTF_8)
|
||||||
val assetUri = PackageAssetUri("package://localhost:0/birds@0.5.0#/Bird.pkl")
|
val assetUri = PackageAssetUri("package://localhost:0/birds@0.5.0#/Bird.pkl")
|
||||||
val birdModule = resolver
|
val birdModule = resolver.getBytes(assetUri, false, null).toString(StandardCharsets.UTF_8)
|
||||||
.getBytes(assetUri, false, null)
|
|
||||||
.toString(StandardCharsets.UTF_8)
|
|
||||||
assertThat(birdModule).isEqualTo(expectedBirdModule)
|
assertThat(birdModule).isEqualTo(expectedBirdModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get directory`() {
|
fun `get directory`() {
|
||||||
val assetUri = PackageAssetUri("package://localhost:0/birds@0.5.0#/")
|
val assetUri = PackageAssetUri("package://localhost:0/birds@0.5.0#/")
|
||||||
val err = assertThrows<IOException> {
|
val err =
|
||||||
resolver
|
assertThrows<IOException> {
|
||||||
.getBytes(assetUri, false, null)
|
resolver.getBytes(assetUri, false, null).toString(StandardCharsets.UTF_8)
|
||||||
.toString(StandardCharsets.UTF_8)
|
}
|
||||||
}
|
|
||||||
assertThat(err).hasMessage("Is a directory")
|
assertThat(err).hasMessage("Is a directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get directory, allowing directory reads`() {
|
fun `get directory, allowing directory reads`() {
|
||||||
val assetUri = PackageAssetUri("package://localhost:0/birds@0.5.0#/")
|
val assetUri = PackageAssetUri("package://localhost:0/birds@0.5.0#/")
|
||||||
val bytes = resolver
|
val bytes = resolver.getBytes(assetUri, true, null).toString(StandardCharsets.UTF_8)
|
||||||
.getBytes(assetUri, true, null)
|
assertThat(bytes)
|
||||||
.toString(StandardCharsets.UTF_8)
|
.isEqualTo(
|
||||||
assertThat(bytes).isEqualTo("""
|
"""
|
||||||
Bird.pkl
|
Bird.pkl
|
||||||
allFruit.pkl
|
allFruit.pkl
|
||||||
catalog
|
catalog
|
||||||
catalog.pkl
|
catalog.pkl
|
||||||
some
|
some
|
||||||
|
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get module bytes resolving path`() {
|
fun `get module bytes resolving path`() {
|
||||||
val expectedBirdModule = packageRoot.resolve("birds@0.5.0/package/Bird.pkl").readString(StandardCharsets.UTF_8)
|
val expectedBirdModule =
|
||||||
|
packageRoot.resolve("birds@0.5.0/package/Bird.pkl").readString(StandardCharsets.UTF_8)
|
||||||
val assetUri = PackageAssetUri("package://localhost:0/birds@0.5.0#/foo/../Bird.pkl")
|
val assetUri = PackageAssetUri("package://localhost:0/birds@0.5.0#/foo/../Bird.pkl")
|
||||||
val birdModule = resolver
|
val birdModule = resolver.getBytes(assetUri, false, null).toString(StandardCharsets.UTF_8)
|
||||||
.getBytes(assetUri, false, null)
|
|
||||||
.toString(StandardCharsets.UTF_8)
|
|
||||||
assertThat(birdModule).isEqualTo(expectedBirdModule)
|
assertThat(birdModule).isEqualTo(expectedBirdModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `list path elements at root`() {
|
fun `list path elements at root`() {
|
||||||
// cast to set to avoid sort issues
|
// cast to set to avoid sort issues
|
||||||
val elements = resolver
|
val elements =
|
||||||
.listElements(PackageAssetUri("package://localhost:0/birds@0.5.0#/"), null)
|
resolver.listElements(PackageAssetUri("package://localhost:0/birds@0.5.0#/"), null).toSet()
|
||||||
.toSet()
|
assertThat(elements)
|
||||||
assertThat(elements).isEqualTo(
|
.isEqualTo(
|
||||||
setOf(
|
setOf(
|
||||||
PathElement("some", true),
|
PathElement("some", true),
|
||||||
PathElement("catalog", true),
|
PathElement("catalog", true),
|
||||||
PathElement("Bird.pkl", false),
|
PathElement("Bird.pkl", false),
|
||||||
PathElement("allFruit.pkl", false),
|
PathElement("allFruit.pkl", false),
|
||||||
PathElement("catalog.pkl", false)
|
PathElement("catalog.pkl", false)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get multiple assets`() {
|
fun `get multiple assets`() {
|
||||||
val bird = resolver.getBytes(
|
val bird =
|
||||||
PackageAssetUri("package://localhost:0/birds@0.5.0#/Bird.pkl"),
|
resolver.getBytes(
|
||||||
false,
|
PackageAssetUri("package://localhost:0/birds@0.5.0#/Bird.pkl"),
|
||||||
null
|
false,
|
||||||
)
|
null
|
||||||
val swallow = resolver.getBytes(
|
)
|
||||||
PackageAssetUri("package://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"),
|
val swallow =
|
||||||
false,
|
resolver.getBytes(
|
||||||
null
|
PackageAssetUri("package://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"),
|
||||||
)
|
false,
|
||||||
|
null
|
||||||
|
)
|
||||||
assertThat(bird).isEqualTo(packageRoot.resolve("birds@0.5.0/package/Bird.pkl").readBytes())
|
assertThat(bird).isEqualTo(packageRoot.resolve("birds@0.5.0/package/Bird.pkl").readBytes())
|
||||||
assertThat(swallow).isEqualTo(packageRoot.resolve("birds@0.5.0/package/catalog/Swallow.pkl").readBytes())
|
assertThat(swallow)
|
||||||
|
.isEqualTo(packageRoot.resolve("birds@0.5.0/package/catalog/Swallow.pkl").readBytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `list path elements in nested directory`() {
|
fun `list path elements in nested directory`() {
|
||||||
// cast to set to avoid sort issues
|
// cast to set to avoid sort issues
|
||||||
val elements = resolver.listElements(PackageAssetUri("package://localhost:0/birds@0.5.0#/catalog/"), null).toSet()
|
val elements =
|
||||||
assertThat(elements).isEqualTo(
|
resolver
|
||||||
setOf(
|
.listElements(PackageAssetUri("package://localhost:0/birds@0.5.0#/catalog/"), null)
|
||||||
PathElement("Ostritch.pkl", false),
|
.toSet()
|
||||||
PathElement("Swallow.pkl", false),
|
assertThat(elements)
|
||||||
|
.isEqualTo(
|
||||||
|
setOf(
|
||||||
|
PathElement("Ostritch.pkl", false),
|
||||||
|
PathElement("Swallow.pkl", false),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `getBytes() throws FileNotFound if package exists but path does not`() {
|
fun `getBytes() throws FileNotFound if package exists but path does not`() {
|
||||||
assertThrows<FileNotFoundException> {
|
assertThrows<FileNotFoundException> {
|
||||||
resolver
|
resolver
|
||||||
.getBytes(
|
.getBytes(PackageAssetUri("package://localhost:0/birds@0.5.0#/Horse.pkl"), false, null)
|
||||||
PackageAssetUri("package://localhost:0/birds@0.5.0#/Horse.pkl"),
|
|
||||||
false,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
.toString(StandardCharsets.UTF_8)
|
.toString(StandardCharsets.UTF_8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,7 +174,8 @@ class PackageResolversTest {
|
|||||||
.getBytes(
|
.getBytes(
|
||||||
PackageAssetUri("package://localhost:0/not-a-package@0.5.0#/Horse.pkl"),
|
PackageAssetUri("package://localhost:0/not-a-package@0.5.0#/Horse.pkl"),
|
||||||
false,
|
false,
|
||||||
null)
|
null
|
||||||
|
)
|
||||||
.toString(StandardCharsets.UTF_8)
|
.toString(StandardCharsets.UTF_8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,26 +183,35 @@ class PackageResolversTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `requires package zip to be an HTTPS URI`() {
|
fun `requires package zip to be an HTTPS URI`() {
|
||||||
assertThatCode {
|
assertThatCode {
|
||||||
resolver.getBytes(
|
resolver.getBytes(
|
||||||
PackageAssetUri("package://localhost:0/badPackageZipUrl@1.0.0#/Bug.pkl"),
|
PackageAssetUri("package://localhost:0/badPackageZipUrl@1.0.0#/Bug.pkl"),
|
||||||
false,
|
false,
|
||||||
null)
|
null
|
||||||
}
|
)
|
||||||
.hasMessage("Expected the zip asset for package `package://localhost:0/badPackageZipUrl@1.0.0` to be an HTTPS URI, but got `ftp://wait/a/minute`.")
|
}
|
||||||
|
.hasMessage(
|
||||||
|
"Expected the zip asset for package `package://localhost:0/badPackageZipUrl@1.0.0` to be an HTTPS URI, but got `ftp://wait/a/minute`."
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `throws if package checksum is invalid`() {
|
fun `throws if package checksum is invalid`() {
|
||||||
val error = assertThrows<PackageLoadError> {
|
val error =
|
||||||
resolver.getBytes(
|
assertThrows<PackageLoadError> {
|
||||||
PackageAssetUri("package://localhost:0/badChecksum@1.0.0#/Bug.pkl"),
|
resolver.getBytes(
|
||||||
false,
|
PackageAssetUri("package://localhost:0/badChecksum@1.0.0#/Bug.pkl"),
|
||||||
null)
|
false,
|
||||||
}
|
null
|
||||||
assertThat(error).hasMessageContaining("""
|
)
|
||||||
|
}
|
||||||
|
assertThat(error)
|
||||||
|
.hasMessageContaining(
|
||||||
|
"""
|
||||||
Computed checksum: "a6bf858cdd1c09da475c2abe50525902580910ee5cc1ff624999170591bf8f69"
|
Computed checksum: "a6bf858cdd1c09da475c2abe50525902580910ee5cc1ff624999170591bf8f69"
|
||||||
Expected checksum: "intentionally bogus checksum"
|
Expected checksum: "intentionally bogus checksum"
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,12 +233,16 @@ class PackageResolversTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val resolver: PackageResolver = PackageResolvers.DiskCachedPackageResolver(
|
override val resolver: PackageResolver =
|
||||||
SecurityManagers.defaultManager, httpClient, cacheDir)
|
PackageResolvers.DiskCachedPackageResolver(
|
||||||
|
SecurityManagers.defaultManager,
|
||||||
|
httpClient,
|
||||||
|
cacheDir
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class InMemoryPackageResolverTest : AbstractPackageResolverTest() {
|
class InMemoryPackageResolverTest : AbstractPackageResolverTest() {
|
||||||
override val resolver: PackageResolver = PackageResolvers.InMemoryPackageResolver(
|
override val resolver: PackageResolver =
|
||||||
SecurityManagers.defaultManager, httpClient)
|
PackageResolvers.InMemoryPackageResolver(SecurityManagers.defaultManager, httpClient)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.core.parser
|
package org.pkl.core.parser
|
||||||
|
|
||||||
import org.antlr.v4.runtime.CommonToken
|
import org.antlr.v4.runtime.CommonToken
|
||||||
|
|||||||
@@ -1,30 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.parser
|
package org.pkl.core.parser
|
||||||
|
|
||||||
import org.pkl.core.Evaluator
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.pkl.core.Evaluator
|
||||||
import org.pkl.core.ModuleSource
|
import org.pkl.core.ModuleSource
|
||||||
|
|
||||||
// tests whitespace handling in multi-line string literals that cannot be reliably tested via snippets
|
// tests whitespace handling in multi-line string literals that cannot be reliably tested via
|
||||||
|
// snippets
|
||||||
// (e.g. due to editors not displaying and/or automatically removing whitespace)
|
// (e.g. due to editors not displaying and/or automatically removing whitespace)
|
||||||
class MultiLineStringLiteralTest {
|
class MultiLineStringLiteralTest {
|
||||||
private val evaluator = Evaluator.preconfigured()
|
private val evaluator = Evaluator.preconfigured()
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `multi-line strings have unix newlines`() {
|
fun `multi-line strings have unix newlines`() {
|
||||||
val module = evaluator.evaluate(
|
val module =
|
||||||
ModuleSource.text(
|
evaluator.evaluate(ModuleSource.text("x = \"\"\"\none\rtwo\nthree\r\nfour\n\"\"\""))
|
||||||
"x = \"\"\"\none\rtwo\nthree\r\nfour\n\"\"\""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
assertThat(module.properties["x"]).isEqualTo("one\ntwo\nthree\nfour")
|
assertThat(module.properties["x"]).isEqualTo("one\ntwo\nthree\nfour")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `raw multi-line strings have unix newlines`() {
|
fun `raw multi-line strings have unix newlines`() {
|
||||||
val module = evaluator.evaluate(
|
val module =
|
||||||
ModuleSource.text("x = #\"\"\"\none\rtwo\nthree\r\nfour\n\"\"\"#")
|
evaluator.evaluate(ModuleSource.text("x = #\"\"\"\none\rtwo\nthree\r\nfour\n\"\"\"#"))
|
||||||
)
|
|
||||||
assertThat(module.properties["x"]).isEqualTo("one\ntwo\nthree\nfour")
|
assertThat(module.properties["x"]).isEqualTo("one\ntwo\nthree\nfour")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.parser
|
package org.pkl.core.parser
|
||||||
|
|
||||||
import org.pkl.core.Evaluator
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.pkl.core.Evaluator
|
||||||
import org.pkl.core.ModuleSource
|
import org.pkl.core.ModuleSource
|
||||||
|
|
||||||
class ShebangTest {
|
class ShebangTest {
|
||||||
@@ -10,15 +25,17 @@ class ShebangTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `shebang is ignored`() {
|
fun `shebang is ignored`() {
|
||||||
val module = evaluator.evaluate(
|
val module =
|
||||||
ModuleSource.text(
|
evaluator.evaluate(
|
||||||
"""
|
ModuleSource.text(
|
||||||
|
"""
|
||||||
#!/usr/local/bin/pkl
|
#!/usr/local/bin/pkl
|
||||||
x = 1
|
x = 1
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
assertThat (module.properties["x"]).isEqualTo(1L)
|
assertThat(module.properties["x"]).isEqualTo(1L)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.project
|
package org.pkl.core.project
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.AfterAll
|
import org.junit.jupiter.api.AfterAll
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
@@ -7,23 +24,21 @@ import org.junit.jupiter.api.assertThrows
|
|||||||
import org.pkl.commons.test.FileTestUtils
|
import org.pkl.commons.test.FileTestUtils
|
||||||
import org.pkl.commons.test.PackageServer
|
import org.pkl.commons.test.PackageServer
|
||||||
import org.pkl.commons.toPath
|
import org.pkl.commons.toPath
|
||||||
import org.pkl.core.http.HttpClient
|
|
||||||
import org.pkl.core.PklException
|
import org.pkl.core.PklException
|
||||||
import org.pkl.core.SecurityManagers
|
import org.pkl.core.SecurityManagers
|
||||||
|
import org.pkl.core.http.HttpClient
|
||||||
import org.pkl.core.packages.PackageResolver
|
import org.pkl.core.packages.PackageResolver
|
||||||
import java.io.ByteArrayOutputStream
|
|
||||||
import java.nio.charset.StandardCharsets
|
|
||||||
|
|
||||||
class ProjectDependenciesResolverTest {
|
class ProjectDependenciesResolverTest {
|
||||||
companion object {
|
companion object {
|
||||||
private val packageServer = PackageServer()
|
private val packageServer = PackageServer()
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@AfterAll
|
@AfterAll
|
||||||
fun afterAll() {
|
fun afterAll() {
|
||||||
packageServer.close()
|
packageServer.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
val httpClient: HttpClient by lazy {
|
val httpClient: HttpClient by lazy {
|
||||||
HttpClient.builder()
|
HttpClient.builder()
|
||||||
.addCertificates(FileTestUtils.selfSignedCertificate)
|
.addCertificates(FileTestUtils.selfSignedCertificate)
|
||||||
@@ -36,13 +51,17 @@ class ProjectDependenciesResolverTest {
|
|||||||
fun resolveDependencies() {
|
fun resolveDependencies() {
|
||||||
val project2Path = javaClass.getResource("project2/PklProject")!!.toURI().toPath()
|
val project2Path = javaClass.getResource("project2/PklProject")!!.toURI().toPath()
|
||||||
val project = Project.loadFromPath(project2Path)
|
val project = Project.loadFromPath(project2Path)
|
||||||
val packageResolver = PackageResolver.getInstance(SecurityManagers.defaultManager, httpClient, null)
|
val packageResolver =
|
||||||
|
PackageResolver.getInstance(SecurityManagers.defaultManager, httpClient, null)
|
||||||
val deps = ProjectDependenciesResolver(project, packageResolver, System.out.writer()).resolve()
|
val deps = ProjectDependenciesResolver(project, packageResolver, System.out.writer()).resolve()
|
||||||
val strDeps = ByteArrayOutputStream()
|
val strDeps =
|
||||||
.apply { deps.writeTo(this) }
|
ByteArrayOutputStream()
|
||||||
.toByteArray()
|
.apply { deps.writeTo(this) }
|
||||||
.toString(StandardCharsets.UTF_8)
|
.toByteArray()
|
||||||
assertThat(strDeps).isEqualTo("""
|
.toString(StandardCharsets.UTF_8)
|
||||||
|
assertThat(strDeps)
|
||||||
|
.isEqualTo(
|
||||||
|
"""
|
||||||
{
|
{
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"resolvedDependencies": {
|
"resolvedDependencies": {
|
||||||
@@ -67,22 +86,30 @@ class ProjectDependenciesResolverTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `fails if project declares a package with an incorrect checksum`() {
|
fun `fails if project declares a package with an incorrect checksum`() {
|
||||||
val projectPath = javaClass.getResource("badProjectChecksum/PklProject")!!.toURI().toPath()
|
val projectPath = javaClass.getResource("badProjectChecksum/PklProject")!!.toURI().toPath()
|
||||||
val project = Project.loadFromPath(projectPath)
|
val project = Project.loadFromPath(projectPath)
|
||||||
val packageResolver = PackageResolver.getInstance(SecurityManagers.defaultManager, httpClient, null)
|
val packageResolver =
|
||||||
val e = assertThrows<PklException> {
|
PackageResolver.getInstance(SecurityManagers.defaultManager, httpClient, null)
|
||||||
ProjectDependenciesResolver(project, packageResolver, System.err.writer()).resolve()
|
val e =
|
||||||
}
|
assertThrows<PklException> {
|
||||||
assertThat(e).hasMessage("""
|
ProjectDependenciesResolver(project, packageResolver, System.err.writer()).resolve()
|
||||||
|
}
|
||||||
|
assertThat(e)
|
||||||
|
.hasMessage(
|
||||||
|
"""
|
||||||
Computed checksum did not match declared checksum for dependency `package://localhost:0/birds@0.5.0`.
|
Computed checksum did not match declared checksum for dependency `package://localhost:0/birds@0.5.0`.
|
||||||
|
|
||||||
Computed: "${PackageServer.BIRDS_SHA}"
|
Computed: "${PackageServer.BIRDS_SHA}"
|
||||||
Declared: "intentionally bogus value"
|
Declared: "intentionally bogus value"
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.project
|
package org.pkl.core.project
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
|
import java.nio.file.Path
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
import org.pkl.core.packages.Checksums
|
import org.pkl.core.packages.Checksums
|
||||||
import org.pkl.core.packages.Dependency
|
import org.pkl.core.packages.Dependency
|
||||||
import org.pkl.core.packages.PackageUri
|
import org.pkl.core.packages.PackageUri
|
||||||
import org.pkl.core.util.EconomicMaps
|
import org.pkl.core.util.EconomicMaps
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import java.io.ByteArrayOutputStream
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
class ProjectDepsTest {
|
class ProjectDepsTest {
|
||||||
private val projectDepsStr = """
|
private val projectDepsStr =
|
||||||
|
"""
|
||||||
{
|
{
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"resolvedDependencies": {
|
"resolvedDependencies": {
|
||||||
@@ -28,27 +44,29 @@ class ProjectDepsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
|
||||||
private val projectDeps = let {
|
private val projectDeps = let {
|
||||||
val projectDepsMap = EconomicMaps.of<CanonicalPackageUri, Dependency>(
|
val projectDepsMap =
|
||||||
CanonicalPackageUri.of("package://localhost:0/birds@0"), Dependency.RemoteDependency(
|
EconomicMaps.of<CanonicalPackageUri, Dependency>(
|
||||||
PackageUri.create("package://localhost:0/birds@0.5.0"),
|
CanonicalPackageUri.of("package://localhost:0/birds@0"),
|
||||||
Checksums("abc123")
|
Dependency.RemoteDependency(
|
||||||
),
|
PackageUri.create("package://localhost:0/birds@0.5.0"),
|
||||||
CanonicalPackageUri.of("package://localhost:0/fruit@1"), Dependency.LocalDependency(
|
Checksums("abc123")
|
||||||
PackageUri.create("package://localhost:0/fruit@1.1.0"),
|
),
|
||||||
Path.of("../fruit")
|
CanonicalPackageUri.of("package://localhost:0/fruit@1"),
|
||||||
|
Dependency.LocalDependency(
|
||||||
|
PackageUri.create("package://localhost:0/fruit@1.1.0"),
|
||||||
|
Path.of("../fruit")
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
ProjectDeps(projectDepsMap)
|
ProjectDeps(projectDepsMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun writeTo() {
|
fun writeTo() {
|
||||||
val str = ByteArrayOutputStream()
|
val str = ByteArrayOutputStream().apply { projectDeps.writeTo(this) }.toString(Charsets.UTF_8)
|
||||||
.apply { projectDeps.writeTo(this) }
|
|
||||||
.toString(Charsets.UTF_8)
|
|
||||||
assertThat(str).isEqualTo(projectDepsStr)
|
assertThat(str).isEqualTo(projectDepsStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.project
|
package org.pkl.core.project
|
||||||
|
|
||||||
|
import java.net.URI
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.util.regex.Pattern
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.assertj.core.api.Assertions.assertThatCode
|
import org.assertj.core.api.Assertions.assertThatCode
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
@@ -8,54 +26,52 @@ import org.pkl.commons.test.FileTestUtils
|
|||||||
import org.pkl.commons.test.PackageServer
|
import org.pkl.commons.test.PackageServer
|
||||||
import org.pkl.commons.writeString
|
import org.pkl.commons.writeString
|
||||||
import org.pkl.core.*
|
import org.pkl.core.*
|
||||||
|
import org.pkl.core.evaluatorSettings.PklEvaluatorSettings
|
||||||
import org.pkl.core.http.HttpClient
|
import org.pkl.core.http.HttpClient
|
||||||
import org.pkl.core.packages.PackageUri
|
import org.pkl.core.packages.PackageUri
|
||||||
import org.pkl.core.evaluatorSettings.PklEvaluatorSettings
|
|
||||||
import java.net.URI
|
|
||||||
import java.nio.file.Path
|
|
||||||
import java.util.regex.Pattern
|
|
||||||
|
|
||||||
class ProjectTest {
|
class ProjectTest {
|
||||||
@Test
|
@Test
|
||||||
fun loadFromPath(@TempDir path: Path) {
|
fun loadFromPath(@TempDir path: Path) {
|
||||||
val projectPath = path.resolve("PklProject")
|
val projectPath = path.resolve("PklProject")
|
||||||
val expectedPackage = Package(
|
val expectedPackage =
|
||||||
"hawk",
|
Package(
|
||||||
PackageUri("package://example.com/hawk@0.5.0"),
|
"hawk",
|
||||||
Version.parse("0.5.0"),
|
PackageUri("package://example.com/hawk@0.5.0"),
|
||||||
URI("https://example.com/hawk/0.5.0/hawk-0.5.0.zip"),
|
Version.parse("0.5.0"),
|
||||||
"Some project about hawks",
|
URI("https://example.com/hawk/0.5.0/hawk-0.5.0.zip"),
|
||||||
listOf("Birdy Bird <birdy@bird.com>"),
|
"Some project about hawks",
|
||||||
URI("https://example.com/my/website"),
|
listOf("Birdy Bird <birdy@bird.com>"),
|
||||||
URI("https://example.com/my/docs"),
|
URI("https://example.com/my/website"),
|
||||||
URI("https://example.com/my/repo"),
|
URI("https://example.com/my/docs"),
|
||||||
"https://example.com/my/repo/0.5.0%{path}",
|
URI("https://example.com/my/repo"),
|
||||||
"MIT",
|
"https://example.com/my/repo/0.5.0%{path}",
|
||||||
"""
|
"MIT",
|
||||||
|
"""
|
||||||
# Some License text
|
# Some License text
|
||||||
|
|
||||||
This is my license text
|
This is my license text
|
||||||
""".trimIndent(),
|
"""
|
||||||
URI("https://example.com/my/issues"),
|
.trimIndent(),
|
||||||
listOf(Path.of("apiTest1.pkl"), Path.of("apiTest2.pkl")),
|
URI("https://example.com/my/issues"),
|
||||||
listOf("PklProject", "PklProject.deps.json", ".**", "*.exe")
|
listOf(Path.of("apiTest1.pkl"), Path.of("apiTest2.pkl")),
|
||||||
)
|
listOf("PklProject", "PklProject.deps.json", ".**", "*.exe")
|
||||||
val expectedSettings = PklEvaluatorSettings(
|
)
|
||||||
mapOf("two" to "2"),
|
val expectedSettings =
|
||||||
mapOf("one" to "1"),
|
PklEvaluatorSettings(
|
||||||
listOf("foo:", "bar:").map(Pattern::compile),
|
mapOf("two" to "2"),
|
||||||
listOf("baz:", "biz:").map(Pattern::compile),
|
mapOf("one" to "1"),
|
||||||
false,
|
listOf("foo:", "bar:").map(Pattern::compile),
|
||||||
path.resolve("cache/"),
|
listOf("baz:", "biz:").map(Pattern::compile),
|
||||||
listOf(
|
false,
|
||||||
path.resolve("modulepath1/"),
|
path.resolve("cache/"),
|
||||||
path.resolve("modulepath2/")
|
listOf(path.resolve("modulepath1/"), path.resolve("modulepath2/")),
|
||||||
),
|
Duration.ofMinutes(5.0),
|
||||||
Duration.ofMinutes(5.0),
|
path,
|
||||||
path,
|
null
|
||||||
null
|
)
|
||||||
)
|
projectPath.writeString(
|
||||||
projectPath.writeString("""
|
"""
|
||||||
amends "pkl:Project"
|
amends "pkl:Project"
|
||||||
|
|
||||||
evaluatorSettings {
|
evaluatorSettings {
|
||||||
@@ -114,24 +130,28 @@ class ProjectTest {
|
|||||||
"test1.pkl"
|
"test1.pkl"
|
||||||
"test2.pkl"
|
"test2.pkl"
|
||||||
}
|
}
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
val project = Project.loadFromPath(projectPath)
|
val project = Project.loadFromPath(projectPath)
|
||||||
assertThat(project.`package`).isEqualTo(expectedPackage)
|
assertThat(project.`package`).isEqualTo(expectedPackage)
|
||||||
assertThat(project.evaluatorSettings).isEqualTo(expectedSettings)
|
assertThat(project.evaluatorSettings).isEqualTo(expectedSettings)
|
||||||
assertThat(project.tests).isEqualTo(listOf(path.resolve("test1.pkl"), path.resolve("test2.pkl")))
|
assertThat(project.tests)
|
||||||
|
.isEqualTo(listOf(path.resolve("test1.pkl"), path.resolve("test2.pkl")))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `load wrong type`(@TempDir path: Path) {
|
fun `load wrong type`(@TempDir path: Path) {
|
||||||
val projectPath = path.resolve("PklProject")
|
val projectPath = path.resolve("PklProject")
|
||||||
projectPath.writeString("""
|
projectPath.writeString(
|
||||||
|
"""
|
||||||
module com.apple.Foo
|
module com.apple.Foo
|
||||||
|
|
||||||
foo = 1
|
foo = 1
|
||||||
""".trimIndent())
|
"""
|
||||||
assertThatCode {
|
.trimIndent()
|
||||||
Project.loadFromPath(projectPath, SecurityManagers.defaultManager, null)
|
)
|
||||||
}
|
assertThatCode { Project.loadFromPath(projectPath, SecurityManagers.defaultManager, null) }
|
||||||
.hasMessageContaining("be of type `pkl.Project`, but got type `com.apple.Foo`")
|
.hasMessageContaining("be of type `pkl.Project`, but got type `com.apple.Foo`")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,18 +160,20 @@ class ProjectTest {
|
|||||||
PackageServer().use { server ->
|
PackageServer().use { server ->
|
||||||
val projectDir = Path.of(javaClass.getResource("badProjectChecksum2/")!!.toURI())
|
val projectDir = Path.of(javaClass.getResource("badProjectChecksum2/")!!.toURI())
|
||||||
val project = Project.loadFromPath(projectDir.resolve("PklProject"))
|
val project = Project.loadFromPath(projectDir.resolve("PklProject"))
|
||||||
val httpClient = HttpClient.builder()
|
val httpClient =
|
||||||
.addCertificates(FileTestUtils.selfSignedCertificate)
|
HttpClient.builder()
|
||||||
.setTestPort(server.port)
|
.addCertificates(FileTestUtils.selfSignedCertificate)
|
||||||
.build()
|
.setTestPort(server.port)
|
||||||
val evaluator = EvaluatorBuilder.preconfigured()
|
.build()
|
||||||
.applyFromProject(project)
|
val evaluator =
|
||||||
.setModuleCacheDir(null)
|
EvaluatorBuilder.preconfigured()
|
||||||
.setHttpClient(httpClient)
|
.applyFromProject(project)
|
||||||
.build()
|
.setModuleCacheDir(null)
|
||||||
assertThatCode {
|
.setHttpClient(httpClient)
|
||||||
evaluator.evaluate(ModuleSource.path(projectDir.resolve("bug.pkl")))
|
.build()
|
||||||
}.hasMessageStartingWith("""
|
assertThatCode { evaluator.evaluate(ModuleSource.path(projectDir.resolve("bug.pkl"))) }
|
||||||
|
.hasMessageStartingWith(
|
||||||
|
"""
|
||||||
–– Pkl Error ––
|
–– Pkl Error ––
|
||||||
Cannot download package `package://localhost:0/fruit@1.0.5` because the computed checksum for package metadata does not match the expected checksum.
|
Cannot download package `package://localhost:0/fruit@1.0.5` because the computed checksum for package metadata does not match the expected checksum.
|
||||||
|
|
||||||
@@ -161,7 +183,9 @@ class ProjectTest {
|
|||||||
|
|
||||||
1 | import "@fruit/Fruit.pkl"
|
1 | import "@fruit/Fruit.pkl"
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.resource
|
package org.pkl.core.resource
|
||||||
|
|
||||||
import org.pkl.core.Evaluator
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.outputStream
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.io.TempDir
|
import org.junit.jupiter.api.io.TempDir
|
||||||
|
import org.pkl.core.Evaluator
|
||||||
import org.pkl.core.EvaluatorBuilder
|
import org.pkl.core.EvaluatorBuilder
|
||||||
import org.pkl.core.ModuleSource
|
import org.pkl.core.ModuleSource
|
||||||
import org.pkl.core.module.ModulePathResolver
|
import org.pkl.core.module.ModulePathResolver
|
||||||
import kotlin.io.path.outputStream
|
|
||||||
|
|
||||||
class ResourceReadersEvaluatorTest {
|
class ResourceReadersEvaluatorTest {
|
||||||
@Test
|
@Test
|
||||||
fun `class path`() {
|
fun `class path`() {
|
||||||
val evaluator = Evaluator.preconfigured()
|
val evaluator = Evaluator.preconfigured()
|
||||||
|
|
||||||
val module = evaluator.evaluate(
|
val module =
|
||||||
ModuleSource.text(
|
evaluator.evaluate(
|
||||||
"""
|
ModuleSource.text(
|
||||||
|
"""
|
||||||
res1 = read("modulepath:/org/pkl/core/resource/resource.txt").text
|
res1 = read("modulepath:/org/pkl/core/resource/resource.txt").text
|
||||||
"""
|
"""
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(module.getProperty("res1")).isEqualTo("content")
|
assertThat(module.getProperty("res1")).isEqualTo("content")
|
||||||
}
|
}
|
||||||
@@ -38,18 +54,16 @@ class ResourceReadersEvaluatorTest {
|
|||||||
ModulePathResolver(listOf(jarFile)).use { resolver ->
|
ModulePathResolver(listOf(jarFile)).use { resolver ->
|
||||||
val reader = ResourceReaders.modulePath(resolver)
|
val reader = ResourceReaders.modulePath(resolver)
|
||||||
|
|
||||||
val evaluator = EvaluatorBuilder
|
val evaluator = EvaluatorBuilder.preconfigured().addResourceReader(reader).build()
|
||||||
.preconfigured()
|
|
||||||
.addResourceReader(reader)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val module = evaluator.evaluate(
|
val module =
|
||||||
ModuleSource.text(
|
evaluator.evaluate(
|
||||||
"""
|
ModuleSource.text(
|
||||||
|
"""
|
||||||
res1 = read("modulepath:/dir1/resource1.txt").text
|
res1 = read("modulepath:/dir1/resource1.txt").text
|
||||||
"""
|
"""
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(module.getProperty("res1")).isEqualTo("content\n")
|
assertThat(module.getProperty("res1")).isEqualTo("content\n")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.resource
|
package org.pkl.core.resource
|
||||||
|
|
||||||
|
import java.net.URI
|
||||||
|
import java.net.URISyntaxException
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.outputStream
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.assertThrows
|
import org.junit.jupiter.api.assertThrows
|
||||||
import org.junit.jupiter.api.io.TempDir
|
import org.junit.jupiter.api.io.TempDir
|
||||||
import org.pkl.core.module.ModulePathResolver
|
import org.pkl.core.module.ModulePathResolver
|
||||||
import java.net.URI
|
|
||||||
import java.net.URISyntaxException
|
|
||||||
import java.nio.file.Path
|
|
||||||
import kotlin.io.path.outputStream
|
|
||||||
|
|
||||||
class ResourceReadersTest {
|
class ResourceReadersTest {
|
||||||
@Test
|
@Test
|
||||||
@@ -82,9 +97,7 @@ class ResourceReadersTest {
|
|||||||
fun `module path - missing leading slash`() {
|
fun `module path - missing leading slash`() {
|
||||||
val reader = ResourceReaders.modulePath(ModulePathResolver(listOf()))
|
val reader = ResourceReaders.modulePath(ModulePathResolver(listOf()))
|
||||||
|
|
||||||
assertThrows<URISyntaxException> {
|
assertThrows<URISyntaxException> { reader.read(URI("modulepath:non/existing")) }
|
||||||
reader.read(URI("modulepath:non/existing"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -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.core.resource
|
package org.pkl.core.resource
|
||||||
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|||||||
@@ -1,38 +1,58 @@
|
|||||||
package org.pkl.core.runtime;
|
/**
|
||||||
|
* 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.core.runtime
|
||||||
|
|
||||||
//
|
//
|
||||||
//import java.io.IOException;
|
// import java.io.IOException;
|
||||||
//import java.net.URI;
|
// import java.net.URI;
|
||||||
//import java.net.URISyntaxException;
|
// import java.net.URISyntaxException;
|
||||||
//import java.nio.file.Files;
|
// import java.nio.file.Files;
|
||||||
//import java.nio.file.Path;
|
// import java.nio.file.Path;
|
||||||
//import java.util.Arrays;
|
// import java.util.Arrays;
|
||||||
//import java.util.Collections;
|
// import java.util.Collections;
|
||||||
//
|
//
|
||||||
//import org.pkl.core.EvalOptions;
|
// import org.pkl.core.EvalOptions;
|
||||||
//import org.pkl.core.EvalException;
|
// import org.pkl.core.EvalException;
|
||||||
//import org.pkl.core.resolve.ModuleKey;
|
// import org.pkl.core.resolve.ModuleKey;
|
||||||
//import org.pkl.core.resolve.ModuleKeyFactories;
|
// import org.pkl.core.resolve.ModuleKeyFactories;
|
||||||
//import org.pkl.core.resolve.ModuleKeys;
|
// import org.pkl.core.resolve.ModuleKeys;
|
||||||
//import com.oracle.truffle.api.source.SourceSection;
|
// import com.oracle.truffle.api.source.SourceSection;
|
||||||
//import org.junit.Ignore;
|
// import org.junit.Ignore;
|
||||||
//import org.junit.Test;
|
// import org.junit.Test;
|
||||||
//
|
//
|
||||||
//import static org.junit.Assert.assertEquals;
|
// import static org.junit.Assert.assertEquals;
|
||||||
//import static org.junit.Assert.assertTrue;
|
// import static org.junit.Assert.assertTrue;
|
||||||
//
|
//
|
||||||
//public class DefaultModuleResolverTest {
|
// public class DefaultModuleResolverTest {
|
||||||
// private final SourceSection sourceSection = VmUtils.unavailableSourceSection();
|
// private final SourceSection sourceSection = VmUtils.unavailableSourceSection();
|
||||||
// private final ModuleResolver resolver =
|
// private final ModuleResolver resolver =
|
||||||
// new ModuleResolver(ModuleKeyFactories.namedModuleOnClassPath, EvalOptions.namedModuleOnClassPath.getAllowedModules());
|
// new ModuleResolver(ModuleKeyFactories.namedModuleOnClassPath,
|
||||||
|
// EvalOptions.namedModuleOnClassPath.getAllowedModules());
|
||||||
// private final ModuleKey fileUrlModule;
|
// private final ModuleKey fileUrlModule;
|
||||||
// private final ModuleKey httpsUrlModule;
|
// private final ModuleKey httpsUrlModule;
|
||||||
// private final ModuleKey literalUrlModule;
|
// private final ModuleKey literalUrlModule;
|
||||||
//
|
//
|
||||||
// {
|
// {
|
||||||
// try {
|
// try {
|
||||||
// fileUrlModule = ModuleKeys.genericUrl(new URI("file:///path/script.pkl"), ModuleKeys.FULL_TRUST);
|
// fileUrlModule = ModuleKeys.genericUrl(new URI("file:///path/script.pkl"),
|
||||||
// httpsUrlModule = ModuleKeys.genericUrl(new URI("https://some.domain.com/path/script.pkl"), ModuleKeys.FULL_TRUST);
|
// ModuleKeys.FULL_TRUST);
|
||||||
// literalUrlModule = ModuleKeys.synthetic("myLiteralModule", "my literal source code", ModuleKeys.FULL_TRUST);
|
// httpsUrlModule = ModuleKeys.genericUrl(new URI("https://some.domain.com/path/script.pkl"),
|
||||||
|
// ModuleKeys.FULL_TRUST);
|
||||||
|
// literalUrlModule = ModuleKeys.synthetic("myLiteralModule", "my literal source code",
|
||||||
|
// ModuleKeys.FULL_TRUST);
|
||||||
// } catch (URISyntaxException e) {
|
// } catch (URISyntaxException e) {
|
||||||
// throw new RuntimeException(e);
|
// throw new RuntimeException(e);
|
||||||
// }
|
// }
|
||||||
@@ -61,7 +81,8 @@ package org.pkl.core.runtime;
|
|||||||
//
|
//
|
||||||
// @Test
|
// @Test
|
||||||
// public void importHttpsUrlFromFileUrl() throws IOException {
|
// public void importHttpsUrlFromFileUrl() throws IOException {
|
||||||
// ModuleKey result = resolver.resolve("https://other.domain.com/path2/script2.pkl", fileUrlModule, sourceSection);
|
// ModuleKey result = resolver.resolve("https://other.domain.com/path2/script2.pkl",
|
||||||
|
// fileUrlModule, sourceSection);
|
||||||
// assertTrue(result instanceof ModuleKey.Url);
|
// assertTrue(result instanceof ModuleKey.Url);
|
||||||
// assertEquals("https://other.domain.com/path2/script2.pkl", result.toString());
|
// assertEquals("https://other.domain.com/path2/script2.pkl", result.toString());
|
||||||
// }
|
// }
|
||||||
@@ -94,7 +115,8 @@ package org.pkl.core.runtime;
|
|||||||
//
|
//
|
||||||
// @Test
|
// @Test
|
||||||
// public void importHttpsUrlFromHttpsUrl() throws IOException {
|
// public void importHttpsUrlFromHttpsUrl() throws IOException {
|
||||||
// ModuleKey result = resolver.resolve("https://other.domain.com/path2/script2.pkl", httpsUrlModule, sourceSection);
|
// ModuleKey result = resolver.resolve("https://other.domain.com/path2/script2.pkl",
|
||||||
|
// httpsUrlModule, sourceSection);
|
||||||
// assertTrue(result instanceof ModuleKey.Url);
|
// assertTrue(result instanceof ModuleKey.Url);
|
||||||
// assertEquals("https://other.domain.com/path2/script2.pkl", result.toString());
|
// assertEquals("https://other.domain.com/path2/script2.pkl", result.toString());
|
||||||
// }
|
// }
|
||||||
@@ -127,14 +149,16 @@ package org.pkl.core.runtime;
|
|||||||
//
|
//
|
||||||
// @Test
|
// @Test
|
||||||
// public void importFileUrlFromLiteral() throws IOException {
|
// public void importFileUrlFromLiteral() throws IOException {
|
||||||
// ModuleKey result = resolver.resolve("file:///import/file.pkl", literalUrlModule, sourceSection);
|
// ModuleKey result = resolver.resolve("file:///import/file.pkl", literalUrlModule,
|
||||||
|
// sourceSection);
|
||||||
// assertTrue(result instanceof ModuleKey.Url);
|
// assertTrue(result instanceof ModuleKey.Url);
|
||||||
// assertEquals("file:///import/file.pkl", result.toString());
|
// assertEquals("file:///import/file.pkl", result.toString());
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// @Test
|
// @Test
|
||||||
// public void importHttpsUrlFromLiteral() throws IOException {
|
// public void importHttpsUrlFromLiteral() throws IOException {
|
||||||
// ModuleKey result = resolver.resolve("https://other.domain.com/path2/script2.pkl", literalUrlModule, sourceSection);
|
// ModuleKey result = resolver.resolve("https://other.domain.com/path2/script2.pkl",
|
||||||
|
// literalUrlModule, sourceSection);
|
||||||
// assertTrue(result instanceof ModuleKey.Url);
|
// assertTrue(result instanceof ModuleKey.Url);
|
||||||
// assertEquals("https://other.domain.com/path2/script2.pkl", result.toString());
|
// assertEquals("https://other.domain.com/path2/script2.pkl", result.toString());
|
||||||
// }
|
// }
|
||||||
@@ -183,4 +207,4 @@ package org.pkl.core.runtime;
|
|||||||
//
|
//
|
||||||
// resolver.resolve("pkl:base", fileUrlModule, sourceSection);
|
// resolver.resolve("pkl:base", fileUrlModule, sourceSection);
|
||||||
// }
|
// }
|
||||||
//}
|
// }
|
||||||
|
|||||||
@@ -1,14 +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.core.runtime
|
package org.pkl.core.runtime
|
||||||
|
|
||||||
|
import java.net.URI
|
||||||
|
import java.nio.file.FileSystems
|
||||||
import org.junit.jupiter.api.Assertions.assertFalse
|
import org.junit.jupiter.api.Assertions.assertFalse
|
||||||
import org.junit.jupiter.api.Assertions.assertTrue
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.net.URI
|
|
||||||
import java.nio.file.FileSystems
|
|
||||||
|
|
||||||
class FileSystemManagerTest {
|
class FileSystemManagerTest {
|
||||||
private val resource =
|
private val resource = javaClass.getResource("/org/pkl/core/resource/resource1.jar")!!.toURI()
|
||||||
javaClass.getResource("/org/pkl/core/resource/resource1.jar")!!.toURI()
|
|
||||||
private val resourceUri = URI("jar:$resource")
|
private val resourceUri = URI("jar:$resource")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -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.core.runtime
|
package org.pkl.core.runtime
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
|||||||
@@ -1,22 +1,38 @@
|
|||||||
package org.pkl.core.runtime;
|
/**
|
||||||
|
* 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.core.runtime
|
||||||
|
|
||||||
//
|
//
|
||||||
//import java.io.File;
|
// import java.io.File;
|
||||||
//import java.io.IOException;
|
// import java.io.IOException;
|
||||||
//import java.net.URI;
|
// import java.net.URI;
|
||||||
//import java.net.URISyntaxException;
|
// import java.net.URISyntaxException;
|
||||||
//
|
//
|
||||||
//import org.pkl.core.resolve.ModuleKey;
|
// import org.pkl.core.resolve.ModuleKey;
|
||||||
//import org.pkl.core.resolve.ModuleKeys;
|
// import org.pkl.core.resolve.ModuleKeys;
|
||||||
//import org.junit.Rule;
|
// import org.junit.Rule;
|
||||||
//import org.junit.Test;
|
// import org.junit.Test;
|
||||||
//import org.junit.rules.TemporaryFolder;
|
// import org.junit.rules.TemporaryFolder;
|
||||||
//
|
//
|
||||||
//import static org.junit.Assert.assertEquals;
|
// import static org.junit.Assert.assertEquals;
|
||||||
//import static org.junit.Assert.assertFalse;
|
// import static org.junit.Assert.assertFalse;
|
||||||
//import static org.junit.Assert.assertTrue;
|
// import static org.junit.Assert.assertTrue;
|
||||||
//
|
//
|
||||||
//// some parts of ModuleKey are tested as part of DefaultModuleResolverTest
|
//// some parts of ModuleKey are tested as part of DefaultModuleResolverTest
|
||||||
//public class ModuleKeyTest {
|
// public class ModuleKeyTest {
|
||||||
// @Rule
|
// @Rule
|
||||||
// public TemporaryFolder folder = new TemporaryFolder();
|
// public TemporaryFolder folder = new TemporaryFolder();
|
||||||
//
|
//
|
||||||
@@ -73,4 +89,4 @@ package org.pkl.core.runtime;
|
|||||||
// assertEquals("literal:name", module.getUri());
|
// assertEquals("literal:name", module.getUri());
|
||||||
// assertFalse(module.isBaseModule());
|
// assertFalse(module.isBaseModule());
|
||||||
// }
|
// }
|
||||||
//}
|
// }
|
||||||
|
|||||||
@@ -1,10 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.runtime
|
package org.pkl.core.runtime
|
||||||
|
|
||||||
import org.pkl.core.*
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.junit.jupiter.api.assertThrows
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.AfterAll
|
import org.junit.jupiter.api.AfterAll
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.assertThrows
|
||||||
|
import org.pkl.core.*
|
||||||
|
|
||||||
class StackTraceRendererTest {
|
class StackTraceRendererTest {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -20,39 +35,51 @@ class StackTraceRendererTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `stringy self-reference`() {
|
fun `stringy self-reference`() {
|
||||||
val message = assertThrows<PklException> {
|
val message =
|
||||||
evaluator.evaluate(
|
assertThrows<PklException> {
|
||||||
ModuleSource.text(
|
evaluator.evaluate(
|
||||||
"""
|
ModuleSource.text(
|
||||||
|
"""
|
||||||
self: String = "Strings; if they were lazy, you could tie the knot on \(self.take(7))"
|
self: String = "Strings; if they were lazy, you could tie the knot on \(self.take(7))"
|
||||||
""".trimIndent())
|
"""
|
||||||
)
|
.trimIndent()
|
||||||
}.message!!
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.message!!
|
||||||
assertThat(message)
|
assertThat(message)
|
||||||
.contains("A stack overflow occurred.")
|
.contains("A stack overflow occurred.")
|
||||||
.containsPattern("""
|
.containsPattern(
|
||||||
|
"""
|
||||||
┌─ \d* repetitions of:
|
┌─ \d* repetitions of:
|
||||||
│ 1 | self: String = "Strings; if they were lazy, you could tie the knot on \\\(self.take\(7\)\)"
|
│ 1 | self: String = "Strings; if they were lazy, you could tie the knot on \\\(self.take\(7\)\)"
|
||||||
│ ^^^^
|
│ ^^^^
|
||||||
""".trim())
|
"""
|
||||||
|
.trim()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `cyclic property references`() {
|
fun `cyclic property references`() {
|
||||||
val message = assertThrows<PklException> {
|
val message =
|
||||||
evaluator.evaluate(
|
assertThrows<PklException> {
|
||||||
ModuleSource.text(
|
evaluator.evaluate(
|
||||||
"""
|
ModuleSource.text(
|
||||||
|
"""
|
||||||
foo: String = "FOO:" + bar
|
foo: String = "FOO:" + bar
|
||||||
bar: String = "BAR:" + baz
|
bar: String = "BAR:" + baz
|
||||||
baz: String = "BAZ:" + qux
|
baz: String = "BAZ:" + qux
|
||||||
qux: String = "QUX:" + foo
|
qux: String = "QUX:" + foo
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}.message!!
|
}
|
||||||
|
.message!!
|
||||||
assertThat(message)
|
assertThat(message)
|
||||||
.contains("A stack overflow occurred.")
|
.contains("A stack overflow occurred.")
|
||||||
.containsPattern("""
|
.containsPattern(
|
||||||
|
"""
|
||||||
┌─ \d+ repetitions of:
|
┌─ \d+ repetitions of:
|
||||||
│ 4 | qux: String = "QUX:" + foo
|
│ 4 | qux: String = "QUX:" + foo
|
||||||
│ ^^^
|
│ ^^^
|
||||||
@@ -70,13 +97,16 @@ class StackTraceRendererTest {
|
|||||||
│ ^^^
|
│ ^^^
|
||||||
│ at text#foo (repl:text)
|
│ at text#foo (repl:text)
|
||||||
└─
|
└─
|
||||||
""".trim())
|
"""
|
||||||
|
.trim()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Suppress("RegExpRepeatedSpace")
|
@Suppress("RegExpRepeatedSpace")
|
||||||
fun `reduce stack overflow from actual Pkl code`() {
|
fun `reduce stack overflow from actual Pkl code`() {
|
||||||
val pklCode = """
|
val pklCode =
|
||||||
|
"""
|
||||||
function suffix(n: UInt): UInt =
|
function suffix(n: UInt): UInt =
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
0
|
0
|
||||||
@@ -106,15 +136,15 @@ class StackTraceRendererTest {
|
|||||||
prefix(n - 1)
|
prefix(n - 1)
|
||||||
|
|
||||||
result = prefix(13)
|
result = prefix(13)
|
||||||
""".trimIndent()
|
"""
|
||||||
val message = assertThrows<PklException> {
|
.trimIndent()
|
||||||
evaluator.evaluate(ModuleSource.text(pklCode))
|
val message =
|
||||||
}.message!!
|
assertThrows<PklException> { evaluator.evaluate(ModuleSource.text(pklCode)) }.message!!
|
||||||
|
|
||||||
if (message.contains("5 | suffix")) {
|
if (message.contains("5 | suffix")) {
|
||||||
assertThat(message).containsPattern("repetitions of:\n│ 5 | suffix(n - 1)")
|
assertThat(message).containsPattern("repetitions of:\n│ 5 | suffix(n - 1)")
|
||||||
}
|
}
|
||||||
|
|
||||||
assertThat(message)
|
assertThat(message)
|
||||||
.contains("A stack overflow occurred.")
|
.contains("A stack overflow occurred.")
|
||||||
.containsPattern("┌─ \\d+ repetitions of:\n│ \n│ 9 | loop\\(\\)")
|
.containsPattern("┌─ \\d+ repetitions of:\n│ \n│ 9 | loop\\(\\)")
|
||||||
@@ -159,15 +189,11 @@ class StackTraceRendererTest {
|
|||||||
add(createFrame("foo", 3))
|
add(createFrame("foo", 3))
|
||||||
}
|
}
|
||||||
val loop = StackTraceRenderer.StackFrameLoop(loopFrames, 1)
|
val loop = StackTraceRenderer.StackFrameLoop(loopFrames, 1)
|
||||||
val frames = listOf(
|
val frames = listOf(createFrame("bar", 1), createFrame("baz", 2), loop)
|
||||||
createFrame("bar", 1),
|
val renderedFrames = buildString { renderer.doRender(frames, null, this, "", true) }
|
||||||
createFrame("baz", 2),
|
assertThat(renderedFrames)
|
||||||
loop
|
.isEqualTo(
|
||||||
)
|
"""
|
||||||
val renderedFrames = buildString {
|
|
||||||
renderer.doRender(frames, null, this, "", true)
|
|
||||||
}
|
|
||||||
assertThat(renderedFrames).isEqualTo("""
|
|
||||||
1 | foo
|
1 | foo
|
||||||
^
|
^
|
||||||
at <unknown> (file:bar)
|
at <unknown> (file:bar)
|
||||||
@@ -188,7 +214,9 @@ class StackTraceRendererTest {
|
|||||||
^
|
^
|
||||||
at <unknown> (file:foo)
|
at <unknown> (file:foo)
|
||||||
|
|
||||||
""".trimIndent())
|
"""
|
||||||
|
.trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createFrame(name: String, id: Int): StackFrame {
|
private fun createFrame(name: String, id: Int): StackFrame {
|
||||||
|
|||||||
@@ -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.core.runtime
|
package org.pkl.core.runtime
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
|||||||
@@ -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.core.runtime
|
package org.pkl.core.runtime
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
|||||||
@@ -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.core.runtime
|
package org.pkl.core.runtime
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
|||||||
@@ -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.core.runtime
|
package org.pkl.core.runtime
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
@@ -10,15 +25,12 @@ class VmSafeMathTest {
|
|||||||
assertThat(VmSafeMath.negate(0)).isEqualTo(0)
|
assertThat(VmSafeMath.negate(0)).isEqualTo(0)
|
||||||
assertThat(VmSafeMath.negate(1)).isEqualTo(-1)
|
assertThat(VmSafeMath.negate(1)).isEqualTo(-1)
|
||||||
assertThat(VmSafeMath.negate(-1)).isEqualTo(1)
|
assertThat(VmSafeMath.negate(-1)).isEqualTo(1)
|
||||||
assertThat(VmSafeMath.negate(java.lang.Long.MAX_VALUE))
|
assertThat(VmSafeMath.negate(java.lang.Long.MAX_VALUE)).isEqualTo(-java.lang.Long.MAX_VALUE)
|
||||||
.isEqualTo(-java.lang.Long.MAX_VALUE)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `negate long - overflow`() {
|
fun `negate long - overflow`() {
|
||||||
assertThrows<VmEvalException> {
|
assertThrows<VmEvalException> { VmSafeMath.negate(java.lang.Long.MIN_VALUE) }
|
||||||
VmSafeMath.negate(java.lang.Long.MIN_VALUE)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -27,10 +39,8 @@ class VmSafeMathTest {
|
|||||||
assertThat(VmSafeMath.negate(-1.0)).isEqualTo(1.0)
|
assertThat(VmSafeMath.negate(-1.0)).isEqualTo(1.0)
|
||||||
assertThat(VmSafeMath.negate(1.0)).isEqualTo(-1.0)
|
assertThat(VmSafeMath.negate(1.0)).isEqualTo(-1.0)
|
||||||
assertThat(VmSafeMath.negate(123.456)).isEqualTo(-123.456)
|
assertThat(VmSafeMath.negate(123.456)).isEqualTo(-123.456)
|
||||||
assertThat(VmSafeMath.negate(-java.lang.Double.MAX_VALUE))
|
assertThat(VmSafeMath.negate(-java.lang.Double.MAX_VALUE)).isEqualTo(java.lang.Double.MAX_VALUE)
|
||||||
.isEqualTo(java.lang.Double.MAX_VALUE)
|
assertThat(VmSafeMath.negate(-java.lang.Double.MIN_VALUE)).isEqualTo(java.lang.Double.MIN_VALUE)
|
||||||
assertThat(VmSafeMath.negate(-java.lang.Double.MIN_VALUE))
|
|
||||||
.isEqualTo(java.lang.Double.MIN_VALUE)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -38,31 +48,23 @@ class VmSafeMathTest {
|
|||||||
assertThat(VmSafeMath.add(0, 0)).isEqualTo(0)
|
assertThat(VmSafeMath.add(0, 0)).isEqualTo(0)
|
||||||
assertThat(VmSafeMath.add(1, 2)).isEqualTo(3)
|
assertThat(VmSafeMath.add(1, 2)).isEqualTo(3)
|
||||||
assertThat(VmSafeMath.add(1, -2)).isEqualTo(-1)
|
assertThat(VmSafeMath.add(1, -2)).isEqualTo(-1)
|
||||||
assertThat(VmSafeMath.add(java.lang.Long.MAX_VALUE - 1, 1))
|
assertThat(VmSafeMath.add(java.lang.Long.MAX_VALUE - 1, 1)).isEqualTo(java.lang.Long.MAX_VALUE)
|
||||||
.isEqualTo(java.lang.Long.MAX_VALUE)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `add long - overflow #1`() {
|
fun `add long - overflow #1`() {
|
||||||
assertThrows<VmEvalException> {
|
assertThrows<VmEvalException> { VmSafeMath.add(java.lang.Long.MAX_VALUE, 1) }
|
||||||
VmSafeMath.add(java.lang.Long.MAX_VALUE, 1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `add long - overflow #2`() {
|
fun `add long - overflow #2`() {
|
||||||
assertThrows<VmEvalException> {
|
assertThrows<VmEvalException> { VmSafeMath.add(java.lang.Long.MIN_VALUE, -1) }
|
||||||
VmSafeMath.add(java.lang.Long.MIN_VALUE, -1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `add long - overflow #3`() {
|
fun `add long - overflow #3`() {
|
||||||
assertThrows<VmEvalException> {
|
assertThrows<VmEvalException> {
|
||||||
VmSafeMath.add(
|
VmSafeMath.add(java.lang.Long.MAX_VALUE / 2, java.lang.Long.MAX_VALUE / 3 * 2)
|
||||||
java.lang.Long.MAX_VALUE / 2,
|
|
||||||
java.lang.Long.MAX_VALUE / 3 * 2
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.runtime
|
package org.pkl.core.runtime
|
||||||
|
|
||||||
import org.pkl.core.SecurityManagers
|
|
||||||
import org.pkl.core.module.ModuleKeys
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.net.URI
|
|
||||||
|
|
||||||
class VmUtilsTest {
|
class VmUtilsTest {
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -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.core.runtime
|
package org.pkl.core.runtime
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user