Implement power assertions (#1384)

This adds power assertions to Pkl!

This implements the SPICE described in
https://github.com/apple/pkl-evolution/pull/29

This follows the power assertions style of reporting also found in
Groovy, Kotlin, and others.

* Literal values are not emitted in the diagram
* Stdlib constructors of literals like `List(1, 2)` are also considered
  literals

Power assertions are added to:

* Failing type constraints
* Failing test facts

Power assertions are implemented as a truffle instrument to observe
execution.
When an assertion fails, the instrument is created and the assertion is
run again to observe facts.
This incurs runtime overhead to collect facts, but has no impact on code
in the non-error case.

---------

Co-authored-by: Islon Scherer <islonscherer@gmail.com>
This commit is contained in:
Daniel Chao
2026-01-20 21:41:33 -08:00
committed by GitHub
parent 3cd294b62a
commit 03a7676e64
107 changed files with 2133 additions and 290 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024-2026 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.
@@ -81,7 +81,7 @@ class CliTestRunnerTest {
facts {
["fail"] {
4 == 9
"foo" != "bar"
1 == 5
}
}
"""
@@ -101,8 +101,13 @@ class CliTestRunnerTest {
facts
✘ fail
4 == 9 (/tempDir/test.pkl, line xx)
false
1 == 5 (/tempDir/test.pkl, line xx)
false
0.0% tests pass [1/1 failed], 50.0% asserts pass [1/2 failed]
0.0% tests pass [1/1 failed], 0.0% asserts pass [2/2 failed]
"""
.trimIndent()
@@ -283,12 +288,14 @@ class CliTestRunnerTest {
<testsuite name="test" tests="2" failures="1">
<testcase classname="test.facts" name="foo"></testcase>
<testcase classname="test.facts" name="bar">
<failure message="Fact Failure">5 == 9 (/tempDir/test.pkl, line xx)</failure>
<failure message="Fact Failure">5 == 9 (/tempDir/test.pkl, line xx)
false</failure>
</testcase>
<system-err><![CDATA[9 = 9
]]></system-err>
</testsuite>
"""
.trimIndent()
)
@@ -481,26 +488,30 @@ class CliTestRunnerTest {
assertThat(junitReport)
.isEqualTo(
"""
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="pkl-tests" tests="5" failures="3">
<testsuite name="test1" tests="2" failures="1">
<testcase classname="test1.facts" name="foo"></testcase>
<testcase classname="test1.facts" name="bar">
<failure message="Fact Failure">5 == 9 (/tempDir/test1.pkl, line xx)</failure>
</testcase>
</testsuite>
<testsuite name="test2" tests="3" failures="2">
<testcase classname="test2.facts" name="xxx">
<failure message="Fact Failure">false (/tempDir/test2.pkl, line xx)</failure>
</testcase>
<testcase classname="test2.facts" name="yyy">
<failure message="Fact Failure">false (/tempDir/test2.pkl, line xx)</failure>
</testcase>
<testcase classname="test2.facts" name="zzz"></testcase>
</testsuite>
</testsuites>
"""
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="pkl-tests" tests="5" failures="3">
<testsuite name="test1" tests="2" failures="1">
<testcase classname="test1.facts" name="foo"></testcase>
<testcase classname="test1.facts" name="bar">
<failure message="Fact Failure">5 == 9 (/tempDir/test1.pkl, line xx)
false</failure>
</testcase>
</testsuite>
<testsuite name="test2" tests="3" failures="2">
<testcase classname="test2.facts" name="xxx">
<failure message="Fact Failure">false (/tempDir/test2.pkl, line xx)
</failure>
</testcase>
<testcase classname="test2.facts" name="yyy">
<failure message="Fact Failure">false (/tempDir/test2.pkl, line xx)
</failure>
</testcase>
<testcase classname="test2.facts" name="zzz"></testcase>
</testsuite>
</testsuites>
"""
.trimIndent()
)
}