mirror of
https://github.com/apple/pkl.git
synced 2026-01-11 22:30:54 +01:00
Run spotless apply
This commit is contained in:
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
plugins {
|
||||
pklAllProjects
|
||||
pklJavaLibrary
|
||||
@@ -15,21 +30,19 @@ dependencies {
|
||||
compileOnly(projects.pklTools)
|
||||
|
||||
// Declare a `runtimeOnly` dependency on `project(":pkl-tools", "fatJar")`
|
||||
// to ensure that the published plugin
|
||||
// (and also plugin tests, see the generated `plugin-under-test-metadata.properties`)
|
||||
// to ensure that the published plugin
|
||||
// (and also plugin tests, see the generated `plugin-under-test-metadata.properties`)
|
||||
// only depends on the pkl-tools shaded fat JAR.
|
||||
// This avoids dependency version conflicts with other Gradle plugins.
|
||||
//
|
||||
// Hide this dependency from IntelliJ
|
||||
// Hide this dependency from IntelliJ
|
||||
// to prevent IntelliJ from reindexing the pkl-tools fat JAR after every build.
|
||||
// (IntelliJ gets everything it needs from the `compileOnly` dependency.)
|
||||
//
|
||||
// To debug shaded code in IntelliJ, temporarily remove the conditional.
|
||||
if (System.getProperty("idea.sync.active") == null) {
|
||||
runtimeOnly(projects.pklTools) {
|
||||
attributes {
|
||||
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.SHADOWED))
|
||||
}
|
||||
attributes { attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.SHADOWED)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,34 +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.gradle
|
||||
|
||||
import org.pkl.commons.createParentDirectories
|
||||
import org.pkl.commons.readString
|
||||
import org.pkl.commons.writeString
|
||||
import java.net.URI
|
||||
import java.nio.file.Path
|
||||
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
|
||||
import org.pkl.commons.createParentDirectories
|
||||
import org.pkl.commons.readString
|
||||
import org.pkl.commons.writeString
|
||||
|
||||
abstract class AbstractTest {
|
||||
private val gradleVersion: String? = System.getProperty("testGradleVersion")
|
||||
|
||||
private val gradleDistributionUrl: String? = System.getProperty("testGradleDistributionUrl")
|
||||
|
||||
@TempDir
|
||||
protected lateinit var testProjectDir: Path
|
||||
@TempDir protected lateinit var testProjectDir: Path
|
||||
|
||||
protected fun runTask(
|
||||
taskName: String,
|
||||
expectFailure: Boolean = false
|
||||
): BuildResult {
|
||||
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)
|
||||
val runner =
|
||||
GradleRunner.create()
|
||||
.withProjectDir(testProjectDir.toFile())
|
||||
.withArguments("--stacktrace", "--no-build-cache", taskName)
|
||||
.withPluginClasspath()
|
||||
.withDebug(true)
|
||||
|
||||
if (gradleVersion != null) {
|
||||
runner.withGradleVersion(gradleVersion)
|
||||
@@ -45,15 +57,15 @@ abstract class AbstractTest {
|
||||
}
|
||||
|
||||
protected fun writeFile(fileName: String, contents: String): Path {
|
||||
return testProjectDir.resolve(fileName)
|
||||
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())
|
||||
assertThat(file.readString().trim()).isEqualTo(contents.trim())
|
||||
}
|
||||
|
||||
protected fun checkTextContains(text: String, vararg contents: String) {
|
||||
|
||||
@@ -1,14 +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.gradle
|
||||
|
||||
import org.assertj.core.api.Assertions
|
||||
import org.pkl.commons.readString
|
||||
import org.pkl.commons.readString
|
||||
import org.pkl.commons.test.PackageServer
|
||||
import org.pkl.commons.toNormalizedPathString
|
||||
import java.nio.file.Path
|
||||
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
|
||||
import org.pkl.commons.readString
|
||||
import org.pkl.commons.test.PackageServer
|
||||
|
||||
class EvaluatorsTest : AbstractTest() {
|
||||
@Test
|
||||
@@ -21,12 +33,14 @@ class EvaluatorsTest : AbstractTest() {
|
||||
|
||||
val outputFile = testProjectDir.resolve("test.pcf")
|
||||
checkFileContents(
|
||||
outputFile, """
|
||||
outputFile,
|
||||
"""
|
||||
person {
|
||||
name = "Pigeon"
|
||||
age = 30
|
||||
}
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -40,11 +54,13 @@ class EvaluatorsTest : AbstractTest() {
|
||||
|
||||
val outputFile = testProjectDir.resolve("test.yaml")
|
||||
checkFileContents(
|
||||
outputFile, """
|
||||
outputFile,
|
||||
"""
|
||||
person:
|
||||
name: Pigeon
|
||||
age: 30
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -58,14 +74,16 @@ class EvaluatorsTest : AbstractTest() {
|
||||
|
||||
val outputFile = testProjectDir.resolve("test.json")
|
||||
checkFileContents(
|
||||
outputFile, """
|
||||
outputFile,
|
||||
"""
|
||||
{
|
||||
"person": {
|
||||
"name": "Pigeon",
|
||||
"age": 30
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -79,7 +97,8 @@ class EvaluatorsTest : AbstractTest() {
|
||||
|
||||
val outputFile = testProjectDir.resolve("test.plist")
|
||||
checkFileContents(
|
||||
outputFile, """
|
||||
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">
|
||||
@@ -93,16 +112,19 @@ class EvaluatorsTest : AbstractTest() {
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `set external properties`() {
|
||||
writeBuildFile(
|
||||
"pcf", """
|
||||
"pcf",
|
||||
"""
|
||||
externalProperties = [prop1: "value1", prop2: "value2"]
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
writePklFile(
|
||||
@@ -110,18 +132,21 @@ class EvaluatorsTest : AbstractTest() {
|
||||
prop1 = read("prop:prop1")
|
||||
prop2 = read("prop:prop2")
|
||||
other = read?("prop:other")
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
runTask("evalTest")
|
||||
|
||||
val outputFile = testProjectDir.resolve("test.pcf")
|
||||
checkFileContents(
|
||||
outputFile, """
|
||||
outputFile,
|
||||
"""
|
||||
prop1 = "value1"
|
||||
prop2 = "value2"
|
||||
other = null
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -134,27 +159,32 @@ class EvaluatorsTest : AbstractTest() {
|
||||
prop1 = read?("env:USER")
|
||||
prop2 = read?("env:PATH")
|
||||
prop3 = read?("env:JAVA_HOME")
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
runTask("evalTest")
|
||||
|
||||
val outputFile = testProjectDir.resolve("test.pcf")
|
||||
checkFileContents(
|
||||
outputFile, """
|
||||
outputFile,
|
||||
"""
|
||||
prop1 = null
|
||||
prop2 = null
|
||||
prop3 = null
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `set environment variables`() {
|
||||
writeBuildFile(
|
||||
"pcf", """
|
||||
"pcf",
|
||||
"""
|
||||
environmentVariables = [VAR1: "value1", VAR2: "value2"]
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
writePklFile(
|
||||
@@ -162,25 +192,29 @@ class EvaluatorsTest : AbstractTest() {
|
||||
prop1 = read("env:VAR1")
|
||||
prop2 = read("env:VAR2")
|
||||
other = read?("env:OTHER")
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
runTask("evalTest")
|
||||
|
||||
val outputFile = testProjectDir.resolve("test.pcf")
|
||||
checkFileContents(
|
||||
outputFile, """
|
||||
outputFile,
|
||||
"""
|
||||
prop1 = "value1"
|
||||
prop2 = "value2"
|
||||
other = null
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `no source modules`() {
|
||||
writeFile(
|
||||
"build.gradle", """
|
||||
"build.gradle",
|
||||
"""
|
||||
plugins {
|
||||
id "org.pkl-lang"
|
||||
}
|
||||
@@ -202,7 +236,8 @@ class EvaluatorsTest : AbstractTest() {
|
||||
@Test
|
||||
fun `source module URIs`() {
|
||||
writeFile(
|
||||
"testDir/test.pkl", """
|
||||
"testDir/test.pkl",
|
||||
"""
|
||||
person {
|
||||
name = "Pigeon"
|
||||
age = 20 + 10
|
||||
@@ -211,7 +246,8 @@ class EvaluatorsTest : AbstractTest() {
|
||||
)
|
||||
|
||||
writeFile(
|
||||
"build.gradle", """
|
||||
"build.gradle",
|
||||
"""
|
||||
plugins {
|
||||
id "org.pkl-lang"
|
||||
}
|
||||
@@ -233,19 +269,22 @@ class EvaluatorsTest : AbstractTest() {
|
||||
|
||||
val outputFile = testProjectDir.resolve("test.pcf")
|
||||
checkFileContents(
|
||||
outputFile, """
|
||||
outputFile,
|
||||
"""
|
||||
person {
|
||||
name = "Pigeon"
|
||||
age = 30
|
||||
}
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `cannot evaluate module located outside evalRootDir`() {
|
||||
writeFile(
|
||||
"build.gradle", """
|
||||
"build.gradle",
|
||||
"""
|
||||
plugins {
|
||||
id "org.pkl-lang"
|
||||
}
|
||||
@@ -264,17 +303,18 @@ class EvaluatorsTest : AbstractTest() {
|
||||
|
||||
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`).")
|
||||
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", """
|
||||
writeBuildFile("pcf", """
|
||||
evalTimeout = java.time.Duration.ofMillis(100)
|
||||
"""
|
||||
)
|
||||
""")
|
||||
|
||||
writePklFile(
|
||||
"""
|
||||
@@ -291,7 +331,8 @@ class EvaluatorsTest : AbstractTest() {
|
||||
fun `module output separator`() {
|
||||
val outputFile = testProjectDir.resolve("test.pcf")
|
||||
writeFile(
|
||||
"build.gradle", """
|
||||
"build.gradle",
|
||||
"""
|
||||
plugins {
|
||||
id "org.pkl-lang"
|
||||
}
|
||||
@@ -309,32 +350,34 @@ class EvaluatorsTest : AbstractTest() {
|
||||
"""
|
||||
)
|
||||
|
||||
writeFile(
|
||||
"test1.pkl",
|
||||
"foo = 1"
|
||||
)
|
||||
writeFile(
|
||||
"test2.pkl",
|
||||
"bar = 2"
|
||||
)
|
||||
writeFile("test1.pkl", "foo = 1")
|
||||
writeFile("test2.pkl", "bar = 2")
|
||||
runTask("evalTask")
|
||||
|
||||
checkFileContents(outputFile, """
|
||||
checkFileContents(
|
||||
outputFile,
|
||||
"""
|
||||
foo = 1
|
||||
// hello
|
||||
bar = 2
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `compliant file URIs`() {
|
||||
writeBuildFile("pcf")
|
||||
writeFile("test.pkl", """
|
||||
writeFile(
|
||||
"test.pkl",
|
||||
"""
|
||||
import "pkl:reflect"
|
||||
output {
|
||||
text = reflect.Module(module).uri
|
||||
}
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
runTask("evalTest")
|
||||
|
||||
@@ -345,9 +388,13 @@ class EvaluatorsTest : AbstractTest() {
|
||||
|
||||
@Test
|
||||
fun `multiple file output`() {
|
||||
writeBuildFile("pcf", """
|
||||
writeBuildFile(
|
||||
"pcf",
|
||||
"""
|
||||
multipleFileOutputDir = layout.projectDirectory.dir("my-output")
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
writeFile(
|
||||
"test.pkl",
|
||||
"""
|
||||
@@ -361,7 +408,8 @@ class EvaluatorsTest : AbstractTest() {
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
runTask("evalTest")
|
||||
checkFileContents(testProjectDir.resolve("my-output/output-1.txt"), "My output 1")
|
||||
@@ -370,17 +418,22 @@ class EvaluatorsTest : AbstractTest() {
|
||||
|
||||
@Test
|
||||
fun expression() {
|
||||
writeBuildFile("yaml", """
|
||||
writeBuildFile(
|
||||
"yaml",
|
||||
"""
|
||||
expression = "metadata.name"
|
||||
outputFile = layout.projectDirectory.file("output.txt")
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
writeFile(
|
||||
"test.pkl",
|
||||
"""
|
||||
metadata {
|
||||
name = "Uni"
|
||||
}
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
runTask("evalTest")
|
||||
checkFileContents(testProjectDir.resolve("output.txt"), "Uni")
|
||||
@@ -388,26 +441,33 @@ class EvaluatorsTest : AbstractTest() {
|
||||
|
||||
@Test
|
||||
fun `explicitly set cache dir`(@TempDir tempDir: Path) {
|
||||
writeBuildFile("pcf", """
|
||||
writeBuildFile(
|
||||
"pcf",
|
||||
"""
|
||||
moduleCacheDir = file("${tempDir.toUri()}")
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
writeFile(
|
||||
"test.pkl",
|
||||
"""
|
||||
import "package://localhost:0/birds@0.5.0#/Bird.pkl"
|
||||
|
||||
res = new Bird { name = "Wally"; favoriteFruit { name = "bananas" } }
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
PackageServer.populateCacheDir(tempDir)
|
||||
runTask("evalTest")
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `explicitly set project dir`() {
|
||||
writeBuildFile("pcf", "projectDir = file(\"proj1\")", listOf("proj1/foo.pkl"))
|
||||
|
||||
writeFile("proj1/PklProject", """
|
||||
|
||||
writeFile(
|
||||
"proj1/PklProject",
|
||||
"""
|
||||
amends "pkl:Project"
|
||||
|
||||
dependencies {
|
||||
@@ -420,9 +480,13 @@ class EvaluatorsTest : AbstractTest() {
|
||||
version = "1.0.0"
|
||||
packageZipUrl = "https://localhost:0/\(name)@\(version).zip"
|
||||
}
|
||||
""".trimIndent())
|
||||
|
||||
writeFile("proj2/PklProject", """
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
writeFile(
|
||||
"proj2/PklProject",
|
||||
"""
|
||||
amends "pkl:Project"
|
||||
|
||||
package {
|
||||
@@ -431,9 +495,13 @@ class EvaluatorsTest : AbstractTest() {
|
||||
version = "1.0.0"
|
||||
packageZipUrl = "https://localhost:0/\(name)@\(version).zip"
|
||||
}
|
||||
""".trimIndent())
|
||||
|
||||
writeFile("proj1/PklProject.deps.json", """
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
writeFile(
|
||||
"proj1/PklProject.deps.json",
|
||||
"""
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"resolvedDependencies": {
|
||||
@@ -444,38 +512,53 @@ class EvaluatorsTest : AbstractTest() {
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
|
||||
writeFile("proj2/PklProject.deps.json", """
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
writeFile(
|
||||
"proj2/PklProject.deps.json",
|
||||
"""
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"resolvedDependencies": {}
|
||||
}
|
||||
""".trimIndent())
|
||||
|
||||
writeFile("proj1/foo.pkl", """
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
writeFile(
|
||||
"proj1/foo.pkl",
|
||||
"""
|
||||
module proj1.foo
|
||||
|
||||
bar: String = import("@proj2/baz.pkl").qux
|
||||
""".trimIndent())
|
||||
|
||||
writeFile("proj2/baz.pkl", """
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
writeFile(
|
||||
"proj2/baz.pkl",
|
||||
"""
|
||||
qux: String = "Contents of @proj2/qux"
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
runTask("evalTest")
|
||||
assertThat(testProjectDir.resolve("proj1/foo.pcf")).exists()
|
||||
}
|
||||
|
||||
private fun writeBuildFile(
|
||||
// don't use `org.pkl.core.OutputFormat`
|
||||
// don't use `org.pkl.core.OutputFormat`
|
||||
// because test compile class path doesn't contain pkl-core
|
||||
outputFormat: String,
|
||||
outputFormat: String,
|
||||
additionalContents: String = "",
|
||||
sourceModules: List<String> = listOf("test.pkl")
|
||||
) {
|
||||
writeFile(
|
||||
"build.gradle", """
|
||||
"build.gradle",
|
||||
"""
|
||||
plugins {
|
||||
id "org.pkl-lang"
|
||||
}
|
||||
|
||||
@@ -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.gradle
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.io.path.listDirectoryEntries
|
||||
import kotlin.io.path.readText
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class JavaCodeGeneratorsTest : AbstractTest() {
|
||||
@Test
|
||||
@@ -12,7 +27,7 @@ class JavaCodeGeneratorsTest : AbstractTest() {
|
||||
writePklFile()
|
||||
|
||||
runTask("configClasses")
|
||||
|
||||
|
||||
val baseDir = testProjectDir.resolve("build/generated/java/foo/bar")
|
||||
val moduleFile = baseDir.resolve("Mod.java")
|
||||
|
||||
@@ -23,16 +38,18 @@ class JavaCodeGeneratorsTest : AbstractTest() {
|
||||
|
||||
// shading must not affect generated code
|
||||
assertThat(text).doesNotContain("org.pkl.thirdparty")
|
||||
|
||||
|
||||
checkTextContains(
|
||||
text, """
|
||||
text,
|
||||
"""
|
||||
|public final class Mod {
|
||||
| public final @Nonnull Object other;
|
||||
"""
|
||||
)
|
||||
|
||||
checkTextContains(
|
||||
text, """
|
||||
text,
|
||||
"""
|
||||
| public static final class Person {
|
||||
| public final @Nonnull String name;
|
||||
|
|
||||
@@ -41,7 +58,8 @@ class JavaCodeGeneratorsTest : AbstractTest() {
|
||||
)
|
||||
|
||||
checkTextContains(
|
||||
text, """
|
||||
text,
|
||||
"""
|
||||
| public static final class Address {
|
||||
| public final @Nonnull String street;
|
||||
|
|
||||
@@ -54,7 +72,7 @@ class JavaCodeGeneratorsTest : AbstractTest() {
|
||||
fun `compile generated code`() {
|
||||
writeBuildFile()
|
||||
writePklFile()
|
||||
|
||||
|
||||
runTask("compileJava")
|
||||
|
||||
val classesDir = testProjectDir.resolve("build/classes/java/main")
|
||||
@@ -65,11 +83,12 @@ class JavaCodeGeneratorsTest : AbstractTest() {
|
||||
assertThat(personClassFile).exists()
|
||||
assertThat(addressClassFile).exists()
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `no source modules`() {
|
||||
writeFile(
|
||||
"build.gradle", """
|
||||
"build.gradle",
|
||||
"""
|
||||
plugins {
|
||||
id "org.pkl-lang"
|
||||
}
|
||||
@@ -90,7 +109,8 @@ class JavaCodeGeneratorsTest : AbstractTest() {
|
||||
|
||||
private fun writeBuildFile() {
|
||||
writeFile(
|
||||
"build.gradle", """
|
||||
"build.gradle",
|
||||
"""
|
||||
plugins {
|
||||
id "java"
|
||||
id "org.pkl-lang"
|
||||
@@ -125,7 +145,8 @@ class JavaCodeGeneratorsTest : AbstractTest() {
|
||||
|
||||
private fun writePklFile() {
|
||||
writeFile(
|
||||
"mod.pkl", """
|
||||
"mod.pkl",
|
||||
"""
|
||||
module org.mod
|
||||
|
||||
class Person {
|
||||
|
||||
@@ -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.gradle
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.io.path.listDirectoryEntries
|
||||
import kotlin.io.path.readText
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class KotlinCodeGeneratorsTest : AbstractTest() {
|
||||
@Test
|
||||
@@ -24,16 +39,15 @@ class KotlinCodeGeneratorsTest : AbstractTest() {
|
||||
// shading must not affect generated code
|
||||
assertThat(text).doesNotContain("org.pkl.thirdparty")
|
||||
|
||||
checkTextContains(
|
||||
text, """
|
||||
checkTextContains(text, """
|
||||
|data class Mod(
|
||||
| val other: Any?
|
||||
|)
|
||||
"""
|
||||
)
|
||||
""")
|
||||
|
||||
checkTextContains(
|
||||
text, """
|
||||
text,
|
||||
"""
|
||||
| data class Person(
|
||||
| val name: String,
|
||||
| val addresses: List<Address>
|
||||
@@ -42,7 +56,8 @@ class KotlinCodeGeneratorsTest : AbstractTest() {
|
||||
)
|
||||
|
||||
checkTextContains(
|
||||
text, """
|
||||
text,
|
||||
"""
|
||||
| open class Address(
|
||||
| open val street: String,
|
||||
| open val zip: Long
|
||||
@@ -65,11 +80,12 @@ class KotlinCodeGeneratorsTest : AbstractTest() {
|
||||
assertThat(personClassFile).exists()
|
||||
assertThat(addressClassFile).exists()
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `no source modules`() {
|
||||
writeFile(
|
||||
"build.gradle", """
|
||||
"build.gradle",
|
||||
"""
|
||||
plugins {
|
||||
id "org.pkl-lang"
|
||||
}
|
||||
@@ -92,7 +108,8 @@ class KotlinCodeGeneratorsTest : AbstractTest() {
|
||||
val kotlinVersion = "1.6.0"
|
||||
|
||||
writeFile(
|
||||
"build.gradle", """
|
||||
"build.gradle",
|
||||
"""
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
@@ -134,10 +151,11 @@ class KotlinCodeGeneratorsTest : AbstractTest() {
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
private fun writePklFile() {
|
||||
writeFile(
|
||||
"mod.pkl", """
|
||||
"mod.pkl",
|
||||
"""
|
||||
module org.mod
|
||||
|
||||
class Person {
|
||||
|
||||
@@ -1,14 +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.gradle
|
||||
|
||||
import kotlin.io.path.readText
|
||||
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", """
|
||||
"build.gradle",
|
||||
"""
|
||||
plugins {
|
||||
id "org.pkl-lang"
|
||||
}
|
||||
@@ -25,7 +41,8 @@ class PkldocGeneratorsTest : AbstractTest() {
|
||||
"""
|
||||
)
|
||||
writeFile(
|
||||
"doc-package-info.pkl", """
|
||||
"doc-package-info.pkl",
|
||||
"""
|
||||
/// A test package.
|
||||
amends "pkl:DocPackageInfo"
|
||||
name = "test"
|
||||
@@ -34,10 +51,12 @@ class PkldocGeneratorsTest : AbstractTest() {
|
||||
authors { "publisher@apple.com" }
|
||||
sourceCode = "sources.apple.com/"
|
||||
issueTracker = "issues.apple.com"
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
writeFile(
|
||||
"person.pkl", """
|
||||
"person.pkl",
|
||||
"""
|
||||
module test.person
|
||||
|
||||
class Person {
|
||||
@@ -51,7 +70,8 @@ class PkldocGeneratorsTest : AbstractTest() {
|
||||
}
|
||||
|
||||
other = 42
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
runTask("pkldoc")
|
||||
@@ -79,7 +99,8 @@ class PkldocGeneratorsTest : AbstractTest() {
|
||||
@Test
|
||||
fun `no source modules`() {
|
||||
writeFile(
|
||||
"build.gradle", """
|
||||
"build.gradle",
|
||||
"""
|
||||
plugins {
|
||||
id "org.pkl-lang"
|
||||
}
|
||||
@@ -90,7 +111,8 @@ class PkldocGeneratorsTest : AbstractTest() {
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
val result = runTask("pkldoc", true)
|
||||
|
||||
@@ -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.gradle
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
@@ -13,13 +28,14 @@ class ProjectPackageTest : AbstractTest() {
|
||||
assertThat(testProjectDir.resolve("build/generated/pkl/packages/proj1@1.0.0")).exists()
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `custom output dir`() {
|
||||
writeBuildFile( """
|
||||
writeBuildFile(
|
||||
"""
|
||||
outputPath.set(file("thepackages"))
|
||||
skipPublishCheck.set(true)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
writeProjectContent()
|
||||
runTask("createMyPackages")
|
||||
assertThat(testProjectDir.resolve("thepackages/proj1@1.0.0.zip")).exists()
|
||||
@@ -28,10 +44,13 @@ class ProjectPackageTest : AbstractTest() {
|
||||
|
||||
@Test
|
||||
fun `junit dir`() {
|
||||
writeBuildFile("""
|
||||
writeBuildFile(
|
||||
"""
|
||||
junitReportsDir.set(file("test-reports"))
|
||||
skipPublishCheck.set(true)
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
writeProjectContent()
|
||||
runTask("createMyPackages")
|
||||
assertThat(testProjectDir.resolve("test-reports")).isNotEmptyDirectory()
|
||||
@@ -39,7 +58,8 @@ class ProjectPackageTest : AbstractTest() {
|
||||
|
||||
private fun writeBuildFile(additionalContents: String = "") {
|
||||
writeFile(
|
||||
"build.gradle", """
|
||||
"build.gradle",
|
||||
"""
|
||||
plugins {
|
||||
id "org.pkl-lang"
|
||||
}
|
||||
@@ -60,7 +80,9 @@ class ProjectPackageTest : AbstractTest() {
|
||||
}
|
||||
|
||||
private fun writeProjectContent() {
|
||||
writeFile("proj1/PklProject", """
|
||||
writeFile(
|
||||
"proj1/PklProject",
|
||||
"""
|
||||
amends "pkl:Project"
|
||||
|
||||
package {
|
||||
@@ -72,19 +94,31 @@ class ProjectPackageTest : AbstractTest() {
|
||||
"tests.pkl"
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
writeFile("proj1/PklProject.deps.json", """
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
writeFile(
|
||||
"proj1/PklProject.deps.json",
|
||||
"""
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"dependencies": {}
|
||||
}
|
||||
""".trimIndent())
|
||||
writeFile("proj1/foo.pkl", """
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
writeFile(
|
||||
"proj1/foo.pkl",
|
||||
"""
|
||||
module proj1.foo
|
||||
|
||||
bar: String
|
||||
""".trimIndent())
|
||||
writeFile("proj1/tests.pkl", """
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
writeFile(
|
||||
"proj1/tests.pkl",
|
||||
"""
|
||||
amends "pkl:test"
|
||||
|
||||
facts {
|
||||
@@ -92,7 +126,9 @@ class ProjectPackageTest : AbstractTest() {
|
||||
1 == 1
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
writeFile("foo.txt", "The contents of foo.txt")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.gradle
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
@@ -9,17 +24,22 @@ class ProjectResolveTest : AbstractTest() {
|
||||
writeBuildFile()
|
||||
writeProjectContent()
|
||||
runTask("resolveMyProj")
|
||||
assertThat(testProjectDir.resolve("proj1/PklProject.deps.json")).hasContent("""
|
||||
assertThat(testProjectDir.resolve("proj1/PklProject.deps.json"))
|
||||
.hasContent(
|
||||
"""
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"resolvedDependencies": {}
|
||||
}
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
private fun writeBuildFile(additionalContents: String = "") {
|
||||
writeFile(
|
||||
"build.gradle", """
|
||||
"build.gradle",
|
||||
"""
|
||||
plugins {
|
||||
id "org.pkl-lang"
|
||||
}
|
||||
@@ -40,8 +60,12 @@ class ProjectResolveTest : AbstractTest() {
|
||||
}
|
||||
|
||||
private fun writeProjectContent() {
|
||||
writeFile("proj1/PklProject", """
|
||||
writeFile(
|
||||
"proj1/PklProject",
|
||||
"""
|
||||
amends "pkl:Project"
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.gradle
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.pkl.commons.toNormalizedPathString
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.readText
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.pkl.commons.toNormalizedPathString
|
||||
|
||||
class TestsTest : AbstractTest() {
|
||||
|
||||
@@ -22,12 +37,16 @@ class TestsTest : AbstractTest() {
|
||||
fun `facts fail`() {
|
||||
writeBuildFile()
|
||||
|
||||
writePklFile(additionalFacts = """
|
||||
writePklFile(
|
||||
additionalFacts =
|
||||
"""
|
||||
["should fail"] {
|
||||
1 == 3
|
||||
"foo" == "bar"
|
||||
}
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
val res = runTask("evalTest", expectFailure = true)
|
||||
assertThat(res.output).contains("should fail ❌")
|
||||
@@ -39,15 +58,21 @@ class TestsTest : AbstractTest() {
|
||||
fun error() {
|
||||
writeBuildFile()
|
||||
|
||||
writePklFile(additionalFacts = """
|
||||
writePklFile(
|
||||
additionalFacts =
|
||||
"""
|
||||
["error"] {
|
||||
throw("exception")
|
||||
}
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
val output = runTask("evalTest", expectFailure = true).output.stripFilesAndLines()
|
||||
|
||||
assertThat(output).contains("""
|
||||
assertThat(output)
|
||||
.contains(
|
||||
"""
|
||||
module test (file:///file, line x)
|
||||
test ❌
|
||||
Error:
|
||||
@@ -61,7 +86,9 @@ class TestsTest : AbstractTest() {
|
||||
3 | facts {
|
||||
^^^^^^^
|
||||
at test#facts (file:///file, line x)
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -73,7 +100,9 @@ class TestsTest : AbstractTest() {
|
||||
|
||||
val output = runTask("evalTest", expectFailure = true).output.stripFilesAndLines()
|
||||
|
||||
assertThat(output.trimStart()).contains("""
|
||||
assertThat(output.trimStart())
|
||||
.contains(
|
||||
"""
|
||||
module test (file:///file, line x)
|
||||
sum numbers ✅
|
||||
divide numbers ✅
|
||||
@@ -105,12 +134,16 @@ class TestsTest : AbstractTest() {
|
||||
name = "Welma"
|
||||
age = 35
|
||||
}
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `overwrite expected examples`() {
|
||||
writePklFile(additionalExamples = """
|
||||
writePklFile(
|
||||
additionalExamples =
|
||||
"""
|
||||
["user 0"] {
|
||||
new {
|
||||
name = "Cool"
|
||||
@@ -127,7 +160,9 @@ class TestsTest : AbstractTest() {
|
||||
age = 35
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
writeFile("test.pkl-expected.pcf", bigTestExpected)
|
||||
|
||||
writeBuildFile("overwrite = true")
|
||||
@@ -150,7 +185,9 @@ class TestsTest : AbstractTest() {
|
||||
val outputFile = testProjectDir.resolve("build/test.xml")
|
||||
val report = outputFile.readText().stripFilesAndLines()
|
||||
|
||||
assertThat(report).isEqualTo("""
|
||||
assertThat(report)
|
||||
.isEqualTo(
|
||||
"""
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuite name="test" tests="6" failures="4">
|
||||
<testcase classname="test" name="sum numbers"></testcase>
|
||||
@@ -190,10 +227,13 @@ class TestsTest : AbstractTest() {
|
||||
]]></system-err>
|
||||
</testsuite>
|
||||
|
||||
""".trimIndent())
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
private val bigTest = """
|
||||
private val bigTest =
|
||||
"""
|
||||
amends "pkl:test"
|
||||
|
||||
local function sum(a, b) = a + b
|
||||
@@ -231,9 +271,11 @@ class TestsTest : AbstractTest() {
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
|
||||
private val bigTestExpected = """
|
||||
private val bigTestExpected =
|
||||
"""
|
||||
examples {
|
||||
["user 0"] {
|
||||
new {
|
||||
@@ -252,11 +294,13 @@ class TestsTest : AbstractTest() {
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
"""
|
||||
.trimIndent()
|
||||
|
||||
private fun writeBuildFile(additionalContents: String = "") {
|
||||
writeFile(
|
||||
"build.gradle", """
|
||||
"build.gradle",
|
||||
"""
|
||||
plugins {
|
||||
id "org.pkl-lang"
|
||||
}
|
||||
@@ -277,7 +321,8 @@ class TestsTest : AbstractTest() {
|
||||
private fun writePklFile(
|
||||
additionalFacts: String = "",
|
||||
additionalExamples: String = "",
|
||||
contents: String = """
|
||||
contents: String =
|
||||
"""
|
||||
amends "pkl:test"
|
||||
|
||||
facts {
|
||||
|
||||
Reference in New Issue
Block a user