Initial commit

This commit is contained in:
Peter Niederwieser
2016-01-19 14:51:19 +01:00
committed by Dan Chao
commit ecad035dca
2972 changed files with 211653 additions and 0 deletions
@@ -0,0 +1,69 @@
package org.pkl.gradle
import org.pkl.commons.createParentDirectories
import org.pkl.commons.readString
import org.pkl.commons.writeString
import org.assertj.core.api.Assertions.assertThat
import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.UnexpectedBuildFailure
import org.junit.jupiter.api.io.TempDir
import java.net.URI
import java.nio.file.Path
abstract class AbstractTest {
private val gradleVersion: String? = System.getProperty("testGradleVersion")
private val gradleDistributionUrl: String? = System.getProperty("testGradleDistributionUrl")
@TempDir
protected lateinit var testProjectDir: Path
protected fun runTask(
taskName: String,
expectFailure: Boolean = false
): BuildResult {
val runner = GradleRunner.create()
.withProjectDir(testProjectDir.toFile())
.withArguments("--stacktrace", "--no-build-cache", taskName)
.withPluginClasspath()
.withDebug(true)
if (gradleVersion != null) {
runner.withGradleVersion(gradleVersion)
}
if (gradleDistributionUrl != null) {
runner.withGradleDistribution(URI(gradleDistributionUrl))
}
return try {
if (expectFailure) runner.buildAndFail() else runner.build()
} catch (e: UnexpectedBuildFailure) {
throw AssertionError(e.buildResult.output)
}
}
protected fun writeFile(fileName: String, contents: String): Path {
return testProjectDir.resolve(fileName)
.apply { createParentDirectories() }
.writeString(contents.trimIndent())
}
protected fun checkFileContents(file: Path, contents: String) {
assertThat(file).exists()
assertThat(file.readString().trim())
.isEqualTo(contents.trim())
}
protected fun checkTextContains(text: String, vararg contents: String) {
for (content in contents) {
try {
assertThat(text).contains(content.trimMargin())
} catch (e: AssertionError) {
// to get diff output in IDE
assertThat(text).isEqualTo(content.trimMargin())
}
}
}
}
@@ -0,0 +1,505 @@
package org.pkl.gradle
import org.assertj.core.api.Assertions
import org.pkl.commons.readString
import org.pkl.commons.test.PackageServer
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import java.nio.file.Path
class EvaluatorsTest : AbstractTest() {
@Test
fun `render Pcf`() {
writeBuildFile("pcf")
writePklFile()
runTask("evalTest")
val outputFile = testProjectDir.resolve("test.pcf")
checkFileContents(
outputFile, """
person {
name = "Pigeon"
age = 30
}
""".trimIndent()
)
}
@Test
fun `render YAML`() {
writeBuildFile("yaml")
writePklFile()
runTask("evalTest")
val outputFile = testProjectDir.resolve("test.yaml")
checkFileContents(
outputFile, """
person:
name: Pigeon
age: 30
""".trimIndent()
)
}
@Test
fun `render JSON`() {
writeBuildFile("json")
writePklFile()
runTask("evalTest")
val outputFile = testProjectDir.resolve("test.json")
checkFileContents(
outputFile, """
{
"person": {
"name": "Pigeon",
"age": 30
}
}
""".trimIndent()
)
}
@Test
fun `render plist`() {
writeBuildFile("plist")
writePklFile()
runTask("evalTest")
val outputFile = testProjectDir.resolve("test.plist")
checkFileContents(
outputFile, """
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>person</key>
<dict>
<key>name</key>
<string>Pigeon</string>
<key>age</key>
<integer>30</integer>
</dict>
</dict>
</plist>
""".trimIndent()
)
}
@Test
fun `set external properties`() {
writeBuildFile(
"pcf", """
externalProperties = [prop1: "value1", prop2: "value2"]
""".trimIndent()
)
writePklFile(
"""
prop1 = read("prop:prop1")
prop2 = read("prop:prop2")
other = read?("prop:other")
""".trimIndent()
)
runTask("evalTest")
val outputFile = testProjectDir.resolve("test.pcf")
checkFileContents(
outputFile, """
prop1 = "value1"
prop2 = "value2"
other = null
""".trimIndent()
)
}
@Test
fun `defaults to empty environment variables`() {
writeBuildFile("pcf")
writePklFile(
"""
prop1 = read?("env:USER")
prop2 = read?("env:PATH")
prop3 = read?("env:JAVA_HOME")
""".trimIndent()
)
runTask("evalTest")
val outputFile = testProjectDir.resolve("test.pcf")
checkFileContents(
outputFile, """
prop1 = null
prop2 = null
prop3 = null
""".trimIndent()
)
}
@Test
fun `set environment variables`() {
writeBuildFile(
"pcf", """
environmentVariables = [VAR1: "value1", VAR2: "value2"]
""".trimIndent()
)
writePklFile(
"""
prop1 = read("env:VAR1")
prop2 = read("env:VAR2")
other = read?("env:OTHER")
""".trimIndent()
)
runTask("evalTest")
val outputFile = testProjectDir.resolve("test.pcf")
checkFileContents(
outputFile, """
prop1 = "value1"
prop2 = "value2"
other = null
""".trimIndent()
)
}
@Test
fun `no source modules`() {
writeFile(
"build.gradle", """
plugins {
id "org.pkl-lang"
}
pkl {
evaluators {
evalTest {
outputFormat = "pcf"
}
}
}
"""
)
val result = runTask("evalTest", true)
assertThat(result.output).contains("No source modules specified.")
}
@Test
fun `source module URIs`() {
val pklFile = writeFile(
"test.pkl", """
person {
name = "Pigeon"
age = 20 + 10
}
"""
)
writeFile(
"build.gradle", """
plugins {
id "org.pkl-lang"
}
pkl {
evaluators {
evalTest {
sourceModules = [uri("modulepath:/test.pkl")]
modulePath.from "${pklFile.parent}"
outputFile = layout.projectDirectory.file("test.pcf")
settingsModule = "pkl:settings"
}
}
}
"""
)
runTask("evalTest")
val outputFile = testProjectDir.resolve("test.pcf")
checkFileContents(
outputFile, """
person {
name = "Pigeon"
age = 30
}
""".trimIndent()
)
}
@Test
fun `cannot evaluate module located outside evalRootDir`() {
writeFile(
"build.gradle", """
plugins {
id "org.pkl-lang"
}
pkl {
evaluators {
evalTest {
evalRootDir = file("/non/existing")
sourceModules = ["test.pkl"]
settingsModule = "pkl:settings"
}
}
}
"""
)
val result = runTask("evalTest", expectFailure = true)
assertThat(result.output).contains("Refusing to load module")
assertThat(result.output).contains("because it does not match any entry in the module allowlist (`--allowed-modules`).")
}
@Test
fun `evaluation timeout`() {
// Gradle 4.10 doesn't automatically import Duration
writeBuildFile(
"pcf", """
evalTimeout = java.time.Duration.ofMillis(100)
"""
)
writePklFile(
"""
function fib(n) = if (n < 2) 0 else fib(n - 1) + fib(n - 2)
x = fib(100)
"""
)
val result = runTask("evalTest", expectFailure = true)
assertThat(result.output).contains("timed out")
}
@Test
fun `module output separator`() {
val outputFile = testProjectDir.resolve("test.pcf")
writeFile(
"build.gradle", """
plugins {
id "org.pkl-lang"
}
pkl {
evaluators {
evalTask {
moduleOutputSeparator = "// hello"
sourceModules = ["test1.pkl", "test2.pkl"]
settingsModule = "pkl:settings"
outputFile = layout.projectDirectory.file("test.pcf")
}
}
}
"""
)
writeFile(
"test1.pkl",
"foo = 1"
)
writeFile(
"test2.pkl",
"bar = 2"
)
runTask("evalTask")
checkFileContents(outputFile, """
foo = 1
// hello
bar = 2
""".trimIndent())
}
@Test
fun `compliant file URIs`() {
writeBuildFile("pcf")
writeFile("test.pkl", """
import "pkl:reflect"
output {
text = reflect.Module(module).uri
}
""".trimIndent())
runTask("evalTest")
val outputFile = testProjectDir.resolve("test.pcf")
assertThat(outputFile).exists()
assertThat(outputFile.readString().trim()).startsWith("file:///")
}
@Test
fun `multiple file output`() {
writeBuildFile("pcf", """
multipleFileOutputDir = layout.projectDirectory.dir("my-output")
""".trimIndent())
writeFile(
"test.pkl",
"""
output {
files {
["output-1.txt"] {
text = "My output 1"
}
["output-2.txt"] {
text = "My output 2"
}
}
}
""".trimIndent()
)
runTask("evalTest")
checkFileContents(testProjectDir.resolve("my-output/output-1.txt"), "My output 1")
checkFileContents(testProjectDir.resolve("my-output/output-2.txt"), "My output 2")
}
@Test
fun expression() {
writeBuildFile("yaml", """
expression = "metadata.name"
outputFile = layout.projectDirectory.file("output.txt")
""".trimIndent())
writeFile(
"test.pkl",
"""
metadata {
name = "Uni"
}
""".trimIndent()
)
runTask("evalTest")
checkFileContents(testProjectDir.resolve("output.txt"), "Uni")
}
@Test
fun `explicitly set cache dir`(@TempDir tempDir: Path) {
writeBuildFile("pcf", """
moduleCacheDir = file("$tempDir")
""".trimIndent())
writeFile(
"test.pkl",
"""
import "package://localhost:12110/birds@0.5.0#/Bird.pkl"
res = new Bird { name = "Wally"; favoriteFruit { name = "bananas" } }
""".trimIndent()
)
PackageServer.populateCacheDir(tempDir)
runTask("evalTest")
}
@Test
fun `explicitly set project dir`() {
writeBuildFile("pcf", "projectDir = file(\"proj1\")", listOf("proj1/foo.pkl"))
writeFile("proj1/PklProject", """
amends "pkl:Project"
dependencies {
["proj2"] = import("../proj2/PklProject")
}
package {
name = "proj1"
baseUri = "package://localhost:12110/\(name)"
version = "1.0.0"
packageZipUrl = "https://localhost:12110/\(name)@\(version).zip"
}
""".trimIndent())
writeFile("proj2/PklProject", """
amends "pkl:Project"
package {
name = "proj2"
baseUri = "package://localhost:12110/\(name)"
version = "1.0.0"
packageZipUrl = "https://localhost:12110/\(name)@\(version).zip"
}
""".trimIndent())
writeFile("proj1/PklProject.deps.json", """
{
"schemaVersion": 1,
"resolvedDependencies": {
"package://localhost:12110/proj2@1": {
"type": "local",
"uri": "projectpackage://localhost:12110/proj2@1.0.0",
"path": "../proj2"
}
}
}
""".trimIndent())
writeFile("proj2/PklProject.deps.json", """
{
"schemaVersion": 1,
"resolvedDependencies": {}
}
""".trimIndent())
writeFile("proj1/foo.pkl", """
module proj1.foo
bar: String = import("@proj2/baz.pkl").qux
""".trimIndent())
writeFile("proj2/baz.pkl", """
qux: String = "Contents of @proj2/qux"
""".trimIndent())
runTask("evalTest")
assertThat(testProjectDir.resolve("proj1/foo.pcf")).exists()
}
private fun writeBuildFile(
// don't use `org.pkl.core.OutputFormat`
// because test compile class path doesn't contain pkl-core
outputFormat: String,
additionalContents: String = "",
sourceModules: List<String> = listOf("test.pkl")
) {
writeFile(
"build.gradle", """
plugins {
id "org.pkl-lang"
}
pkl {
evaluators {
evalTest {
sourceModules = [${sourceModules.joinToString(separator = ", ") { "\"$it\"" }}]
outputFormat = "$outputFormat"
settingsModule = "pkl:settings"
$additionalContents
}
}
}
"""
)
}
private fun writePklFile(
contents: String = """
person {
name = "Pigeon"
age = 20 + 10
}
"""
) {
writeFile("test.pkl", contents)
}
}
@@ -0,0 +1,168 @@
package org.pkl.gradle
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import kotlin.io.path.listDirectoryEntries
import kotlin.io.path.readText
class JavaCodeGeneratorsTest : AbstractTest() {
@Test
fun `generate code`() {
writeBuildFile()
writePklFile()
runTask("configClasses")
val baseDir = testProjectDir.resolve("build/generated/java/org")
val moduleFile = baseDir.resolve("Mod.java")
assertThat(baseDir.listDirectoryEntries().count()).isEqualTo(1)
assertThat(moduleFile).exists()
val text = moduleFile.readText()
// shading must not affect generated code
assertThat(text).doesNotContain("org.pkl.thirdparty")
checkTextContains(
text, """
|public final class Mod {
| public final @Nonnull Object other;
"""
)
checkTextContains(
text, """
| public static final class Person {
| public final @Nonnull String name;
|
| public final @Nonnull List<@Nonnull Address> addresses;
"""
)
checkTextContains(
text, """
| public static final class Address {
| public final @Nonnull String street;
|
| public final long zip;
"""
)
}
@Test
fun `compile generated code`() {
writeBuildFile()
writeFile("mod.pkl", """
module org.mod
class Person {
name: String
addresses: List<Address?>
}
class Address {
street: String
zip: Int
}
other: Any = 42
""".trimIndent())
runTask("compileJava")
val classesDir = testProjectDir.resolve("build/classes/java/main")
val moduleClassFile = classesDir.resolve("org/Mod.class")
val personClassFile = classesDir.resolve("org/Mod\$Person.class")
val addressClassFile = classesDir.resolve("org/Mod\$Address.class")
assertThat(moduleClassFile).exists()
assertThat(personClassFile).exists()
assertThat(addressClassFile).exists()
}
@Test
fun `no source modules`() {
writeFile(
"build.gradle", """
plugins {
id "org.pkl-lang"
}
pkl {
evaluators {
evalTest {
outputFormat = "pcf"
}
}
}
"""
)
val result = runTask("evalTest", true)
assertThat(result.output).contains("No source modules specified.")
}
private fun writeBuildFile() {
writeFile(
"build.gradle", """
plugins {
id "java"
id "org.pkl-lang"
}
repositories {
mavenCentral()
}
dependencies {
implementation "javax.inject:javax.inject:1"
implementation "com.google.code.findbugs:jsr305:3.0.2"
}
pkl {
javaCodeGenerators {
configClasses {
sourceModules = ["mod.pkl"]
outputDir = file("build/generated")
paramsAnnotation = "javax.inject.Named"
nonNullAnnotation = "javax.annotation.Nonnull"
settingsModule = "pkl:settings"
}
}
}
"""
)
}
private fun writeGradlePropertiesFile() {
writeFile("gradle.properties", """
systemProp.http.proxyHost=proxy.config.pcp.local
systemProp.http.proxyPort=3128
systemProp.http.nonProxyHosts=localhost|*.apple.com
systemProp.https.proxyHost=proxy.config.pcp.local
systemProp.https.proxyPort=3128
systemProp.https.nonProxyHosts=localhost|*.apple.com
""")
}
private fun writePklFile() {
writeFile(
"mod.pkl", """
module org.mod
class Person {
name: String
addresses: List<Address>
}
class Address {
street: String
zip: Int
}
other = 42
"""
)
}
}
@@ -0,0 +1,155 @@
package org.pkl.gradle
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import kotlin.io.path.listDirectoryEntries
import kotlin.io.path.readText
class KotlinCodeGeneratorsTest : AbstractTest() {
@Test
fun `generate code`() {
writeBuildFile()
writePklFile()
runTask("configClasses")
val baseDir = testProjectDir.resolve("build/generated/kotlin/org")
val kotlinFile = baseDir.resolve("Mod.kt")
assertThat(baseDir.listDirectoryEntries().count()).isEqualTo(1)
assertThat(kotlinFile).exists()
val text = kotlinFile.readText()
// shading must not affect generated code
assertThat(text).doesNotContain("org.pkl.thirdparty")
checkTextContains(
text, """
|data class Mod(
| val other: Any?
|)
"""
)
checkTextContains(
text, """
| data class Person(
| val name: String,
| val addresses: List<Address>
| )
"""
)
checkTextContains(
text, """
| open class Address(
| open val street: String,
| open val zip: Long
| )
"""
)
}
@Test
fun `compile generated code`() {
writeBuildFile()
writePklFile()
runTask("compileKotlin")
val classesDir = testProjectDir.resolve("build/classes/kotlin/main")
val moduleClassFile = classesDir.resolve("org/Mod.class")
val personClassFile = classesDir.resolve("org/Mod\$Person.class")
val addressClassFile = classesDir.resolve("org/Mod\$Address.class")
assertThat(moduleClassFile).exists()
assertThat(personClassFile).exists()
assertThat(addressClassFile).exists()
}
@Test
fun `no source modules`() {
writeFile(
"build.gradle", """
plugins {
id "org.pkl-lang"
}
pkl {
evaluators {
evalTest {
outputFormat = "pcf"
}
}
}
"""
)
val result = runTask("evalTest", true)
assertThat(result.output).contains("No source modules specified.")
}
private fun writeBuildFile() {
val kotlinVersion = "1.6.0"
writeFile(
"build.gradle", """
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") {
exclude module: "kotlin-android-extensions"
}
}
}
plugins {
id "org.pkl-lang"
}
apply plugin: "kotlin"
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
}
pkl {
kotlinCodeGenerators {
configClasses {
sourceModules = ["mod.pkl"]
outputDir = file("build/generated")
settingsModule = "pkl:settings"
}
}
}
"""
)
}
private fun writePklFile() {
writeFile(
"mod.pkl", """
module org.mod
class Person {
name: String
addresses: List<Address>
}
// "open" to test generating regular class
open class Address {
street: String
zip: Int
}
other = 42
"""
)
}
}
@@ -0,0 +1,99 @@
package org.pkl.gradle
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import kotlin.io.path.readText
class PkldocGeneratorsTest : AbstractTest() {
@Test
fun `generate docs`() {
writeFile(
"build.gradle", """
plugins {
id "org.pkl-lang"
}
pkl {
pkldocGenerators {
pkldoc {
sourceModules = ["person.pkl", "doc-package-info.pkl"]
outputDir = file("build/pkldoc")
settingsModule = "pkl:settings"
}
}
}
"""
)
writeFile(
"doc-package-info.pkl", """
/// A test package.
amends "pkl:DocPackageInfo"
name = "test"
version = "1.0.0"
importUri = "https://pkl-lang.org/"
authors { "publisher@apple.com" }
sourceCode = "sources.apple.com/"
issueTracker = "issues.apple.com"
""".trimIndent()
)
writeFile(
"person.pkl", """
module test.person
class Person {
name: String
addresses: List<Address>
}
class Address {
street: String
zip: Int
}
other = 42
""".trimIndent()
)
runTask("pkldoc")
val baseDir = testProjectDir.resolve("build/pkldoc")
val mainFile = baseDir.resolve("index.html")
val packageFile = baseDir.resolve("test/1.0.0/index.html")
val moduleFile = baseDir.resolve("test/1.0.0/person/index.html")
val personFile = baseDir.resolve("test/1.0.0/person/Person.html")
val addressFile = baseDir.resolve("test/1.0.0/person/Address.html")
assertThat(mainFile).exists()
assertThat(packageFile).exists()
assertThat(moduleFile).exists()
assertThat(personFile).exists()
assertThat(addressFile).exists()
checkTextContains(mainFile.readText(), "<html>", "test")
checkTextContains(packageFile.readText(), "<html>", "test.person")
checkTextContains(moduleFile.readText(), "<html>", "Person", "Address", "other")
checkTextContains(personFile.readText(), "<html>", "name", "addresses")
checkTextContains(addressFile.readText(), "<html>", "street", "zip")
}
@Test
fun `no source modules`() {
writeFile(
"build.gradle", """
plugins {
id "org.pkl-lang"
}
pkl {
pkldocGenerators {
pkldoc {
}
}
}
""".trimIndent()
)
val result = runTask("pkldoc", true)
assertThat(result.output).contains("No source modules specified.")
}
}
@@ -0,0 +1,98 @@
package org.pkl.gradle
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
class ProjectPackageTest : AbstractTest() {
@Test
fun basic() {
writeBuildFile("skipPublishCheck.set(true)")
writeProjectContent()
runTask("createMyPackages")
assertThat(testProjectDir.resolve("build/generated/pkl/packages/proj1@1.0.0.zip")).exists()
assertThat(testProjectDir.resolve("build/generated/pkl/packages/proj1@1.0.0")).exists()
}
@Test
fun `custom output dir`() {
writeBuildFile( """
outputPath.set(file("thepackages"))
skipPublishCheck.set(true)
""")
writeProjectContent()
runTask("createMyPackages")
assertThat(testProjectDir.resolve("thepackages/proj1@1.0.0.zip")).exists()
assertThat(testProjectDir.resolve("thepackages/proj1@1.0.0")).exists()
}
@Test
fun `junit dir`() {
writeBuildFile("""
junitReportsDir.set(file("test-reports"))
skipPublishCheck.set(true)
""".trimIndent())
writeProjectContent()
runTask("createMyPackages")
assertThat(testProjectDir.resolve("test-reports")).isNotEmptyDirectory()
}
private fun writeBuildFile(additionalContents: String = "") {
writeFile(
"build.gradle", """
plugins {
id "org.pkl-lang"
}
pkl {
project {
packagers {
createMyPackages {
projectDirectories.from(file("proj1"))
settingsModule = "pkl:settings"
$additionalContents
}
}
}
}
"""
)
}
private fun writeProjectContent() {
writeFile("proj1/PklProject", """
amends "pkl:Project"
package {
name = "proj1"
baseUri = "package://localhost:12110/proj1"
version = "1.0.0"
packageZipUrl = "https://localhost:12110/proj1@\(version).zip"
apiTests {
"tests.pkl"
}
}
""".trimIndent())
writeFile("proj1/PklProject.deps.json", """
{
"schemaVersion": 1,
"dependencies": {}
}
""".trimIndent())
writeFile("proj1/foo.pkl", """
module proj1.foo
bar: String
""".trimIndent())
writeFile("proj1/tests.pkl", """
amends "pkl:test"
facts {
["it works"] {
1 == 1
}
}
""".trimIndent())
writeFile("foo.txt", "The contents of foo.txt")
}
}
@@ -0,0 +1,47 @@
package org.pkl.gradle
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
class ProjectResolveTest : AbstractTest() {
@Test
fun basic() {
writeBuildFile()
writeProjectContent()
runTask("resolveMyProj")
assertThat(testProjectDir.resolve("proj1/PklProject.deps.json")).hasContent("""
{
"schemaVersion": 1,
"resolvedDependencies": {}
}
""".trimIndent())
}
private fun writeBuildFile(additionalContents: String = "") {
writeFile(
"build.gradle", """
plugins {
id "org.pkl-lang"
}
pkl {
project {
resolvers {
resolveMyProj {
projectDirectories.from(file("proj1"))
settingsModule = "pkl:settings"
$additionalContents
}
}
}
}
"""
)
}
private fun writeProjectContent() {
writeFile("proj1/PklProject", """
amends "pkl:Project"
""".trimIndent())
}
}
@@ -0,0 +1,301 @@
package org.pkl.gradle
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import java.nio.file.Path
import kotlin.io.path.readText
class TestsTest : AbstractTest() {
@Test
fun `facts pass`() {
writeBuildFile()
writePklFile()
val res = runTask("evalTest")
assertThat(res.output).contains("should pass ✅")
}
@Test
fun `facts fail`() {
writeBuildFile()
writePklFile(additionalFacts = """
["should fail"] {
1 == 3
"foo" == "bar"
}
""".trimIndent())
val res = runTask("evalTest", expectFailure = true)
assertThat(res.output).contains("should fail ❌")
assertThat(res.output).contains("1 == 3 ❌")
assertThat(res.output).contains(""""foo" == "bar" ❌""")
}
@Test
fun error() {
writeBuildFile()
writePklFile(additionalFacts = """
["error"] {
throw("exception")
}
""".trimIndent())
val output = runTask("evalTest", expectFailure = true).output.stripFilesAndLines()
assertThat(output.trimStart()).startsWith("""
> Task :evalTest FAILED
module test (file:///file, line x)
test ❌
Error:
–– Pkl Error ––
exception
9 | throw("exception")
^^^^^^^^^^^^^^^^^^
at test#facts["error"][#1] (file:///file, line x)
3 | facts {
^^^^^^^
at test#facts (file:///file, line x)
""".trimIndent())
}
@Test
fun `full example`() {
writePklFile(contents = bigTest)
writeFile("test.pkl-expected.pcf", bigTestExpected)
writeBuildFile()
val output = runTask("evalTest", expectFailure = true).output.stripFilesAndLines()
assertThat(output.trimStart()).contains("""
module test (file:///file, line x)
sum numbers ✅
divide numbers ✅
fail ❌
4 == 9 ❌ (file:///file, line x)
"foo" == "bar" ❌ (file:///file, line x)
user 0 ✅
user 1 ❌
(file:///file, line x)
Expected: (file:///file, line x)
new {
name = "Pigeon"
age = 40
}
Actual: (file:///file, line x)
new {
name = "Pigeon"
age = 41
}
user 1 ❌
(file:///file, line x)
Expected: (file:///file, line x)
new {
name = "Parrot"
age = 35
}
Actual: (file:///file, line x)
new {
name = "Welma"
age = 35
}
""".trimIndent())
}
@Test
fun `overwrite expected examples`() {
writePklFile(additionalExamples = """
["user 0"] {
new {
name = "Cool"
age = 11
}
}
["user 1"] {
new {
name = "Pigeon"
age = 41
}
new {
name = "Welma"
age = 35
}
}
""".trimIndent())
writeFile("test.pkl-expected.pcf", bigTestExpected)
writeBuildFile("overwrite = true")
val output = runTask("evalTest").output
assertThat(output).contains("user 0 ✍️")
assertThat(output).contains("user 1 ✍️")
}
@Test
fun `JUnit reports`() {
val pklFile = writePklFile(contents = bigTest)
writeFile("test.pkl-expected.pcf", bigTestExpected)
writeBuildFile("junitReportsDir = file('${pklFile.parent}/build')")
runTask("evalTest", expectFailure = true)
val outputFile = testProjectDir.resolve("build/test.xml")
val report = outputFile.readText().stripFilesAndLines()
assertThat(report).isEqualTo("""
<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="test" tests="6" failures="4">
<testcase classname="test" name="sum numbers"></testcase>
<testcase classname="test" name="divide numbers"></testcase>
<testcase classname="test" name="fail">
<failure message="Fact Failure">4 == 9 ❌ (file:///file, line x)</failure>
<failure message="Fact Failure">&quot;foo&quot; == &quot;bar&quot; ❌ (file:///file, line x)</failure>
</testcase>
<testcase classname="test" name="user 0"></testcase>
<testcase classname="test" name="user 1">
<failure message="Example Failure">(file:///file, line x)
Expected: (file:///file, line x)
new {
name = &quot;Pigeon&quot;
age = 40
}
Actual: (file:///file, line x)
new {
name = &quot;Pigeon&quot;
age = 41
}</failure>
</testcase>
<testcase classname="test" name="user 1">
<failure message="Example Failure">(file:///file, line x)
Expected: (file:///file, line x)
new {
name = &quot;Parrot&quot;
age = 35
}
Actual: (file:///file, line x)
new {
name = &quot;Welma&quot;
age = 35
}</failure>
</testcase>
<system-err><![CDATA[8 = 8
]]></system-err>
</testsuite>
""".trimIndent())
}
private val bigTest = """
amends "pkl:test"
local function sum(a, b) = a + b
facts {
["sum numbers"] {
sum(3, 5) == trace(8)
sum(3, 0) == 3
}
["divide numbers"] {
(8 / 4) == 2
(12 / 2) == 6
}
["fail"] {
4 == 9
"foo" == "bar"
}
}
examples {
["user 0"] {
new {
name = "Cool"
age = 11
}
}
["user 1"] {
new {
name = "Pigeon"
age = 41
}
new {
name = "Welma"
age = 35
}
}
}
""".trimIndent()
private val bigTestExpected = """
examples {
["user 0"] {
new {
name = "Cool"
age = 11
}
}
["user 1"] {
new {
name = "Pigeon"
age = 40
}
new {
name = "Parrot"
age = 35
}
}
}
""".trimIndent()
private fun writeBuildFile(additionalContents: String = "") {
writeFile(
"build.gradle", """
plugins {
id "org.pkl-lang"
}
pkl {
tests {
evalTest {
sourceModules = ["test.pkl"]
settingsModule = "pkl:settings"
$additionalContents
}
}
}
"""
)
}
private fun writePklFile(
additionalFacts: String = "",
additionalExamples: String = "",
contents: String = """
amends "pkl:test"
facts {
["should pass"] {
1 == 1
10 == 10
}
$additionalFacts
}
examples {
$additionalExamples
}
"""
): Path {
return writeFile("test.pkl", contents)
}
private fun String.stripFilesAndLines(): String =
replace(Regex("""\(file:///.*, line \d+\)"""), "(file:///file, line x)")
}