fix(test): a generic function called from a test block works
Test blocks were never type-checked, and the checker is what makes a generic call real; they are checked like entry now. Reseed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
9faaa2094d
commit
a2012a5afe
7 changed files with 10045 additions and 9933 deletions
|
|
@ -1782,7 +1782,8 @@ ludicc app.ludic --emit-llvm -o app.ll # stop at LLVM IR
|
|||
```
|
||||
|
||||
A test program is a file of `test "name" { ... }` blocks with `expect(cond)`, `expect_eq(a, b)` and
|
||||
`expect_near(a, b, tol)` in them. `ludic test` finds `tests/*.ludic` and `src/**/*_test.ludic`;
|
||||
`expect_near(a, b, tol)` in them; a test block is type-checked like `entry`, so a generic function
|
||||
called from one works as it does anywhere. `ludic test` finds `tests/*.ludic` and `src/**/*_test.ludic`;
|
||||
given a directory, it runs every `*_test.ludic` under it and every file straight inside a `tests/`
|
||||
directory under it. **Each test block runs in a process of its own**, so a global one test changes
|
||||
is back to its initial value in the next - no test depends on another having run, or not. A
|
||||
|
|
|
|||
5
changes/test-generics.md
Normal file
5
changes/test-generics.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
bump: patch
|
||||
type: fix
|
||||
**A generic function called from a `test` block works.** Test blocks were never type-checked, and
|
||||
the checker is what makes a generic call real, so `q_new()` inside a test was "unknown function".
|
||||
They are checked like `entry` now - which also means a type error in a test is reported.
|
||||
25
examples/library/testing_generic.ludic
Normal file
25
examples/library/testing_generic.ludic
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# testing_generic.ludic — a test block is checked like `entry`, so a generic function called from
|
||||
# one is made real for its type arguments there, as it is from any function. Its runner prints:
|
||||
# == 2 passed, 0 failed ==
|
||||
program TestingGeneric {
|
||||
property Box<T> { items: []T = null }
|
||||
function box_new<T>() -> Box<T> {
|
||||
let b = new Box<T>
|
||||
b.items = new []T
|
||||
return b
|
||||
}
|
||||
function box_push<T>(b: Box<T>, v: T) -> void {
|
||||
push(b.items, v)
|
||||
}
|
||||
test "a generic call in a test" {
|
||||
let b: Box<int> = box_new()
|
||||
box_push(b, 4)
|
||||
box_push(b, 5)
|
||||
expect_eq(len(b.items), 2)
|
||||
}
|
||||
test "another instance of it" {
|
||||
let b: Box<string> = box_new()
|
||||
box_push(b, "trout")
|
||||
expect(b.items[0] == "trout")
|
||||
}
|
||||
}
|
||||
|
|
@ -185,6 +185,12 @@ function check_program() -> void {
|
|||
ck_listener(g_onlisten[j])
|
||||
j += 1
|
||||
}
|
||||
# a test block is checked like `entry`: that is also what makes its generic calls real
|
||||
j = 0
|
||||
while j < len(g_tests) {
|
||||
ck_block(g_tests[j].a)
|
||||
j += 1
|
||||
}
|
||||
gen_finish()
|
||||
if ck_errors > 0 and not ck_reporting() {
|
||||
let m = `{itoa(ck_errors)} type error(s)\n`
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -713,6 +713,7 @@ function cmd_dev_test() -> int {
|
|||
controller_case("library/combat_kit", "xxxxxxxxxxxx", "6846 153196 31 107110 6000 5002 1 80 97 11 10 700 110", "combat_kit.ludic (Dash, Melee + MeleeHit, build stats in Combat.damage + Crit, Stats.add, Dungeon arena / exits / entry points, Prefs.max)")
|
||||
controller_case("games/rpg_demo", "", "1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1", "rpg_demo.ludic (ludic.rpg #59 all 7 modules: grid move+veto+interact, inventory+equip, crafting, quests, dialog graph, sokoban+signal gate, poison status)")
|
||||
spec_case("library/testing", "== 6 passed, 0 failed ==")
|
||||
spec_case("library/testing_generic", "== 2 passed, 0 failed ==")
|
||||
spec_case("library/coverage", "== 3 passed, 0 failed ==")
|
||||
feat_case("library/errors", "", "5 10 0 7 1", "errors.ludic (assert guards an invariant, holds -> runs to the end; issue #8 success path)")
|
||||
feat_case("library/recover", "", "2600 100 1 1 42 7", "recover.ludic (try/else recovers a result value + fallback, error binding, is_ok/is_err; issue #46)")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue