on master help sign in
Run the test suites' arms under eval with one runner

Each tests/lib suite had its own script under tools/, 52 in all, and each script started its own eval and built the library again, often several times: type-todo-full-test took 580 to 850 s alone, and the 60 eval checks about 49 minutes of check time. This is review question 29. tools/test-arms runs the test- arms of every tests/lib suite under urbit eval, with the subject Ford gives the suite on the jibb-dev desk: its /+ libraries and /* files, found where tools/ship assemble puts them. Many suites share one eval, so the library is built once. Each arm runs under mule and prints OK, FAILED or CRASHED, as -test does on the ship; a crash's trace is placed in the suite and the library, and a suite that doesn't build is found by retrying one suite at a time. tools/check runs the suites in four shards balanced by measured cost: 55 to 80 s each, about 4.5 minutes of check time for all 56 suites. What the scripts checked outside the arms is kept: - 29 suites with a golden file now have a report arm, so --report prints the report, --update rewrites the file, and a failing arm shows a diff against it. Each report matches its golden byte for byte. - Golden files must end in exactly one newline and hold no BAD line, which the scripts' byte comparisons and BAD scans used to catch. - The fixtures copied from my-app are listed in tests/my-app-copies.txt (49 pairs, some of which no script checked) and compared by the my-app-copies check. The itype-unify-test check goes too: the jibb-typecheck suite runs the same arm. tests/type-api-evidence/expected.txt, which only its script read, is gone. tools/testdata/selftest tests the runner against the stub library. The docs describe each suite where they described its script. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U4FzmSdubYxmZGDp2VJRAQ

commitd74b5e2d4505f7a5ae8249666f60fe8287dab671 authorClaude <noreply@anthropic.com> dateTue 3 Nov 2026, 01:09 (11 hours ago) parentec7c6d4
95 files changed+1059−2492
README.md+38−16 docs/compiler.md+3−3 docs/development.md+74−58 docs/status.md+48−41 tests/lib/jibb-api-paths.hoon+5−2 tests/lib/jibb-bridge.hoon+4−1 tests/lib/jibb-deferred-context.hoon+6−2 tests/lib/jibb-deferred-resolver.hoon+4−1 tests/lib/jibb-deferred.hoon+4−1 tests/lib/jibb-direct-gate-source.hoon+5−1 tests/lib/jibb-empty.hoon+4−2 tests/lib/jibb-full-overlap-basic.hoon+4−1 tests/lib/jibb-full-overlap-graph.hoon+4−1 tests/lib/jibb-gate-free-source.hoon+4−1 tests/lib/jibb-generic-construction.hoon+4−2 tests/lib/jibb-generic-pattern.hoon+4−2 tests/lib/jibb-generic-recursion.hoon+13−10 tests/lib/jibb-import-default.hoon+4−1 tests/lib/jibb-import-diagnostic.hoon+4−1 tests/lib/jibb-import-overlap.hoon+4−1 tests/lib/jibb-import-structural.hoon+4−1 tests/lib/jibb-import.hoon+6−2 tests/lib/jibb-list-alias-guards.hoon+5−1 tests/lib/jibb-mark-bridge.hoon+4−1 tests/lib/jibb-module-scope.hoon+4−1 tests/lib/jibb-poke-bridge.hoon+4−1 tests/lib/jibb-tlon-bridge.hoon+4−1 tests/lib/jibb-todo-api.hoon+7−1 tests/lib/jibb-todo-full.hoon+6−3 tests/lib/jibb-todo-partial.hoon+5−2 tests/lib/jibb-typecheck.hoon+7−5 tests/lib/jibb-union-alias-overlap.hoon+4−1 tests/lib/jibb-union-source.hoon+4−1 tests/my-app-copies.txt+56 tests/type-api-evidence/expected.txt−1 tests/type-gate-free/about.txt+1−1 tests/type-todo-api/about.txt+1−1 tests/type-todo-full/about.txt+1−1 tests/type-todo-partial/about.txt+1−1 tools/check+16−56 tools/importer-test−37 tools/test-arms+568 tools/testdata/selftest+106−3 tools/type-api-evidence-test−40 tools/type-api-paths-test−52 tools/type-arithmetic-guards-test−28 tools/type-ask-guards-test−31 tools/type-buttons-test−40 tools/type-cell-branch-test−43 tools/type-closed-gate-guards-test−29 tools/type-constructor-fit-guards-test−29 tools/type-deferred-context-test−31 tools/type-deferred-prepared-test−49 tools/type-deferred-resolver-test−33 tools/type-deferred-test−32 tools/type-direct-gate-test−64 tools/type-doc-examples-test−49 tools/type-empty-test−55 tools/type-full-overlap-test−49 tools/type-gate-free-guards-test−29 tools/type-gate-free-source-test−50 tools/type-generic-alias-test−28 tools/type-generic-construction-test−49 tools/type-generic-pattern-test−52 tools/type-generic-recursion-test−61 tools/type-hole-guards-test−32 tools/type-import-default-test−38 tools/type-import-diagnostic-test−43 tools/type-import-overlap-test−33 tools/type-import-structural-test−36 tools/type-import-test−39 tools/type-list-alias-test−33 tools/type-mark-test−35 tools/type-module-scope-test−40 tools/type-nested-union-guards-test−29 tools/type-page-main-test−86 tools/type-poke-test−50 tools/type-positional-face-guards-test−29 tools/type-program-init-test−55 tools/type-program-main-test−46 tools/type-program-update-test−46 tools/type-program-watch-test−48 tools/type-proj-guards-test−32 tools/type-qath-guards-test−31 tools/type-request-guards-test−31 tools/type-store-test−41 tools/type-sub-guards-test−31 tools/type-theme-test−44 tools/type-tlon-test−39 tools/type-todo-api-test−62 tools/type-todo-full-test−105 tools/type-todo-partial-test−55 tools/type-union-alias-overlap-test−52 tools/type-union-source-test−55 tools/urbit_eval.py+5−3
README.md+38−16
@@ -10,8 +10,8 @@ Milestone 1 of the doc's eight, the parser and the `%jibb` mark, is done; milest
1010- `jibb/`: the `%jibb` desk, for the shared host (milestone 4).
1111- `my-app/`: an example app desk built from the doc's worked examples.
1212- `vendor/`: pinned copies of the base-dev and landscape files the desks need.
13−- `tests/`: golden cases in `golden/<case>/`, and on-ship tests for the `-test` thread in `lib/jibb.hoon`.
14−- `tools/`: dev tooling: `golden`, `hoon` and `doc-blocks`, with their self-test in `testdata/`, `ship`, and `check`, which runs every check.
13+- `tests/`: golden cases in `golden/<case>/`, test suites in `lib/` and their fixtures, for `tools/test-arms` and the ship's `-test` thread, and `my-app-copies.txt`, the list of fixtures copied from `my-app/`. `lib/jibb.hoon`, which runs the golden cases on the ship, is generated.
14+- `tools/`: dev tooling: `golden`, `test-arms`, `hoon` and `doc-blocks`, with their self-test in `testdata/`, `ship`, and `check`, which runs every check.
1515- `docs/`: the doc's tabs as Markdown in `spec/`, the status, the open questions, the development guide, the compiler's map, and briefs for milestones in `prompts/`.
1616
1717## Building and checking with Nix
@@ -27,7 +27,7 @@ nix build .#fakezod # a freshly booted fake ~zod pier (Linux)
2727
2828Jibb has no native binary: what it ships is desks, Hoon and Jibb source that a ship builds. So `nix build` writes the three desks exactly as `tools/ship sync` would commit them (it runs `tools/ship assemble`), and compiles `jibb.hoon` and `jibb-import.hoon` under `urbit eval` to check that they build.
2929
30−`nix flake check` builds that too, then runs `tools/check --group eval` and, on Linux, `tools/check --group ship` against a copy of a fake ~zod it boots from the pill. Everything runs in the Nix sandbox without network, so a check can't pass because of something on your machine. Each group is one build; a failure prints the failing checks' output, and a passing build keeps every check's log in its output. On four CPUs it took about 20 minutes, the two groups building side by side: 18 minutes for the eval group, most of it `type-todo-full-test`, and 10 for the ship group. To run a single check, use `nix develop -c tools/check <name>` (see [docs/development.md](docs/development.md#before-pushing)).
30+`nix flake check` builds that too, then runs `tools/check --group eval` and, on Linux, `tools/check --group ship` against a copy of a fake ~zod it boots from the pill. Everything runs in the Nix sandbox without network, so a check can't pass because of something on your machine. Each group is one build; a failure prints the failing checks' output, and a passing build keeps every check's log in its output. On four CPUs it takes about 10 minutes, the two groups building side by side: under 3 minutes for the eval group (it took 18 before `tools/test-arms` replaced a script per suite) and 10 for the ship group. To run a single check, use `nix develop -c tools/check <name>` (see [docs/development.md](docs/development.md#before-pushing)).
3131
3232Limits: the ship checks need Linux, since `tools/ship` finds the ship's processes in `/proc`, so on macOS `nix flake check` runs only the eval group. Only `x86_64-linux` has been tried; the flake also declares `aarch64-linux` and `aarch64-darwin`, the other platforms nixpkgs builds vere for.
3333
@@ -59,19 +59,7 @@ tools/hoon '(golden /a/b/jibb (crip "++ main view"))'
5959tools/hoon --raw --cord src=tests/golden/foo/source.jibb 'tree:(golden /a/b/jibb src)'
6060```
6161
62−`tools/testdata/selftest` tests both tools against a stub library, and `tools/doc-blocks` against Markdown it writes. `tools/importer-test` compares the partial Hoon importer's fixture projections against their golden file. `tools/type-import-test`, `tools/type-import-overlap-test`, `tools/type-import-structural-test`, `tools/type-union-source-test`, `tools/type-union-alias-overlap-test`, `tools/type-full-overlap-test`, `tools/type-generic-recursion-test`, `tools/type-generic-construction-test`, `tools/type-generic-pattern-test`, `tools/type-deferred-test`, `tools/type-deferred-prepared-test`, `tools/type-deferred-resolver-test`, `tools/type-deferred-context-test`, `tools/type-empty-test`, `tools/type-cell-branch-test`, `tools/type-tlon-test`, `tools/type-mark-test`, `tools/type-poke-test` and `tools/type-api-paths-test` check importer/checker, prelude and partial API path analysis boundaries under eval; the ship suite runs the same fixtures.
63−
64−The focused `tools/type-page-main-test` fully checks the byte-identical static about page and direct blog/todo data pages through the real readers, with exact main types, downstream imports and fail-closed syntax/evidence controls; the same fixture runs on the fake ship. It does not render pages or execute requests.
65−
66−The focused `tools/type-buttons-test` fully checks the documented `labelled` and `wide` definitions and the unchanged module's exact source-located unresolved-`%add` error through detailed and legacy inference. The eval test and fake-ship arm share the valid source, schemes and error fixtures. It does not render or execute UI.
67−
68−The focused `tools/type-doc-examples-test` fully checks the import-only example with real Hoon readers and the card module, the `view-day` and `step` modules, and the `cmd`/`sub` molds at their prelude path through detailed and legacy inference. The same fixture runs on the fake ship.
69−
70−The focused `tools/type-theme-test` fully checks the byte-identical real theme against the exact prelude mold, including its exported type, structural downstream import, dark absent/present forms and malformed-field negatives under eval with a shared fake-ship arm. It does not check contrast, render themes or route fonts.
71−
72−The focused `tools/type-store-test` checks the byte-identical cart store and basket through detailed and legacy inference, exact main and derived schemes, structural imports, direct store watch evidence and rejection controls under eval with a shared fake-ship arm. It does not lower or execute stores, support multi-action declarations, or permit store requests in page loads.
73−
74−The focused `tools/type-program-main-test` checks the narrow closed, subscription-free `main` slice and its shared fake-ship fixture. `tools/type-program-init-test` checks transactional initializer recovery for a synthetic direct program, including exact exported and imported types and rejection boundaries. `tools/type-program-update-test` checks derived result context for an unannotated two-slot update, including a union/boolean branch, downstream types and fail-closed controls under eval with a shared fake-ship arm. `tools/type-program-watch-test` uses the real todo readers with synthetic program components to check one direct request value against merged API-source evidence and reject hand-built, indirect, parameterized, diff and ambiguous subscriptions. These are static checks only: they do not run an island or establish runtime watching. `tools/type-todo-full-test` additionally checks the byte-identical todo island through both full-module APIs, verifies its exact closed `main` type and structural downstream import, and runs rejection controls.
62+`tools/testdata/selftest` tests `tools/golden` and `tools/hoon` against a stub library, `tools/test-arms` against the same library with suites it writes, and `tools/doc-blocks` against Markdown it writes.
7563
7664### The doc's examples
7765
@@ -84,6 +72,40 @@ tools/doc-blocks Grammar.md Overview.md Core-language.md # fresh exports
8472
8573It matches each labelled block to the case whose `source.jibb` is the block's text plus a newline, and lists the blocks no case holds, each with a diff against the closest unmatched case, and the `doc-*` cases no block holds. Pass every tab with Jibb blocks, or the other tabs' cases count as stale. The exit status is 0 when every block has a case and every case a block, 1 when one doesn't, and 2 when the check can't run, for example because no block is labelled `jibb`.
8674
75+## Test suites
76+
77+Each `tests/lib/<suite>.hoon` file is a test suite: a core whose `test-` arms return a `tang`, empty when the arm passes. `tools/ship test` runs every suite on the fake ship with the `-test` thread. `tools/test-arms` runs the same arms under `urbit eval`, without a ship, for every suite but the generated `jibb.hoon`, whose golden cases `tools/golden` runs. It gives each suite the subject Ford would give it on the `jibb-dev` desk: its `/+` libraries and its `/*` files, which must be `%txt` or `%jibb` files, from where `tools/ship assemble` puts them. Like `tools/golden`, it needs `urbit` on PATH and Python 3.
78+
79+```
80+tools/test-arms # the my-app copies, then every suite
81+tools/test-arms jibb-store 'jibb-program-*' # suites by name or glob
82+tools/test-arms --shard 2/4 # the second of four shards, balanced by measured cost
83+tools/test-arms --list # the suites and their arms; ", report" marks a golden report
84+tools/test-arms --report jibb-import # print a golden-report suite's report
85+tools/test-arms --update jibb-import # write it to the suite's expected file
86+tools/test-arms --copies # only the my-app copies
87+```
88+
89+Many suites share one eval, so the library is built once per eval, not once per suite. Each arm runs under `mule` and prints OK, FAILED or CRASHED, as `-test` does, with what it returned or, for a crash, its trace mapped to lines of the suite and the library. When an eval fails, it is run again one suite at a time, and each suite that doesn't build is reported as `FAILED <suite> (build)`, with its error placed in the suite file. An eval that runs past `--timeout`, 1800 s by default, fails each of its suites as `(timeout)`. The exit status is 0 when every arm passes, 1 when an arm, a golden file or a `my-app` copy fails, and 2 when the suites can't run, for example on a usage error or a suite header it can't read. `tools/check` runs the suites in four shards, `arms-1` to `arms-4`.
90+
91+A golden-report suite has a `report` arm and a `/*` file bound to the face `expected`; when one of its arms fails, the runner prints a diff between that file and the report. Before any eval, the runner checks the golden files of the suites it runs, the `%txt` files bound to a face containing `expected`: each must end in exactly one newline, which an arm can't see in the file's wain, and hold no line that starts `BAD ` or ends `: BAD`. `--update` won't write a report that breaks either rule.
92+
93+Some fixtures in `tests/` are byte copies of `my-app` files, because the `jibb-dev` desk has no `my-app`. `tests/my-app-copies.txt` lists each copy with its source; a copy may leave out one line of its source, such as a mark's `/-` import. `tools/test-arms` checks every pair when it runs with no suite or shard named, and with `--copies`, which `tools/check` runs as `my-app-copies`. The suites below that check byte-identical `my-app` files read these copies.
94+
95+`tools/test-arms --list` lists every suite, and [The test suites](docs/development.md#the-test-suites) in the development guide says what each one checks. Each suite it lists runs under eval and on the fake ship, with the same fixtures. The `jibb-import` suite compares the partial Hoon importer's fixture projections against their golden file. The suites `jibb-bridge`, `jibb-import-overlap`, `jibb-import-structural`, `jibb-union-source`, `jibb-union-alias-overlap`, `jibb-full-overlap-basic`, `jibb-full-overlap-graph`, `jibb-generic-recursion`, `jibb-generic-construction`, `jibb-generic-pattern`, `jibb-deferred`, `jibb-deferred-prepared`, `jibb-deferred-resolver`, `jibb-deferred-context`, `jibb-empty`, `jibb-cell-branch`, `jibb-tlon-bridge`, `jibb-mark-bridge`, `jibb-poke-bridge` and `jibb-api-paths` check importer/checker, prelude and partial API path analysis boundaries.
96+
97+`tests/lib/jibb-page-main.hoon` fully checks the byte-identical static about page and direct blog/todo data pages through the real readers, with exact main types, downstream imports and fail-closed syntax/evidence controls. It does not render pages or execute requests.
98+
99+`tests/lib/jibb-buttons.hoon` fully checks the documented `labelled` and `wide` definitions and the unchanged module's exact source-located unresolved-`%add` error through detailed and legacy inference, with the valid source, schemes and error fixtures in `tests/type-buttons/`. It does not render or execute UI.
100+
101+`tests/lib/jibb-doc-examples.hoon` fully checks the import-only example with real Hoon readers and the card module, the `view-day` and `step` modules, and the `cmd`/`sub` molds at their prelude path through detailed and legacy inference.
102+
103+`tests/lib/jibb-theme.hoon` fully checks the byte-identical real theme against the exact prelude mold, including its exported type, structural downstream import, dark absent/present forms and malformed-field negatives. It does not check contrast, render themes or route fonts.
104+
105+`tests/lib/jibb-store.hoon` checks the byte-identical cart store and basket through detailed and legacy inference, exact main and derived schemes, structural imports, direct store watch evidence and rejection controls. It does not lower or execute stores, support multi-action declarations, or permit store requests in page loads.
106+
107+`tests/lib/jibb-program-main.hoon` checks the narrow closed, subscription-free `main` slice. `tests/lib/jibb-program-init.hoon` checks transactional initializer recovery for a synthetic direct program, including exact exported and imported types and rejection boundaries. `tests/lib/jibb-program-update.hoon` checks derived result context for an unannotated two-slot update, including a union/boolean branch, downstream types and fail-closed controls. `tests/lib/jibb-program-watch.hoon` uses the real todo readers with synthetic program components to check one direct request value against merged API-source evidence and reject hand-built, indirect, parameterized, diff and ambiguous subscriptions. These are static checks only: they do not run an island or establish runtime watching. `tests/lib/jibb-todo-full.hoon` additionally checks the byte-identical todo island through both full-module APIs, verifies its exact closed `main` type and structural downstream import, and runs rejection controls.
108+
87109## Licence
88110
89111Jibb is under the MIT licence, in [LICENSE](LICENSE). Two kinds of files in it are other people's, under their own MIT licences: the files in `vendor/` are copies from urbit/urbit, whose licence is in [vendor/LICENSE-urbit.txt](vendor/LICENSE-urbit.txt), and the Tlon `/sur` files that `tests/` uses as importer fixtures come from tloncorp/tlon-apps, whose licence is in [tests/importer/tlon-license.txt](tests/importer/tlon-license.txt).
docs/compiler.md+3−3
@@ -68,7 +68,7 @@ Before the empty-capital optimization below, single sequential eval runs includi
6868
6969Restricted-number promotion only applies to written capital variables. If none are present, it returns immediately instead of traversing the environment. In one startup-inclusive pair of runs on 2,000 independent gates, output was byte-identical and user CPU fell from 71.67 to 38.26 seconds; wall time was 72.80 versus 51.66 seconds while other checks were running. This does not establish a bound for dependent modules or a complete-checker benchmark.
7070
71−A bounded source proof can also establish distinct literal heads when a union case is a one-hop application of a uniquely resolved local generic mold. It compares literal runtime nouns and checks the original mold normally before publishing an interface. The same source proof improves the partial report, which still says the mold is not checked. The new proof declines nested or qualified applications, opaque references, recursive-index states, holes and deferred obligations; other valid unions can remain unsupported. A 256-node source budget and a separate 256-entry inherited-state budget apply per attempt. They do not bound the existing pairwise union pass, parsing, atom or name sizes, or downstream checking. Prepared interfaces and inference state remain trusted inputs. `tools/type-union-source-test` and the shared ship guard exercise source resolution, reporting, rollback and these bounds. A separate positive witness can identify overlap in two-field, literal-headed cases when a unique one-hop local, one-parameter generic alias is applied to a concrete primitive payload. It compares the literal noun values and proves the payloads have a shared noun, so an empty or unknown payload is not a witness. The partial report identifies both original case sites. The partial report and the full module check find overlaps with one helper, `mold-overlap-witness`: it takes the first overlapping pair from the pairwise projection, which covers atoms, `?` and literal constants, and nested literal-headed cells, and tries this source witness only when no pair overlaps and some pair stays unknown. A projected overlap is therefore named even when the source witness would prove an earlier pair. For the same union both paths name the same pair, but the full check attaches evidence only when that union is the first mold whose inference fails and its generic parameters are valid; an earlier failing mold, including one that refers to the union, and a union with duplicate or too many parameters keep the generic error. `infer-jibb-file-detailed` returns structured overlap evidence for the first failed mold, including the originating path, exact source, mold name and both case spans. Ordinary Jibb imports preserve a child’s evidence through source and cache checks; the legacy `infer-jibb-file` API remains a text-result adapter and renders both excerpts. Specialized API and prepared-prelude paths retain their existing generic or text-only error boundaries. This witness uses a shared 256-node source/pair budget per attempt; generic-wrapper parameter validation has a separate 256-entry cap. An unsupported earlier case may hide a later overlap. The pairwise projection has no budget: the full check runs it before inferring a union's cases, and once more, to find the pair, on a failed union mold whose generic parameters are valid. Parsing, atom and name sizes, source-excerpt rendering, and downstream checking also remain outside these budgets. `tools/type-union-alias-overlap-test` checks the source proof and partial report; `tools/type-full-overlap-test` checks the detailed and legacy full-module paths, source attribution and cache behavior.
71+A bounded source proof can also establish distinct literal heads when a union case is a one-hop application of a uniquely resolved local generic mold. It compares literal runtime nouns and checks the original mold normally before publishing an interface. The same source proof improves the partial report, which still says the mold is not checked. The new proof declines nested or qualified applications, opaque references, recursive-index states, holes and deferred obligations; other valid unions can remain unsupported. A 256-node source budget and a separate 256-entry inherited-state budget apply per attempt. They do not bound the existing pairwise union pass, parsing, atom or name sizes, or downstream checking. Prepared interfaces and inference state remain trusted inputs. The `tests/lib/jibb-union-source.hoon` suite exercises source resolution, reporting, rollback and these bounds under eval (`tools/test-arms jibb-union-source`) and on the ship. A separate positive witness can identify overlap in two-field, literal-headed cases when a unique one-hop local, one-parameter generic alias is applied to a concrete primitive payload. It compares the literal noun values and proves the payloads have a shared noun, so an empty or unknown payload is not a witness. The partial report identifies both original case sites. The partial report and the full module check find overlaps with one helper, `mold-overlap-witness`: it takes the first overlapping pair from the pairwise projection, which covers atoms, `?` and literal constants, and nested literal-headed cells, and tries this source witness only when no pair overlaps and some pair stays unknown. A projected overlap is therefore named even when the source witness would prove an earlier pair. For the same union both paths name the same pair, but the full check attaches evidence only when that union is the first mold whose inference fails and its generic parameters are valid; an earlier failing mold, including one that refers to the union, and a union with duplicate or too many parameters keep the generic error. `infer-jibb-file-detailed` returns structured overlap evidence for the first failed mold, including the originating path, exact source, mold name and both case spans. Ordinary Jibb imports preserve a child’s evidence through source and cache checks; the legacy `infer-jibb-file` API remains a text-result adapter and renders both excerpts. Specialized API and prepared-prelude paths retain their existing generic or text-only error boundaries. This witness uses a shared 256-node source/pair budget per attempt; generic-wrapper parameter validation has a separate 256-entry cap. An unsupported earlier case may hide a later overlap. The pairwise projection has no budget: the full check runs it before inferring a union's cases, and once more, to find the pair, on a failed union mold whose generic parameters are valid. Parsing, atom and name sizes, source-excerpt rendering, and downstream checking also remain outside these budgets. `tests/lib/jibb-union-alias-overlap.hoon` checks the source proof and partial report; `tests/lib/jibb-full-overlap-basic.hoon` and `tests/lib/jibb-full-overlap-graph.hoon` check the detailed and legacy full-module paths, source attribution and cache behavior.
7272
7373A single-arm cell pattern can bind two or more positions, with its last binder capturing the remaining tail. Duplicate and shadowed names are rejected. A definite non-cell spine fails; an intermediate union or collection that might contain a cell remains unsupported. For a known non-union cell, a separate one-arm rule also accepts structured patterns, including nested literal and wildcard positions, when the existing coverage proof establishes the whole pattern. It binds payloads with their original types and checks result context; unknown, partially covered, union or recursive spines stay unsupported.
7474
@@ -102,7 +102,7 @@ A known closed union with two or more arms can be matched when each arm provably
102102
103103A known closed union can also provide context to each arm of a complete loobean or unit-shaped branch in a cast or a call with a known union sample. Nested branches and transparent groups work; a mismatch reports the expected union and the offending arm. General patterns and context through bodies with local definitions remain unsupported, and unrelated unresolved tags stay pending.
104104
105−The separate `jibb-dev/lib/jibb-import.hoon` is an unfinished reader for selected Hoon type graphs. It handles named recursion, nested map, set, queue, list, unit, jar and jug arguments, direct ordered maps, and direct `$^` unions whose source branches can be proved disjoint. It also recognizes a direct ordered-map call with two simple named mold operands, as in Tlon `notes.log`, after validating provenance and operand source; revisiting the same map hold fails closed. It also reads ordered map fields in records when the map arguments are syntactically fixed atom molds and other fields are fixed atom molds or standard collections of static atom molds. Collection names must not be shadowed. The reader can also import a mark door sample, removing its outer sample face and validating its build subject. For a mark whose sample is exactly a named arm of its single Ford-imported `/sur` core, it can recover a source-proved nonrecursive union, including source-location wrappers around fields; recursive or unverified fallback results remain unsupported. The reader checks explicit Hoon `$%`, `$?` and `$^` unions against the Grammar’s disjointness rule, as @iko confirmed on 2026-10-30. For an explicit `$%` with distinct literal head tags, it can also prove restricted local named payload dependencies, including bare `~` fields, re-evaluate and validate each source branch, and recover the union before Hoon collapses it. The real Tlon `notes.u-note` exercises its `[%deleted ~]` case. A bounded fallback also recovers one level of local named tagged unions inside such a union, including Tlon `notes.u-notebook` and `notes.u-notes`. Source-proved tagged unions can also be wrapped in Hoon `$~` defaults, including a downstream union using Tlon `epic.saga`; the selected source and projected branches still undergo the same provenance and disjointness checks. The tagged-source helper peels up to four consecutive default wrappers, while default wrappers encountered inside dependency proofs consume the existing semantic-node budget. A source-proved nested self-recursive union retains its named owner, including Tlon `notes.import-node`; deeper, mutually recursive or unproven cases stay unsupported. The nested source proof has a 256-visit semantic-node budget, and source-location wrapper peeling is limited to four per node; Hoon evaluation and source scans are not metered. It rejects recursive or computed dependencies, inherited same-name collisions, unsupported nested unions and proofs exceeding a shared 4,096-node budget. It re-evaluates statically recognizable source branches before Hoon can collapse them, checks materialized fork cases, and rejects shapes it cannot prove disjoint. Static records may also have verified standard-collection and `path` siblings. One direct explicit union argument in a standard list, set, map or unit is accepted when its call wrapper and collection provenance are verified and its static cases are pairwise disjoint. A synthetic regression checks that forged wrapper subjects, samples and tails are rejected. Other collection-union forms, nested ordered maps, general source-level disjointness and complete integration with the checker remain unfinished. `+golden-types-imports` can consume fixed-aura atoms, valid term singletons, Hoon's `%n` zero singleton as Jibb `~`, nested faced or unfaced cells, unions of supported, pairwise-disjoint cases, and opaque standard collections with supported arguments from caller-supplied reader results for declared `/-` imports; `+golden-types-with-marks` accepts the same shapes for declared marks. The caller must pass unchanged results from the source-aware reader: the bridge validates the supplied graph but cannot detect source cases Hoon collapsed before that graph was built. The opaque collection types retain their names and arguments for identity, unification and printing. The validated standard prelude `list` mold shares the imported list representation; other Jibb-written collection molds and most prelude collection operations remain unsupported. Other forms remain unsupported. Its disjointness proof is conservative and can reject a valid union it cannot prove disjoint. Collection recognition requires the originating `/sur` core. The reader validates direct zuse subjects and Ford subjects consisting of faced imported cores and a validated tail, checking imported cores transitively; it rejects shadowed names, inconsistent core subjects and other subject shapes. For a recursive reference, the reader matches the exact Hoon hold against named arms in validated cores, including transitive Ford imports; it rejects missing, unlabelled or ambiguous origins. Its fixtures include three real Tlon files; `tools/importer-test` compares the internal projection under eval, and the ship test compares the same golden output. `tools/type-import-test` and `tools/type-mark-test` compare bridge reports under eval and on the ship. `tools/type-tlon-test` and its ship counterpart exercise four real Tlon presence unions and a field read through the source-aware reader and partial checker. `tools/clay-fixtures` also passes Clay-built `/sur` molds and mark samples through the Clay-built importer and partial checker.
105+The separate `jibb-dev/lib/jibb-import.hoon` is an unfinished reader for selected Hoon type graphs. It handles named recursion, nested map, set, queue, list, unit, jar and jug arguments, direct ordered maps, and direct `$^` unions whose source branches can be proved disjoint. It also recognizes a direct ordered-map call with two simple named mold operands, as in Tlon `notes.log`, after validating provenance and operand source; revisiting the same map hold fails closed. It also reads ordered map fields in records when the map arguments are syntactically fixed atom molds and other fields are fixed atom molds or standard collections of static atom molds. Collection names must not be shadowed. The reader can also import a mark door sample, removing its outer sample face and validating its build subject. For a mark whose sample is exactly a named arm of its single Ford-imported `/sur` core, it can recover a source-proved nonrecursive union, including source-location wrappers around fields; recursive or unverified fallback results remain unsupported. The reader checks explicit Hoon `$%`, `$?` and `$^` unions against the Grammar’s disjointness rule, as @iko confirmed on 2026-10-30. For an explicit `$%` with distinct literal head tags, it can also prove restricted local named payload dependencies, including bare `~` fields, re-evaluate and validate each source branch, and recover the union before Hoon collapses it. The real Tlon `notes.u-note` exercises its `[%deleted ~]` case. A bounded fallback also recovers one level of local named tagged unions inside such a union, including Tlon `notes.u-notebook` and `notes.u-notes`. Source-proved tagged unions can also be wrapped in Hoon `$~` defaults, including a downstream union using Tlon `epic.saga`; the selected source and projected branches still undergo the same provenance and disjointness checks. The tagged-source helper peels up to four consecutive default wrappers, while default wrappers encountered inside dependency proofs consume the existing semantic-node budget. A source-proved nested self-recursive union retains its named owner, including Tlon `notes.import-node`; deeper, mutually recursive or unproven cases stay unsupported. The nested source proof has a 256-visit semantic-node budget, and source-location wrapper peeling is limited to four per node; Hoon evaluation and source scans are not metered. It rejects recursive or computed dependencies, inherited same-name collisions, unsupported nested unions and proofs exceeding a shared 4,096-node budget. It re-evaluates statically recognizable source branches before Hoon can collapse them, checks materialized fork cases, and rejects shapes it cannot prove disjoint. Static records may also have verified standard-collection and `path` siblings. One direct explicit union argument in a standard list, set, map or unit is accepted when its call wrapper and collection provenance are verified and its static cases are pairwise disjoint. A synthetic regression checks that forged wrapper subjects, samples and tails are rejected. Other collection-union forms, nested ordered maps, general source-level disjointness and complete integration with the checker remain unfinished. `+golden-types-imports` can consume fixed-aura atoms, valid term singletons, Hoon's `%n` zero singleton as Jibb `~`, nested faced or unfaced cells, unions of supported, pairwise-disjoint cases, and opaque standard collections with supported arguments from caller-supplied reader results for declared `/-` imports; `+golden-types-with-marks` accepts the same shapes for declared marks. The caller must pass unchanged results from the source-aware reader: the bridge validates the supplied graph but cannot detect source cases Hoon collapsed before that graph was built. The opaque collection types retain their names and arguments for identity, unification and printing. The validated standard prelude `list` mold shares the imported list representation; other Jibb-written collection molds and most prelude collection operations remain unsupported. Other forms remain unsupported. Its disjointness proof is conservative and can reject a valid union it cannot prove disjoint. Collection recognition requires the originating `/sur` core. The reader validates direct zuse subjects and Ford subjects consisting of faced imported cores and a validated tail, checking imported cores transitively; it rejects shadowed names, inconsistent core subjects and other subject shapes. For a recursive reference, the reader matches the exact Hoon hold against named arms in validated cores, including transitive Ford imports; it rejects missing, unlabelled or ambiguous origins. Its fixtures include three real Tlon files; the `tests/lib/jibb-import.hoon` suite compares the internal projection with its golden output, under eval (`tools/test-arms jibb-import`) and on the ship. `tests/lib/jibb-bridge.hoon` and `tests/lib/jibb-mark-bridge.hoon` compare bridge reports under eval and on the ship. `tests/lib/jibb-tlon-bridge.hoon` exercises four real Tlon presence unions and a field read through the source-aware reader and partial checker, under eval and on the ship. `tools/clay-fixtures` also passes Clay-built `/sur` molds and mark samples through the Clay-built importer and partial checker.
106106
107107An import-free Jibb library can export an opaque single-parameter recursive identity when its source has exactly two distinct term-tagged cases: a text leaf and a node containing `(list (name M))`, optionally with one `$-(@t M)` event field. A module-local index records the exact parsed source, defining path and prepared prelude interface; it is shared across that module's inference passes, and its canonical `list` must be source-backed. The normal resolver publishes an interface only after all ordinary mold and value checks succeed. Same-origin aliases retain the defining identity and independently instantiate type arguments; distinct origins remain unsupported. The opaque identity is conservatively treated as gate-bearing for numeric defaulting, and gate-freedom remains unknown. Explicit literal-headed construction uses a source-proven one-layer view: the event result receives the existing type argument and recursive children keep the defining identity. It consumes the existing shared 256-step recursive inference budget, and a per-view 4,096-visit guard bounds the new face and substitution scan; longer scans decline. These bounds do not cover parsing, existing inference, atom sizes or repeated attempts. One startup-inclusive, shared-load comparison of 100 valid and 100 invalid source definitions took 29.67 s wall / 25.14 s user CPU before this slice and 33.47 s / 26.99 s with it; the former declined all 200 while the latter inferred the valid definitions. These single runs are not a production benchmark. Matches over explicit source tags, flat binder or wildcard fields, and nonbinding catch-alls use that same one-layer view and existing binder, coverage and branch checks. Up to 128 arms are screened per attempt; longer matches decline. A single-arm match on a direct in-scope wing can report its missing case, and a contextual one-arm call subject can use a nonbinding catch-all. Recursive children retain their nominal type and arguments. Subject recognition and view validation can each scan substitutions, and the scan cap applies separately to each attempt. In one separate startup-inclusive comparison of 100 valid and 100 invalid source matches, the construction-only checker took 30.18 s wall / 29.31 s user CPU and declined all 200, while the pattern slice took 28.28 s / 27.69 s and inferred or diagnosed them. These single shared-load figures are not production benchmarks. General structural fits, whole-case binders, nested recursive patterns, uncontextualized single-arm call subjects, recursive source with imports and local recursive molds remain unsupported; the test tree does not prescribe the eventual `element` representation. Caller-supplied detached interfaces and caches retain the existing trusted-input contract.
108108
@@ -150,7 +150,7 @@ Ordinary inference runs for every component before recovery, so a keyed view no
150150
151151A component-local recovery sequence handles a recognized direct program whose context-dependent definitions cannot resolve ordinarily. Update first derives its result from its inferred two-slot sample and canonical `cmd`/`list` templates. Subscription recovery then checks the same message/model relation and the canonical fourth slot. A narrow keyed-view proof finds exactly one direct `each (turn xs mapper)` site, derives the mapper from the actual `each` and `turn` schemes, and recovers the view before the existing initializer and ordinary `main` retries. Every recovered scheme must be closed and freshly allocated above the current environment and prelude IDs. That bound comes from one unbudgeted pass over the environment and prelude schemes, which treats named recursive types as leaves and declines only when a scheme still holds an unresolved literal tag. Non-gate views and aliases decline without crashing. Final publication still requires all module definitions, the program-mold and gate-free checks, and request-value watchability.
152152
153−Canonical `element` composition has two tightly scoped accommodations. Recursive result context is allowed only when every recursive side has the prepared prelude's `element` origin. When ordinary list-item fitting fails, an `element` target may instead prove its message argument invariantly or select one exact literal case with a full payload fit; a successful ordinary fit always takes precedence. This covers the unchanged todo's union controls and raw constructors without opening those paths to other unions. `tools/type-todo-full-test` checks the byte-identical island through both full APIs, the exact closed `main` type, structural downstream import, and model/message/mapper/watch rejection controls. It does not execute Jibb or implement runtime watching.
153+Canonical `element` composition has two tightly scoped accommodations. Recursive result context is allowed only when every recursive side has the prepared prelude's `element` origin. When ordinary list-item fitting fails, an `element` target may instead prove its message argument invariantly or select one exact literal case with a full payload fit; a successful ordinary fit always takes precedence. This covers the unchanged todo's union controls and raw constructors without opening those paths to other unions. The `tests/lib/jibb-todo-full.hoon` suite checks the byte-identical island through both full APIs, the exact closed `main` type, structural downstream import, and model/message/mapper/watch rejection controls. It does not execute Jibb or implement runtime watching.
154154
155155Each case's canonical API identity and source-derived schema travel across imports in a nonrecursive graph certificate containing the exact source bundle, prelude, reserved scope and trusted reader results. Cached interfaces must match those inputs and cannot hide an active ancestor; unknown legacy entries are rebuilt from their unique supplied source. Request-bearing closures are limited to 256 paths and requests. Closed gate samples can also fit when an unnamed input slot corresponds to a named one, provided products are identical and nested value faces and ambiguous cell tails remain intact. This is type inference only: request lowering, runtime schema validation and value watchability proofs are not implemented.
156156
docs/development.md+74−58
@@ -14,7 +14,7 @@ From the plan's Setup and ground rules, and from @iko:
1414- **Push straight to `master`.** @iko reviews work in the project's chat, not in pull requests, so there are none. Run the checks below first.
1515- **Keep docs/ current**: [status.md](status.md) when a milestone moves, [open-questions.md](open-questions.md) when a question is found, and [spec/decisions.md](spec/decisions.md) when one is settled: it moves there.
1616
17−The source-backed generic-union guard can be run under eval with `tools/type-union-source-test`; its `test-union-source` arm is also assembled for the fake ship. It checks a bounded partial inference slice, not general union completeness. `tools/type-union-alias-overlap-test` exercises the separate positive overlap witness and its shared ship test arm. `tools/type-full-overlap-test` checks structured full-module overlap evidence and the legacy error text under eval; both of its test arms are assembled for the fake ship.
17+The source-backed generic-union guard is the suite `tests/lib/jibb-union-source.hoon`: `tools/test-arms jibb-union-source` runs its `test-union-source` arm under eval, and the same arm is assembled for the fake ship. It checks a bounded partial inference slice, not general union completeness. `tests/lib/jibb-union-alias-overlap.hoon` exercises the separate positive overlap witness, with one test arm shared by eval and the ship. `tests/lib/jibb-full-overlap-basic.hoon` and `tests/lib/jibb-full-overlap-graph.hoon` check structured full-module overlap evidence and the legacy error text; `tools/test-arms 'jibb-full-overlap-*'` runs both of their test arms under eval, and both are assembled for the fake ship.
1818
1919## Setting up a machine
2020
@@ -72,68 +72,86 @@ git clone https://github.com/urbit/tools /root/src/tools
7272| --- | --- |
7373| `tools/check` | Runs every check in this table, or a group (`--group eval` or `ship`), or some by name: see [Before pushing](#before-pushing) |
7474| `tools/golden` | Runs the golden cases under `urbit eval`: every case, or those matching `--case`; `--update` rewrites the expected outputs; `--show` prints them |
75−| `tools/importer-test` | Compares the partial Hoon importer's diagnostic trees and errors with `tests/importer/tree.txt` under `urbit eval` |
76−| `tools/type-import-default-test` | Compares default-wrapped union source proofs and adversarial cases under eval; the same golden runs on the ship |
77−| `tools/type-import-test` | Composes the Hoon importer with the partial checker and compares `tests/type-import/expected.txt` under eval |
78−| `tools/type-import-overlap-test` | Checks source-aware Hoon union overlap, provenance and proof-budget controls under eval; the same fixture runs on the ship |
79−| `tools/type-import-structural-test` | Checks multi-case and nested Hoon union overlap witnesses under eval and on the ship |
80−| `tools/type-union-source-test` | Checks bounded local generic-alias disjointness and state guards under eval and on the ship |
81−| `tools/type-union-alias-overlap-test` | Checks source-backed generic-alias overlap witnesses under eval and on the ship |
82−| `tools/type-full-overlap-test` | Checks structured full-module overlap evidence and imported-source attribution |
83−| `tools/type-tlon-test` | Runs the real Tlon presence source through the importer and partial checker, comparing `tests/type-tlon/expected.txt` under eval |
84−| `tools/type-import-diagnostic-test` | Compares the structured reader diagnostic bridge report under eval |
85−| `tools/type-mark-test` | Checks the partial checker’s mark import boundary against `tests/type-mark/expected.txt` under eval |
86−| `tools/type-poke-test` | Checks source-backed prelude and poke-only API reports against `tests/type-poke/expected.txt` under eval |
87−| `tools/type-api-paths-test` | Checks partial API path analysis with real todo mark samples against `tests/type-api-paths/expected.txt` under eval |
88−| `tools/type-api-evidence-test` | Runs source, scope, reader-result and declaration-watchability evidence guards under eval and on the ship |
89−| `tools/type-hole-guards-test` | Runs the shared hole-defaulting and API interface guards under eval; the same checks run on the ship |
90−| `tools/type-list-alias-test` | Runs the shared prelude list-alias and provenance guards under eval and on the ship |
91−| `tools/type-generic-recursion-test` | Checks source-backed generic recursive identity and provenance under eval and on the ship |
92−| `tools/type-generic-construction-test` | Checks source-backed one-layer recursive construction, provenance and fuel under eval and on the ship |
93−| `tools/type-generic-pattern-test` | Checks source-backed recursive patterns, catch-all coverage, state and per-attempt fuel/arm limits under eval and on the ship |
94−| `tools/type-deferred-test` | Checks the bounded source-owned deferred inference transaction under eval and on the ship |
95−| `tools/type-deferred-resolver-test` | Checks deferred resolution, report consistency and atomic failure under eval and on the ship |
96−| `tools/type-deferred-context-test` | Checks deferred source order and literal branch contexts under eval and on the ship |
97−| `tools/type-deferred-prepared-test` | Checks prepared-prelude tuple initializer recovery, exact partial reports and fail-closed guards under eval and on the ship |
98−| `tools/type-cell-branch-test` | Checks closed-cell branch context, rollback and bounded retry screens under eval and on the ship |
99−| `tools/type-generic-alias-test` | Runs public/private generic union alias and provenance guards under eval and on the ship |
100−| `tools/type-positional-face-guards-test` | Runs positional-call and nested-face guards under eval and on the ship |
101−| `tools/type-qath-guards-test` | Runs source-provenance, recursive unfolding and face guards under eval and on the ship |
102−| `tools/type-todo-partial-test` | Reports partial inference of the unchanged todo island through the real API and readers under eval and on the ship |
103−| `tools/type-todo-api-test` | Exercises the actual todo API through the real Hoon readers and partial checker |
104−| `tools/type-direct-gate-test` | Checks a synthetic source-backed program report and direct gate provenance under eval and on the ship |
105−| `tools/type-page-main-test` | Fully checks byte-identical static and direct data pages through real readers, exact main types, downstream imports and rejection guards under eval and on the ship |
106−| `tools/type-buttons-test` | Checks the documented valid button helpers and the unchanged unresolved-`%add` module through detailed and legacy inference under eval and on the ship |
107−| `tools/type-doc-examples-test` | Fully checks the import-only, view-day, step and cmd/sub doc fragments in their intended contexts through detailed and legacy inference under eval and on the ship |
108−| `tools/type-theme-test` | Fully checks the byte-identical real theme, its exact exported type, structural downstream import, dark absent/present forms and rejection guards under eval and on the ship |
109−| `tools/type-program-main-test` | Checks the narrow closed subscription-free program-main interface, downstream import and rejection guards under eval and on the ship |
110−| `tools/type-program-init-test` | Checks transactional direct-program initializer recovery, exact exported/imported types and fail-closed boundaries under eval and on the ship |
111−| `tools/type-program-update-test` | Checks transactional direct-program update result recovery, union/boolean context, exact exported/imported types and fail-closed boundaries under eval and on the ship |
112−| `tools/type-program-watch-test` | Checks direct singleton request-value watchability against merged real-todo evidence, exact types/imports and rejection boundaries under eval and on the ship |
113−| `tools/type-store-test` | Checks the unchanged cart/basket through detailed and legacy inference, exact store/derived schemes, malformed-prelude guards, structural imports, source-bound state watch evidence and rejection guards under eval and on the ship |
114−| `tools/type-todo-full-test` | Fully checks the byte-identical todo island and an ordinary call-bodied annotated-initializer variant through real readers, exact main types, structural downstream import and rejection controls under eval and on the ship |
115−| `tools/type-closed-gate-guards-test` | Checks closed gate sample labels and face uncertainty under eval and on the ship |
116−| `tools/type-constructor-fit-guards-test` | Checks constructor-case uncertainty and known mismatches under eval and on the ship |
117−| `tools/type-nested-union-guards-test` | Checks nested tagged-union case selection and uncertainty under eval and on the ship |
118−| `tools/type-empty-test` | Checks source-backed empty molds, inhabitedness, coverage and proof budgets under eval and on the ship |
119−| `tools/type-gate-free-guards-test` | Checks bounded gate-free verdicts, persistent constraints, substitution safeguards, collection keys and witness paths under eval and on the ship |
120−| `tools/type-gate-free-source-test` | Checks source-backed todo mold analysis through the real readers under eval and on the ship |
121−| `tools/type-sub-guards-test` | Checks source-backed subscription mold dependencies under eval and on the ship |
122−| `tools/type-ask-guards-test` | Runs ask origin and canonical list/unit bootstrap guards under eval and on the ship |
123−| `tools/type-request-guards-test` | Runs request evidence, source consistency and cache provenance guards under eval and on the ship |
124−| `tools/type-proj-guards-test` | Runs projection evidence, name-scope and dependency guards under eval and on the ship |
125−| `tools/type-arithmetic-guards-test` | Runs restricted atom-variable, unification and projection guards under eval and on the ship |
126−| `tools/type-module-scope-test` | Checks the partial module checker’s prelude boundary and duplicate-source rejection against `tests/type-module-scope/expected.txt` under eval |
75+| `tools/test-arms` | Runs the `test-` arms of the `tests/lib` suites under `urbit eval`, each with the subject Ford would give it on the `jibb-dev` desk: every suite, or those named or matched by a glob, as `tools/test-arms jibb-store 'jibb-program-*'`; `--shard I/N` runs the I-th of N balanced shards; `--list` prints the suites and their arms; `--report` and `--update` print or rewrite a golden-report suite's report; `--copies` checks only the `my-app` copies. See [The test suites](#the-test-suites) |
12776| `tools/clay-fixtures` | Syncs `my-app`, builds its example `/sur` files and marks through Clay, checks selected mold and mark projections and the partial checker, and records Ford and mark subject shapes on the fake ship |
12877| `tools/hoon` | Evaluates Hoon with the library in scope, as `tools/hoon '(golden /a/b/jibb (crip "++ main view"))'`; `--cord name=file` binds a file's text, `-f` reads the expression from a file; `--no-debug` leaves out `!:`, which gives errors their positions but makes the checker 2.2 to 2.6 times slower than on a ship, for timings |
12978| `tools/doc-blocks` | Checks the doc's `jibb` blocks against the `doc-*` golden cases: `tools/doc-blocks docs/spec` |
13079| `tools/ship` | Runs the fake ship: `start`, `stop`, `status`, `log`, `sync <desk>`, `assemble --out <dir>` (no ship needed), `test`, `gen-tests`, `check-commit`, `scry`, `hoon`, `run`, `poke`, `commit`, `mount`, `unmount` |
131−| `tools/testdata/selftest` | Tests `tools/golden` and `tools/hoon` against a stub library, and `tools/doc-blocks` against Markdown it writes |
80+| `tools/testdata/selftest` | Tests `tools/golden` and `tools/hoon` against a stub library, `tools/test-arms` against the stub library with suites it writes, and `tools/doc-blocks` against Markdown it writes |
13281| `tools/testdata/ship-selftest` | Tests `tools/ship`'s test generator and runner against a stub library on the ship |
13382| `tools/testdata/clay-fixtures-selftest` | Tests temporary Clay fixture cleanup and signal handling without a ship |
13483
13584`tools/golden` starts `urbit eval` once and builds the library, which takes about 27 s, then runs every case under `mule`, so a crash fails only its own case.
13685
86+## The test suites
87+
88+Each file in `tests/lib` is a suite: a core of `test-` arms, with the libraries and files it reads bound by `/+` and `/*`. On the fake ship, `tools/ship test` runs every suite's arms with `-test /=jibb-dev=/tests`; under eval, `tools/test-arms` runs the same arms, so every suite below runs in both places. `tools/test-arms` gives each suite the subject Ford would give it on the `jibb-dev` desk: each `/+` library and each `/*` file, found where `tools/ship assemble` puts them. Before a suite's `|%` it takes only comments, `/+` lines and `/*` lines, and binds only `%txt` and `%jibb` files. The suites it runs share one eval, so the library is built once for all of them, in about 17 s with `!:`, and so is the importer library `jibb-import`, in about 20 s more, when any of them uses it. Each arm runs under `mule` and prints `OK`, `FAILED` or `CRASHED`, as `-test` does; a crashed arm's trace is mapped to lines in the suite and the library, with an excerpt of the innermost spot. When a suite doesn't build, `tools/test-arms` runs the suites again one at a time and reports it as `FAILED <suite> (build)`, with its error placed in the suite file. `tools/test-arms <suite>` runs one suite, and names or globs pick several, as `tools/test-arms jibb-store 'jibb-program-*'`; `tools/test-arms --list` prints the suites and their arms. `tools/check` runs them all in four shards, `arms-1` to `arms-4`, each `tools/test-arms --shard I/4` in an eval of its own, balanced by the measured costs in `COSTS` and `LIB_COSTS` in `tools/test-arms`. `tests/lib/jibb.hoon`, which `tools/ship gen-tests` writes from `tests/golden`, is left out under eval, since `tools/golden` runs those cases.
89+
90+A golden-report suite has a `report` arm and a golden file bound to the face `expected`; its test arm compares the report with that file, and `tools/test-arms --list` marks it `, report`. `tools/test-arms --report <suite>` prints the report, and `tools/test-arms --update <suite>` writes it to the file; with no suite named, `--update` writes every golden-report suite's. When such a suite's arm fails, `tools/test-arms` prints a unified diff between the file and the report. `jibb-buttons` and `jibb-deferred-prepared` have golden files too, but compare them inside helpers over several cases and have no `report` arm. Every golden file, a `/*` `%txt` file bound to a face containing `expected`, must end in exactly one newline (a suite compares `wain`s, which can't show a missing one) and hold no line that starts `BAD ` or ends `: BAD`; `tools/test-arms` checks that before any eval, and `--update` won't write a report that breaks it.
91+
92+The `jibb-dev` desk has no `my-app`, so the suites that check `my-app` files read byte copies of them kept under `tests/`, as do some golden cases. `tests/my-app-copies.txt` lists every such copy, one per line, as `COPY SOURCE`, or `COPY SOURCE without LINE` for a copy that leaves out one line of its source, such as `/- blog`. `tools/test-arms` checks every pair when run with no suite or shard named, and `tools/test-arms --copies`, the `my-app-copies` check, checks only them. Where the table below calls a `my-app` file byte-identical or unchanged, it is one of these copies.
93+
94+| Suite | What it checks | Golden files |
95+| --- | --- | --- |
96+| `jibb-api-evidence` | Source, scope, reader-result and declaration-watchability evidence guards for path declarations, in two arms, over synthetic and real todo inputs | |
97+| `jibb-api-paths` | Partial API path analysis with real todo mark samples; it does not generate request interfaces | `tests/type-api-paths/expected.txt` |
98+| `jibb-arithmetic-guards` | Restricted atom-variable, unification and projection guards | |
99+| `jibb-ask-guards` | Ask origin and canonical list/unit bootstrap guards | |
100+| `jibb-bridge` | The importer/checker bridge: the Hoon importer composed with the partial checker | `tests/type-import/expected.txt` |
101+| `jibb-buttons` | The documented valid button helpers and the unchanged unresolved-`%add` module, through detailed and legacy inference | `tests/type-buttons/expected.txt` |
102+| `jibb-cell-branch` | Closed-cell branch context, rollback and bounded retry screens | |
103+| `jibb-closed-gate-guards` | Closed gate sample labels and face uncertainty | |
104+| `jibb-constructor-fit-guards` | Constructor-case uncertainty and known mismatches | |
105+| `jibb-deferred` | The bounded source-owned deferred inference transaction | `tests/type-deferred/expected.txt` |
106+| `jibb-deferred-context` | Deferred source order and literal branch contexts | `tests/type-deferred-context/report.txt` |
107+| `jibb-deferred-prepared` | Prepared-prelude tuple initializer recovery, exact partial reports and fail-closed guards | `tests/type-deferred-prepared/expected.txt`, `expected-control.txt` and `expected-tuple-only.txt` |
108+| `jibb-deferred-resolver` | Deferred resolution, report consistency and atomic failure | `tests/type-deferred-resolver/expected.txt` |
109+| `jibb-direct-gate-guards` | Direct gate provenance: direct layout evidence keeps its provenance and final face constraints | |
110+| `jibb-direct-gate-source` | A synthetic source-backed program report: direct-source gate layouts through a synthetic program scaffold | `tests/type-direct-gate/expected.txt` |
111+| `jibb-doc-examples` | Full checking of the import-only, view-day, step and cmd/sub doc fragments in their intended contexts, through detailed and legacy inference | |
112+| `jibb-empty` | Source-backed empty molds, inhabitedness, coverage and proof budgets | `tests/type-empty/expected.txt` |
113+| `jibb-full-overlap-basic` | Structured full-module overlap evidence: source-bound overlap witnesses, generic parameter limits, precedence and rejection controls, and the legacy full-module error text | `tests/type-full-overlap/expected-basic.txt` |
114+| `jibb-full-overlap-graph` | Imported-source attribution of overlap evidence across parent and child modules: cache rebuilds and source binding, and private, cyclic, duplicate, missing and transitive imports | `tests/type-full-overlap/expected-graph.txt` |
115+| `jibb-gate-free-guards` | Bounded gate-free verdicts, persistent constraints, substitution safeguards, collection keys and witness paths | |
116+| `jibb-gate-free-source` | Source-backed todo mold analysis through the real readers | `tests/type-gate-free/expected.txt` |
117+| `jibb-generic-alias` | Public/private generic union alias and provenance guards | |
118+| `jibb-generic-construction` | Source-backed one-layer recursive construction, provenance and fuel | `tests/type-generic-construction/expected.txt` |
119+| `jibb-generic-pattern` | Source-backed recursive patterns, catch-all coverage, state and per-attempt fuel/arm limits | `tests/type-generic-pattern/expected.txt` |
120+| `jibb-generic-recursion` | Source-backed generic recursive identity and provenance | `tests/type-generic-recursion/expected.txt` |
121+| `jibb-hole-guards` | Hole-defaulting and API interface guards | |
122+| `jibb-import` | The partial Hoon importer's diagnostic trees and errors over the importer fixtures; the projection is an internal tree, not the Jibb type printer | `tests/importer/tree.txt` |
123+| `jibb-import-default` | Default-wrapped union source proofs over a real Tlon mold, and adversarial cases | `tests/type-import-default/expected.txt` |
124+| `jibb-import-diagnostic` | The structured reader diagnostic bridge report: definite and unsupported reader diagnostics through the checker | `tests/type-import-diagnostic/expected.txt` |
125+| `jibb-import-overlap` | Source-aware Hoon union overlap, provenance and proof-budget controls | `tests/type-import-overlap/expected.txt` |
126+| `jibb-import-structural` | Multi-case and nested Hoon union overlap witnesses | `tests/type-import-structural/expected.txt` |
127+| `jibb-list-alias-guards` | Prelude list-alias and provenance guards | `tests/type-list-alias/expected.txt` |
128+| `jibb-mark-bridge` | The partial checker's mark import boundary | `tests/type-mark/expected.txt` |
129+| `jibb-module-scope` | The partial module checker's prelude boundary and duplicate-source rejection | `tests/type-module-scope/expected.txt`, and the golden case's `tests/golden/types-prelude-interface/types.txt` |
130+| `jibb-nested-union-guards` | Nested tagged-union case selection and uncertainty | |
131+| `jibb-page-main` | Full checking of byte-identical static and direct data pages through real readers, exact main types, downstream imports and rejection guards | |
132+| `jibb-poke-bridge` | Source-backed prelude and poke-only API reports | `tests/type-poke/expected.txt` |
133+| `jibb-positional-face-guards` | Positional-call and nested-face guards | |
134+| `jibb-program-init` | Transactional direct-program initializer recovery, exact exported/imported types and fail-closed boundaries | |
135+| `jibb-program-main` | The narrow closed subscription-free program-main interface, downstream import and rejection guards | |
136+| `jibb-program-update` | Transactional direct-program update result recovery, union/boolean context, exact exported/imported types and fail-closed boundaries | |
137+| `jibb-program-watch` | Direct singleton request-value watchability against merged real-todo evidence, exact types/imports and rejection boundaries | |
138+| `jibb-proj-guards` | Projection evidence, name-scope and dependency guards | |
139+| `jibb-qath-fuel` | Recursive qath unfolding and face guards: unfolding uses bounded fuel and keeps uncertain faces | |
140+| `jibb-qath-source` | Qath source-provenance guards: source-backed qath accepts only the proven public and internal interfaces | |
141+| `jibb-request-guards` | Request evidence, source consistency and cache provenance guards | |
142+| `jibb-store` | The unchanged cart/basket through detailed and legacy inference, exact store/derived schemes, malformed-prelude guards, structural imports, source-bound state watch evidence and rejection guards | |
143+| `jibb-sub-guards` | Source-backed subscription mold dependencies | |
144+| `jibb-theme` | Full checking of the byte-identical real theme, its exact exported type, structural downstream import, dark absent/present forms and rejection guards | |
145+| `jibb-tlon-bridge` | The real, unmodified Tlon presence source through the importer and partial checker | `tests/type-tlon/expected.txt` |
146+| `jibb-todo-api` | The actual todo API through the real Hoon readers and partial checker | `tests/type-todo-api/expected.txt` and `negative-expected.txt` |
147+| `jibb-todo-full` | Full checking of the byte-identical todo island and an ordinary call-bodied annotated-initializer variant through real readers, exact main types, structural downstream import and rejection controls | `tests/type-todo-full/expected.txt` |
148+| `jibb-todo-partial` | Partial inference reports for the unchanged todo island through the real API and readers | `tests/type-todo-partial/expected.txt` |
149+| `jibb-typecheck` | The partial inference unifier, through the library's own `+itype-unify-test` cases | `tests/checker/unification.txt` |
150+| `jibb-union-alias-overlap` | Source-backed generic-alias overlap witnesses | `tests/type-union-alias-overlap/expected.txt` |
151+| `jibb-union-source` | Bounded local generic-alias disjointness and state guards | `tests/type-union-source/expected.txt` |
152+
153+`jibb-deferred` exercises the bounded, source-owned constructor transaction and low-level freshness/replay guards. `jibb-deferred-resolver` checks the experimental import-free library resolver, report consistency, atomic failure, and that both source orders of a late face constraint decline. `jibb-deferred-prepared` checks the separate partial-report-only prepared-prelude route, direct tuple-literal obligations, exact report types and its wrong-field, unrelated-tag, mold-collision and no-final-cast controls. These suites do not establish island-kind or watchability support.
154+
137155## Before pushing
138156
139157```
@@ -142,13 +160,13 @@ tools/check --group eval # only the checks that need no ship, as CI runs the
142160nix flake check # the same checks in the Nix sandbox, on a fresh fake ~zod
143161```
144162
145−`tools/check` runs every check the repo has. Their one list is `CHECKS` in the script, so a new check goes there, as well as in the table above; `tools/check --list` prints it with each check's command. The eval group, the 62 checks that need only `urbit` and Python, runs several at a time (`-j`, by default one per CPU), the slowest first. The ship group, `ship-selftest`, `ship-test`, `check-commit` and `clay-fixtures`, then runs one check at a time on the ship `tools/ship` talks to; `tools/check` starts it if it isn't running and stops it again afterwards. Name checks, or globs, to run only those: `tools/check golden 'type-todo-*'`. A failing check's output follows its FAIL line; `-v` prints every check's output, and `--logs DIR` keeps it all.
163+`tools/check` runs every check the repo has. Their one list is `CHECKS` in the script, so a new check goes there, as well as in the table above; `tools/check --list` prints it with each check's command. A new suite in `tests/lib` needs no new check: `arms-1` to `arms-4` run every suite's arms, in shards of about equal time, and a slow suite's cost belongs in `COSTS` in `tools/test-arms`, which balances them. The eval group, the 13 checks that need only `urbit` and Python, runs several at a time (`-j`, by default one per CPU), the slowest first. The ship group, `ship-selftest`, `ship-test`, `check-commit` and `clay-fixtures`, then runs one check at a time on the ship `tools/ship` talks to; `tools/check` starts it if it isn't running and stops it again afterwards. Name checks, or globs, to run only those: `tools/check golden 'arms-*'`. To run one suite under eval, use `tools/test-arms <suite>`, as `tools/test-arms jibb-todo-full`. A failing check's output follows its FAIL line; `-v` prints every check's output, and `--logs DIR` keeps it all.
146164
147165CI, [.github/workflows/check.yml](../.github/workflows/check.yml), builds the desks and runs the eval group through the flake on every push to `master` and every pull request. It doesn't run the ship group, so run that before pushing.
148166
149167`ship-selftest` matters most when `tools/ship` changed, and `check-commit` when the mark or the desks changed, but `tools/check` runs both every time. The self-test leaves fixture files on the `jibb-dev` desk, and `ship-test`, which runs after it, puts the real ones back.
150168
151−`tools/ship test` regenerates `tests/lib/jibb.hoon` and syncs the `jibb-dev` desk before it runs. The file is ignored by git, since desk assembly always regenerates it. Sync preflights and splits large deletion lists into bounded click requests, waiting for each Clay revision; a failure stops later batches. The ship self-test exercises this when switching from the full desk to a smaller fixture desk. A run with `--stub`, `--lib`, or a custom `--golden` isolates its generated golden tests from the repository's other test programs; run the default command afterward to restore and test those programs. It also runs the independent `tests/lib/jibb-import.hoon` test against the same importer fixtures and expected diagnostic projection as `tools/importer-test`. The projection is an internal tree, not the Jibb type printer. `tests/lib/jibb-bridge.hoon` also runs the importer/checker bridge fixture on the ship; `tools/type-import-test` runs the same report under eval. `tests/lib/jibb-tlon-bridge.hoon` and `tools/type-tlon-test` run the real Tlon presence reader/checker fixture on both. The structured reader diagnostics have their own `tests/lib/jibb-import-diagnostic.hoon` ship test and `tools/type-import-diagnostic-test` eval test. The mark bridge has its own `tests/lib/jibb-mark-bridge.hoon` ship test and `tools/type-mark-test` eval test; both compare the same fixture report. `tests/lib/jibb-poke-bridge.hoon` and `tools/type-poke-test` share the source-backed prelude and poke-only API fixture. `tests/lib/jibb-api-paths.hoon` and `tools/type-api-paths-test` share partial path analysis over the real todo marks; this does not generate request interfaces. `tests/lib/jibb-module-scope.hoon` and `tools/type-module-scope-test` compare the prelude scope report on the ship and under eval.
169+`tools/ship test` regenerates `tests/lib/jibb.hoon` and syncs the `jibb-dev` desk before it runs. The file is ignored by git, since desk assembly always regenerates it. Sync preflights and splits large deletion lists into bounded click requests, waiting for each Clay revision; a failure stops later batches. The ship self-test exercises this when switching from the full desk to a smaller fixture desk. A run with `--stub`, `--lib`, or a custom `--golden` isolates its generated golden tests from the repository's other test programs; run the default command afterward to restore and test those programs. `tools/ship test` also runs every other suite in `tests/lib`, and `tools/test-arms` runs the same suites under eval, so each compares the same fixtures and golden files in both places. `tests/lib/jibb-import.hoon` runs the importer fixtures against their expected diagnostic projection, an internal tree, not the Jibb type printer. `tests/lib/jibb-bridge.hoon` runs the importer/checker bridge fixture, and `tests/lib/jibb-tlon-bridge.hoon` the real Tlon presence reader/checker fixture. `tests/lib/jibb-import-diagnostic.hoon` covers the structured reader diagnostics, and `tests/lib/jibb-mark-bridge.hoon` compares the mark bridge's fixture report. `tests/lib/jibb-poke-bridge.hoon` holds the source-backed prelude and poke-only API fixture. `tests/lib/jibb-api-paths.hoon` runs partial path analysis over the real todo marks; this does not generate request interfaces. `tests/lib/jibb-module-scope.hoon` compares the prelude scope report.
152170
153171## Golden cases
154172
@@ -187,5 +205,3 @@ Write `source.jibb` and `about.txt` by hand, run `tools/golden --update --case <
187205## Commits
188206
189207A short subject in the imperative, then a body that says what changed and why, wrapped at 72 columns, as in `git log`. Each commit leaves every check passing.
190−
191−`tools/type-deferred-test` exercises the bounded, source-owned constructor transaction and low-level freshness/replay guards. `tools/type-deferred-resolver-test` checks the experimental import-free library resolver, report consistency, atomic failure, and that both source orders of a late face constraint decline. `tools/type-deferred-prepared-test` checks the separate partial-report-only prepared-prelude route, direct tuple-literal obligations, exact report types and its wrong-field, unrelated-tag, mold-collision and no-final-cast controls. These checks do not establish island-kind or watchability support.
docs/status.md+48−41
@@ -27,11 +27,11 @@ The internal prelude also defines `qath` as a transparent recursive knot sequenc
2727
2828The checker also recognizes a limited source-proven generic recursive tree in an import-free defining module. Its nominal identity retains the defining path, mold name and type arguments, including across supported imports and aliases. With a known expected type it can construct supported tagged cases by checking one source-proven layer at a time. Flat matches with explicit tags or nonbinding catch-alls also work for these source-proven trees, as does a missing-case diagnostic for a supported single-arm match. At most 128 arms are screened per attempt; whole-case binders and nested patterns remain unsupported. Broader pattern matching, general structural fits and gate-free proof remain unsupported; this is not yet the prelude's `element` implementation or island checking. The source index uses fixed-shape checks during mold collection. Each construction or supported pattern attempt has 256 unfolding steps and at most 4,096 face and substitution visits per scan; pattern subject recognition and view validation can each scan separately. Parsing, other inference and retries remain outside those limits. A single startup-inclusive comparison of 1,000 ordinary gates produced identical reports and used 29.12 seconds of user CPU before the shared-resolver refactor and 28.55 seconds after it, with other work running; it is not a general performance bound.
2929
30−A bounded local source proof recognizes a narrow class of generic-alias union cases with different literal heads, then applies the ordinary mold checks. Nested or qualified aliases and several open states remain unsupported, including a valid alias used during the deferred transaction; the partial report states that the mold itself has not been checked. `tools/type-union-source-test` exercises the source and state bounds and failure paths under eval and on the ship. A separate bounded witness now reports proven collisions between supported literal-headed aliases, with both original case sites; unknown payload intersections still decline. The detailed full-module result now carries the first failed mold’s source-bound overlap evidence, including through ordinary Jibb imports; the legacy text result renders both case excerpts. Specialized API and prelude paths remain limited. The shared guards pass under eval and on the ship.
30+A bounded local source proof recognizes a narrow class of generic-alias union cases with different literal heads, then applies the ordinary mold checks. Nested or qualified aliases and several open states remain unsupported, including a valid alias used during the deferred transaction; the partial report states that the mold itself has not been checked. The `jibb-union-source` suite, `tests/lib/jibb-union-source.hoon`, exercises the source and state bounds and failure paths under eval (`tools/test-arms jibb-union-source`) and on the ship (`tools/ship test`). A separate bounded witness now reports proven collisions between supported literal-headed aliases, with both original case sites; unknown payload intersections still decline. The detailed full-module result now carries the first failed mold’s source-bound overlap evidence, including through ordinary Jibb imports; the legacy text result renders both case excerpts. Specialized API and prelude paths remain limited. The shared guards pass under eval and on the ship.
3131
3232The checker can experimentally discharge a narrowly scoped direct-constructor constraint while resolving an import-free library without a prepared prelude. It preserves independent generalized schemes and publishes only after all source molds, values, and recorded constraints close. API/store paths, `main`, imports, prepared preludes, recursive groups, open constraints, projection actions, and `%grec` in the constraint graph remain unsupported by this route. The fallback also declines source shapes outside its bounded direct-call screen. It does not yet typecheck the unchanged todo island or establish watchability.
3333
34−A prepared-prelude partial report can recover a narrow import-free, non-main ordinary library initializer by deferring source-owned literals in a direct tuple until a later exact result cast. The prepared interface and declared-name inventories must agree exactly. API/store paths, `main` and imports remain excluded, and the ordinary full-module resolver does not publish the recovered interface. Wrong field types, unrelated tags and mold collisions fail closed; a no-final-cast control remains unchecked. `tools/type-deferred-prepared-test` checks the exact recovered types and unchanged `partial inference; module not checked` disclaimer under eval and on the ship. List-literal deferral and import-aware recovery remain unsupported.
34+A prepared-prelude partial report can recover a narrow import-free, non-main ordinary library initializer by deferring source-owned literals in a direct tuple until a later exact result cast. The prepared interface and declared-name inventories must agree exactly. API/store paths, `main` and imports remain excluded, and the ordinary full-module resolver does not publish the recovered interface. Wrong field types, unrelated tags and mold collisions fail closed; a no-final-cast control remains unchecked. The `jibb-deferred-prepared` suite, `tests/lib/jibb-deferred-prepared.hoon`, checks the exact recovered types and unchanged `partial inference; module not checked` disclaimer under eval and on the ship. List-literal deferral and import-aware recovery remain unsupported.
3535
3636Closed cell context can now flow through a bounded loobean branch while preserving the inferred value faces and original failed-inference behavior. Open or structurally uncertain substitutions and nested retry shapes remain unsupported. This does not by itself provide the remaining cross-definition context or complete island-kind and watchability checks needed by the unchanged todo island.
3737
@@ -121,7 +121,7 @@ Besides the plan's list:
121121
122122- 689 golden cases: 460 that parse and 229 that fail, each failure at a stated line and column. One failing case has an unclear expectation (corpus question 3). The newer type-output cases exercise only the partial inference fragment. Each case's `about.txt` quotes the doc's words it tests.
123123- The 689-case corpus passed under `urbit eval` in 107.0 s while other checks were running. The fake ship passed all 746 tests, including the source-overlap, structural-overlap, generic-union source and alias-overlap, full-module overlap, deferred-context, generic-recursion, generic-construction, generic-pattern, deferred-inference, empty-mold and cell-branch fixtures, importer, importer/checker and mark/checker bridges, module scope, unification, hole, qath, ask, default-wrapper importer, projection, arithmetic, generic-alias, positional-face, API-evidence, request, closed-gate, todo API, constructor, sub, nested-union, gate-free and direct-gate guards and the unchanged todo report. Desk sync took 111.2 s and the ship's `-test` run took 316.7 s. The importer golden compares 221 projections; `tools/clay-fixtures` builds the example Hoon fixtures through Clay, checks a recursive Ford import's origin, and passes Clay-built types through the Clay-built importer and partial checker.
124−- `tools/testdata/selftest` (22 checks), `tools/testdata/ship-selftest` and `tools/testdata/clay-fixtures-selftest` test the tools themselves; the last checks temporary Clay fixture cleanup and signal handling without a ship.
124+- `tools/testdata/selftest` (23 checks), `tools/testdata/ship-selftest` and `tools/testdata/clay-fixtures-selftest` test the tools themselves; the last checks temporary Clay fixture cleanup and signal handling without a ship.
125125- Two independent audits before 7c739b7, one of which compared the library with a reference parser written in Python from the doc over about 19,000 generated programs. Before ab797a9, a second Python parser, written from the decisions, agreed with the library on 8,000 generated programs and 900 hand-written probes.
126126- Speed: starting `urbit eval` and building the library takes about 27 s with the dev tools' `!:`, and 24 s without it (`tools/hoon --no-debug`). After that, a 2,000-line module of 400 definitions parses in about a second. Loops over definitions, arms, lines and items grow no stack; nesting costs a few stack frames a level, and 100,000 nested brackets still parse (library section 3).
127127
@@ -251,54 +251,61 @@ On a machine set up as [development.md](development.md) says:
251251
252252```
253253tools/golden # 660 cases under urbit eval
254−tools/importer-test # the Hoon importer fixture projection
255−tools/type-import-default-test # default-wrapped source proof golden
256−tools/type-import-test # the importer/checker bridge fixture
257−tools/type-import-overlap-test # source-aware Hoon overlap and provenance fixture
258−tools/type-import-structural-test # structural overlap and multi-case source fixture
259−tools/type-union-source-test # local generic-alias union guards
260−tools/type-union-alias-overlap-test # local generic-alias overlap diagnostics
261−tools/type-full-overlap-test # full-module overlap evidence
262−tools/type-tlon-test # the real Tlon reader/checker fixture
263−tools/type-mark-test # the mark/checker bridge fixture
264−tools/type-poke-test # the source-backed poke/API fixture
265−tools/type-api-evidence-test # API declaration evidence guards
266−tools/type-api-paths-test # partial API path metadata fixture
267−tools/type-hole-guards-test # hole defaulting and API interface guards
268−tools/type-list-alias-test # prelude list-alias guards
269−tools/type-generic-alias-test # generic union alias guards
270−tools/type-generic-recursion-test # source-proven generic recursion guards
271−tools/type-generic-construction-test # source-proven recursive construction guards
272−tools/type-generic-pattern-test # source-proven recursive pattern guards
273−tools/type-deferred-test # source-owned deferred inference guards
274−tools/type-deferred-resolver-test # resolver consistency and failure guards
275−tools/type-deferred-context-test # deferred source-order and branch guards
276−tools/type-deferred-prepared-test # prepared initializer reports and failure guards
277−tools/type-empty-test # empty molds and coverage guards
278−tools/type-cell-branch-test # branch context and rollback guards
279−tools/type-positional-face-guards-test # positional sample face guards
280−tools/type-qath-guards-test # qath source and unfolding guards
281−tools/type-ask-guards-test # ask source and bootstrap guards
282−tools/type-proj-guards-test # projection evidence and scope guards
283−tools/type-buttons-test # documented buttons schemes and exact pending-tag error
284−tools/type-theme-test # byte-identical real theme, exact type and rejection guards
285−tools/type-module-scope-test # module and prelude scope fixture
286−tools/type-program-main-test # closed program-main interface and rejection guards
287−tools/type-program-init-test # transactional direct-program initializer context guards
288−tools/type-program-update-test # transactional direct-program update context guards
289−tools/type-program-watch-test # direct request-value watchability guards
290−tools/type-todo-full-test # byte-identical full todo and rejection guards
254+tools/test-arms # the my-app copies, then every tests/lib suite under urbit eval
255+tools/test-arms --list # the suites and their arms; ", report" marks a golden report
256+tools/test-arms --copies # the tests/ copies of my-app files in tests/my-app-copies.txt match my-app
257+tools/test-arms --report jibb-import # print a golden-report suite's report
258+tools/test-arms --update jibb-import # write it to the suite's expected file
259+tools/test-arms jibb-import # the Hoon importer fixture projection
260+tools/test-arms jibb-import-default # default-wrapped source proof golden
261+tools/test-arms jibb-bridge # the importer/checker bridge fixture
262+tools/test-arms jibb-import-overlap # source-aware Hoon overlap and provenance fixture
263+tools/test-arms jibb-import-structural # structural overlap and multi-case source fixture
264+tools/test-arms jibb-union-source # local generic-alias union guards
265+tools/test-arms jibb-union-alias-overlap # local generic-alias overlap diagnostics
266+tools/test-arms 'jibb-full-overlap-*' # full-module overlap evidence, in two suites
267+tools/test-arms jibb-tlon-bridge # the real Tlon reader/checker fixture
268+tools/test-arms jibb-mark-bridge # the mark/checker bridge fixture
269+tools/test-arms jibb-poke-bridge # the source-backed poke/API fixture
270+tools/test-arms jibb-api-evidence # API declaration evidence guards
271+tools/test-arms jibb-api-paths # partial API path metadata fixture
272+tools/test-arms jibb-hole-guards # hole defaulting and API interface guards
273+tools/test-arms jibb-list-alias-guards # prelude list-alias guards
274+tools/test-arms jibb-generic-alias # generic union alias guards
275+tools/test-arms jibb-generic-recursion # source-proven generic recursion guards
276+tools/test-arms jibb-generic-construction # source-proven recursive construction guards
277+tools/test-arms jibb-generic-pattern # source-proven recursive pattern guards
278+tools/test-arms jibb-deferred # source-owned deferred inference guards
279+tools/test-arms jibb-deferred-resolver # resolver consistency and failure guards
280+tools/test-arms jibb-deferred-context # deferred source-order and branch guards
281+tools/test-arms jibb-deferred-prepared # prepared initializer reports and failure guards
282+tools/test-arms jibb-empty # empty molds and coverage guards
283+tools/test-arms jibb-cell-branch # branch context and rollback guards
284+tools/test-arms jibb-positional-face-guards # positional sample face guards
285+tools/test-arms 'jibb-qath-*' # qath source and unfolding guards, in two suites
286+tools/test-arms jibb-ask-guards # ask source and bootstrap guards
287+tools/test-arms jibb-proj-guards # projection evidence and scope guards
288+tools/test-arms jibb-buttons # documented buttons schemes and exact pending-tag error
289+tools/test-arms jibb-theme # byte-identical real theme, exact type and rejection guards
290+tools/test-arms jibb-module-scope # module and prelude scope fixture
291+tools/test-arms jibb-program-main # closed program-main interface and rejection guards
292+tools/test-arms jibb-program-init # transactional direct-program initializer context guards
293+tools/test-arms jibb-program-update # transactional direct-program update context guards
294+tools/test-arms jibb-program-watch # direct request-value watchability guards
295+tools/test-arms jibb-todo-full # byte-identical full todo and rejection guards
291296tools/hoon check-spans-test # prints <<>> when the span checker works
292297tools/testdata/selftest # the tools themselves
293298tools/doc-blocks docs/spec # the doc's examples are golden cases
294299tools/ship start
295−tools/ship test # the same 660 cases as -test arms on the ship
300+tools/ship test # the same 660 cases, and every tests/lib suite, as -test arms on the ship
296301tools/testdata/ship-selftest
297302tools/testdata/clay-fixtures-selftest # scratch fixture cleanup without a ship
298303tools/ship check-commit # |commit stores .jibb files
299304tools/clay-fixtures # example /sur files and marks build through Clay
300305```
301306
307+`tools/test-arms` runs the `test-` arms of the `tests/lib` suites under eval, and `tools/ship test` runs the same arms on the ship. [The test suites](development.md#the-test-suites) in development.md says what each suite checks. `tools/check` runs them in four shards balanced by measured cost, `arms-1` to `arms-4`; `tools/check --list` prints its checks, and `tools/test-arms --shard 2/4 --list` the suites in one shard. Where a comment above says byte-identical, the suite reads a copy of the `my-app` file kept under `tests/`. `tools/test-arms --copies`, and `tools/test-arms` with no suite or shard named, check that every copy listed in `tests/my-app-copies.txt` still matches its source; naming a suite skips that check.
308+
302309## What milestone 1 leaves to later milestones
303310
304311- Errors carry a start only. Spans keep each node's end so that milestone 2's type errors can underline both conflicting sites with excerpts (library section 1).
tests/lib/jibb-api-paths.hoon+5−2
@@ -19,6 +19,9 @@
1919 |= lines=wain
2020 ^- @t
2121 (rap 3 (turn lines |=(line=@t (cat 3 line '\0a'))))
22+++ report
23+ ^- @t
24+ (of-wain:format (fixture-output prelude internal (text sur) (text action) (text todos) (text update) (text item) (text api) (text missing-decl) (text value-clash) (text poke-clash) (text scry) (text scry-bad)))
2225++ test-api-path-analysis
2326 ^- tang
2427 ?~ sur ~[leaf+"API path fixture sur is missing"]
@@ -33,9 +36,9 @@
3336 ?~ scry ~[leaf+"API path fixture scry is missing"]
3437 ?~ scry-bad ~[leaf+"API path fixture scry-bad is missing"]
3538 ?~ expected ~[leaf+"API path expected output is missing"]
36− =/ got (fixture-output prelude internal (text sur) (text action) (text todos) (text update) (text item) (text api) (text missing-decl) (text value-clash) (text poke-clash) (text scry) (text scry-bad))
39+ =/ got=@t report
3740 :: A definite error's report spans several lines of expected.txt.
38− ?. =((to-wain:format (of-wain:format got)) expected) ~[leaf+"API path analysis output differs from expected.txt"]
41+ ?. =((to-wain:format got) expected) ~[leaf+"API path analysis output differs from expected.txt"]
3942 ~
4043++ show-result
4144 |= [label=@t result=(each (list iapi-path-typed:jibb) @t)]
tests/lib/jibb-bridge.hoon+4−1
@@ -8,12 +8,15 @@
88 |= lines=wain
99 ^- @t
1010 (rap 3 (turn lines |=(line=@t (cat 3 line '\0a'))))
11+++ report
12+ ^- @t
13+ (bridge-output (text sur) (text source))
1114++ test-import-bridge
1215 ^- tang
1316 ?~ sur ~[leaf+"import bridge /sur fixture is missing"]
1417 ?~ source ~[leaf+"import bridge source is missing"]
1518 ?~ expected ~[leaf+"import bridge expected output is missing"]
16− =/ got (bridge-output (text sur) (text source))
19+ =/ got=@t report
1720 ?. =((to-wain:format (cat 3 got '\0a')) expected)
1821 ~[leaf+"import bridge output differs from tests/type-import/expected.txt"]
1922 ~
tests/lib/jibb-deferred-context.hoon+6−2
@@ -14,6 +14,10 @@
1414 |= lines=wain
1515 ^- @t
1616 (rap 3 (turn lines |=(line=@t (cat 3 line '\0a'))))
17+++ report
18+ ^- @t
19+ =/ at=path /ui/context/jibb
20+ (golden-types-with-marks:jibb at (text rich) ~ ~)
1721++ test-context
1822 ^- tang
1923 =/ at=path /ui/context/jibb
@@ -41,8 +45,8 @@
4145 ?~ reveal-ship ~[leaf+"ship result missing"]
4246 ?. ?=([%atom %t] typ.u.reveal) ~[leaf+"text result changed"]
4347 ?. ?=([%atom %p] typ.u.reveal-ship) ~[leaf+"ship result changed"]
44− =/ report=@t (golden-types-with-marks:jibb at source ~ ~)
45− ?. =((to-wain:format (cat 3 report '\0a')) expected) ~[leaf+"report differs from committed types"]
48+ =/ got=@t report
49+ ?. =((to-wain:format (cat 3 got '\0a')) expected) ~[leaf+"report differs from committed types"]
4650 =/ rest-good=(list wain) ~[plain simple]
4751 =/ checked=?
4852 %+ levy rest-good
tests/lib/jibb-deferred-resolver.hoon+4−1
@@ -87,9 +87,12 @@
8787 ==
8888 =. lines (snoc lines (case-no-fallback good public internal))
8989 (of-wain:format lines)
90+++ report
91+ ^- @t
92+ (resolver-report (text good) (text conflict) (text missing) (text hole) (text duplicate) (text face) (text store) public internal)
9093++ test-deferred-resolver
9194 ^- tang
92− =/ result=@t (resolver-report (text good) (text conflict) (text missing) (text hole) (text duplicate) (text face) (text store) public internal)
95+ =/ result=@t report
9396 ?. =((to-wain:format (cat 3 result '\0a')) expected) ~[leaf+"deferred resolver report differs"]
9497 =/ closed=itype:jibb [%cell [%face %foo [%atom %t]] [%atom %t]]
9598 =/ open=itype:jibb [%cell [%face %foo [%var 500]] [%atom %t]]
tests/lib/jibb-deferred.hoon+4−1
@@ -242,9 +242,12 @@
242242 =. lines (weld lines case-grec-scan)
243243 =. lines (weld lines ~[case-default-behavior case-screen-bounds])
244244 (of-wain:format lines)
245+++ report
246+ ^- @t
247+ (deferred-report (text nested-src) (text principal-src) (text missing-src) (text conflict-src) (text duplicate-src) (text hole-src) (text local-src) (text mutual-src) (text mold-hole-src) (text face-good-src) (text face-bad-src))
245248++ test-deferred
246249 ^- tang
247− =/ result=@t (deferred-report (text nested-src) (text principal-src) (text missing-src) (text conflict-src) (text duplicate-src) (text hole-src) (text local-src) (text mutual-src) (text mold-hole-src) (text face-good-src) (text face-bad-src))
250+ =/ result=@t report
248251 ?. =((to-wain:format (cat 3 result '\0a')) expected) ~[leaf+"deferred partial transaction report differs"]
249252 ~
250253--
tests/lib/jibb-direct-gate-source.hoon+5−1
@@ -32,6 +32,10 @@
3232 ?: !=(1 (lent projections.i.defs)) ~["unexpected projection action count"]
3333 ?. =(steps.i.projections.i.defs ~[[%count 2] [%label 6]]) ~["projection axes changed"]
3434 ~
35+++ report
36+ ^- @t
37+ =/ prepared=(unit iprelude:jibb) (direct-gate-prepared real-prelude real-internal)
38+ (direct-gate-source-output (text source) prepared)
3539++ test-direct-gate-source
3640 ^- tang
3741 ?~ source ~[leaf+"direct gate source is missing"]
@@ -39,7 +43,7 @@
3943 =/ prepared=(unit iprelude:jibb) (direct-gate-prepared real-prelude real-internal)
4044 =/ errors=(list tape) (direct-gate-projection-errors prepared)
4145 ?^ errors (turn errors |=(reason=tape leaf+reason))
42− =/ got=@t (direct-gate-source-output (text source) prepared)
46+ =/ got=@t report
4347 ?. =((to-wain:format (cat 3 got '\0a')) expected)
4448 ~[leaf+"direct gate source output differs from its golden"]
4549 ~
tests/lib/jibb-empty.hoon+4−2
@@ -152,6 +152,9 @@
152152 =/ unit-report=@t (golden-types-with-prepared-prelude:jibb f unit-dead ~ ~ ~ prep)
153153 =/ late-report=@t (golden-types-with-prepared-prelude:jibb f late-cap ~ ~ ~ prep)
154154 (rap 3 ~[(of-wain:format (turn checks line)) '\0a' report '\0a' overlap-report '\0a' dead-report '\0a' missing-report '\0a' list-report '\0a' unit-report '\0a' late-report])
155+++ report
156+ ^- @t
157+ (empty-output real-prelude real-internal (text good) (text overlap) (text dead) (text missing) (text standard-good) (text list-dead) (text unit-dead) (text late-cap) (text list-live) (text list-open) (text face-source))
155158++ test-empty
156159 ^- tang
157160 ?~ good ~[leaf+"empty source missing"]
@@ -166,8 +169,7 @@
166169 ?~ list-open ~[leaf+"generic list source missing"]
167170 ?~ face-source ~[leaf+"face source missing"]
168171 ?~ expected ~[leaf+"expected output missing"]
169− =/ actual=@t
170− (empty-output real-prelude real-internal (text good) (text overlap) (text dead) (text missing) (text standard-good) (text list-dead) (text unit-dead) (text late-cap) (text list-live) (text list-open) (text face-source))
172+ =/ actual=@t report
171173 ?. =((to-wain:format (cat 3 actual '\0a')) expected)
172174 ~[leaf+"empty mold output differs from expected"]
173175 ~
tests/lib/jibb-full-overlap-basic.hoon+4−1
@@ -180,10 +180,13 @@
180180 ^- @t
181181 =/ result=(list [@t ?]) (run same zero unsupported precedence duplicate invalid distinct parent child generic duplicate-generic atoms flag nested order)
182182 (of-wain:format (turn result |=(entry=[@t ?] (crip "{(trip -.entry)}: {?:(+.entry "ok" "BAD")}"))))
183+++ report
184+ ^- @t
185+ (output (text same) (text zero) (text unsupported) (text precedence) (text duplicate) (text invalid) (text distinct) (text parent) (text child) (text generic) (text duplicate-generic) (text atoms) (text flag) (text nested) (text order))
183186++ test-full-overlap-basic
184187 ^- tang
185188 ?~ expected ~[leaf+"expected output missing"]
186− =/ actual=@t (output (text same) (text zero) (text unsupported) (text precedence) (text duplicate) (text invalid) (text distinct) (text parent) (text child) (text generic) (text duplicate-generic) (text atoms) (text flag) (text nested) (text order))
189+ =/ actual=@t report
187190 ?. =((to-wain:format (cat 3 actual '\0a')) expected)
188191 ~[leaf+"full-module overlap output differs"]
189192 ~
tests/lib/jibb-full-overlap-graph.hoon+4−1
@@ -116,10 +116,13 @@
116116 ^- @t
117117 =/ result=(list [@t ?]) (run parent child distinct)
118118 (of-wain:format (turn result |=(entry=[@t ?] (crip "{(trip -.entry)}: {?:(+.entry "ok" "BAD")}"))))
119+++ report
120+ ^- @t
121+ (output (text parent) (text child) (text distinct))
119122++ test-full-overlap-graph
120123 ^- tang
121124 ?~ expected ~[leaf+"expected output missing"]
122− =/ actual=@t (output (text parent) (text child) (text distinct))
125+ =/ actual=@t report
123126 ?. =((to-wain:format (cat 3 actual '\0a')) expected)
124127 ~[leaf+"full-module overlap output differs"]
125128 ~
tests/lib/jibb-gate-free-source.hoon+4−1
@@ -87,9 +87,12 @@
8787 =/ errors (skim errors |=(x=@t !=(x '')))
8888 ?^ errors (of-wain:format errors)
8989 'todo model: gate-free\0acallback model: gate at callback\0anoun model: unknown\0azero fuel: unknown\0aoversized fuel: capped\0ainvalid inputs: rejected\0asource evidence: retained\0amatching root and unused sur: accepted\0aroot import cycle: rejected'
90+++ report
91+ ^- @t
92+ (gate-free-source-report prelude internal (text sur) (text action) (text todos) (text update) (text item) (text api) (text source) (text gate-source) (text noun-source))
9093++ test-gate-free-source
9194 ^- tang
92− =/ actual (gate-free-source-report prelude internal (text sur) (text action) (text todos) (text update) (text item) (text api) (text source) (text gate-source) (text noun-source))
95+ =/ actual=@t report
9396 ?. =((to-wain:format (cat 3 actual '\0a')) expected) ~[leaf+"gate-free mold report differs from expected"]
9497 ~
9598--
tests/lib/jibb-generic-construction.hoon+4−2
@@ -121,6 +121,9 @@
121121 =/ aliases=@t (golden-types-with-prepared-prelude:jibb /tests/tree/alias-client/jibb alias-client ~ ~ modules prep)
122122 =/ no-event=@t (golden-types-with-prepared-prelude:jibb /tests/tree/no-event-client/jibb no-event-client ~ ~ small prep)
123123 (cat 3 (of-wain:format (turn checks line)) (cat 3 '\0a' (cat 3 report (cat 3 '\0a' (cat 3 aliases (cat 3 '\0a' no-event))))))
124+++ report
125+ ^- @t
126+ (construction-output real-prelude real-internal (text tree) (text alias) (text client) (text alias-client) (text tree-no-event) (text no-event-client) (text owner-positive) (text owner-negative) (text sibling-values))
124127++ test-generic-construction
125128 ^- tang
126129 ?~ tree ~[leaf+"tree source missing"]
@@ -133,8 +136,7 @@
133136 ?~ owner-negative ~[leaf+"invalid owner source missing"]
134137 ?~ sibling-values ~[leaf+"sibling source missing"]
135138 ?~ expected ~[leaf+"expected output missing"]
136− =/ actual=@t
137− (construction-output real-prelude real-internal (text tree) (text alias) (text client) (text alias-client) (text tree-no-event) (text no-event-client) (text owner-positive) (text owner-negative) (text sibling-values))
139+ =/ actual=@t report
138140 ?. =((to-wain:format (cat 3 actual '\0a')) expected)
139141 ~[leaf+"generic construction output differs from expected"]
140142 ~
tests/lib/jibb-generic-pattern.hoon+4−2
@@ -145,6 +145,9 @@
145145 =/ report=@t (golden-types-with-prepared-prelude:jibb /tests/tree/client/jibb client ~ ~ modules prep)
146146 =/ noreport=@t (golden-types-with-prepared-prelude:jibb /tests/tree/no-event/jibb no-event ~ ~ small prep)
147147 (cat 3 (of-wain:format (turn checks line)) (cat 3 '\0a' (cat 3 report (cat 3 '\0a' noreport))))
148+++ report
149+ ^- @t
150+ (pattern-output real-prelude real-internal (text tree) (text alias) (text tree-no-event) (text client) (text no-event) (text values) (text poly-values) (text owner) (text owner-bad))
148151++ test-generic-pattern
149152 ^- tang
150153 ?~ tree ~[leaf+"tree source missing"]
@@ -157,8 +160,7 @@
157160 ?~ owner ~[leaf+"owner source missing"]
158161 ?~ owner-bad ~[leaf+"invalid owner source missing"]
159162 ?~ expected ~[leaf+"expected output missing"]
160− =/ actual=@t
161− (pattern-output real-prelude real-internal (text tree) (text alias) (text tree-no-event) (text client) (text no-event) (text values) (text poly-values) (text owner) (text owner-bad))
163+ =/ actual=@t report
162164 ?. =((to-wain:format (cat 3 actual '\0a')) expected)
163165 ~[leaf+"generic pattern output differs from expected"]
164166 ~
tests/lib/jibb-generic-recursion.hoon+13−10
@@ -138,6 +138,18 @@
138138 =/ lines=(list @t) (weld (turn checks result-line) (weld invalid-lines (turn more result-line)))
139139 =/ report=@t (golden-types-with-prepared-prelude:jibb /tests/tree/client/jibb client ~ ~ modules prep)
140140 (cat 3 (of-wain:format lines) (cat 3 '\0a' report))
141+++ report
142+ ^- @t
143+ =/ invalid=(list [label=@t src=@t])
144+ :~ ['unused mold hole declined' (text bad-mold)]
145+ ['invalid constructor declined' (text bad-constructor)]
146+ ['invalid matching declined' (text bad-match)]
147+ ['nonuniform recursion declined' (text bad-parameter)]
148+ ['identical local shadow declined' (text local-shadow)]
149+ ['different local shadow declined' (text local-distinct)]
150+ ['local recursion declined' (text local-only)]
151+ ==
152+ (generic-output real-prelude real-internal (text tree) (text changed) (text alias) (text client) invalid (text list-shadow) (text chain))
141153++ test-generic-recursion
142154 ^- tang
143155 ?~ tree ~[leaf+"recursive source is missing"]
@@ -154,16 +166,7 @@
154166 ?~ list-shadow ~[leaf+"list shadow fixture is missing"]
155167 ?~ chain ~[leaf+"unindexed chain fixture is missing"]
156168 ?~ expected ~[leaf+"recursive expected output is missing"]
157− =/ invalid=(list [label=@t src=@t])
158− :~ ['unused mold hole declined' (text bad-mold)]
159− ['invalid constructor declined' (text bad-constructor)]
160− ['invalid matching declined' (text bad-match)]
161− ['nonuniform recursion declined' (text bad-parameter)]
162− ['identical local shadow declined' (text local-shadow)]
163− ['different local shadow declined' (text local-distinct)]
164− ['local recursion declined' (text local-only)]
165− ==
166− =/ actual=@t (generic-output real-prelude real-internal (text tree) (text changed) (text alias) (text client) invalid (text list-shadow) (text chain))
169+ =/ actual=@t report
167170 ?. =((to-wain:format (cat 3 actual '\0a')) expected)
168171 ~[leaf+"generic recursion output differs from expected"]
169172 ~
tests/lib/jibb-import-default.hoon+4−1
@@ -37,13 +37,16 @@
3737 ?~ p.malformed 'rejected'
3838 'accepted'
3939 (of-wain:format ~[(projection 'saga' tc %saga) (projection 'saga-envelope' tc %saga-envelope) (projection 'outer-good' cc %outer-good) (projection 'outer-overlap' cc %outer-bad) (projection 'recursive-overlap' cc %outer-bad-rec) (projection 'mutual-recursion' cc %outer-mutual) (projection 'shadow' sc %outer-good) (crip "default-wrapper-bound: {(trip bound)}") (crip "malformed-wrapper: {(trip malformed-status)}")])
40+++ report
41+ ^- @t
42+ (fixture-output (text tlon) (text controls) (text parent))
4043++ test-import-default
4144 ^- tang
4245 ?~ tlon ~[leaf+"Tlon default fixture missing"]
4346 ?~ controls ~[leaf+"default controls missing"]
4447 ?~ parent ~[leaf+"default shadow source missing"]
4548 ?~ expected ~[leaf+"default expected output missing"]
46− =/ got=@t (fixture-output (text tlon) (text controls) (text parent))
49+ =/ got=@t report
4750 ?. =((to-wain:format (cat 3 got '\0a')) expected)
4851 ~[leaf+"default-wrapper golden differs"]
4952 ~
tests/lib/jibb-import-diagnostic.hoon+4−1
@@ -10,6 +10,9 @@
1010 |= lines=wain
1111 ^- @t
1212 (rap 3 (turn lines |=(line=@t (cat 3 line '\0a'))))
13+++ report
14+ ^- @t
15+ (diagnostic-output (text sur) (text mark) (text source) (text nested))
1316++ test-import-diagnostic
1417 ^- tang
1518 ?~ sur ~[leaf+"diagnostic /sur fixture is missing"]
@@ -17,7 +20,7 @@
1720 ?~ source ~[leaf+"diagnostic source fixture is missing"]
1821 ?~ nested ~[leaf+"diagnostic nested source is missing"]
1922 ?~ expected ~[leaf+"diagnostic expected output is missing"]
20− =/ got (diagnostic-output (text sur) (text mark) (text source) (text nested))
23+ =/ got=@t report
2124 ?. =((to-wain:format (cat 3 got '\0a')) expected)
2225 ~[leaf+"import diagnostic output differs from tests/type-import-diagnostic/expected.txt"]
2326 ~
tests/lib/jibb-import-overlap.hoon+4−1
@@ -7,12 +7,15 @@
77 |= lines=wain
88 ^- @t
99 (rap 3 (turn lines |=(line=@t (cat 3 line '\0a'))))
10+++ report
11+ ^- @t
12+ (overlap-output (text sur) (text source))
1013++ test-import-overlap
1114 ^- tang
1215 ?~ sur ~[leaf+"overlap fixture source is missing"]
1316 ?~ source ~[leaf+"overlap fixture client is missing"]
1417 ?~ expected ~[leaf+"overlap fixture expected output is missing"]
15− =/ got (overlap-output (text sur) (text source))
18+ =/ got=@t report
1619 ?. =((to-wain:format (cat 3 got '\0a')) expected)
1720 ~[leaf+"overlap output differs from expected"]
1821 ~
tests/lib/jibb-import-structural.hoon+4−1
@@ -7,12 +7,15 @@
77 |= lines=wain
88 ^- @t
99 (rap 3 (turn lines |=(line=@t (cat 3 line '\0a'))))
10+++ report
11+ ^- @t
12+ (structural-output (text sur) (text source))
1013++ test-import-structural
1114 ^- tang
1215 ?~ sur ~[leaf+"structural overlap /sur is missing"]
1316 ?~ source ~[leaf+"structural overlap client is missing"]
1417 ?~ expected ~[leaf+"structural overlap expected is missing"]
15− =/ got (structural-output (text sur) (text source))
18+ =/ got=@t report
1619 ?. =((to-wain:format (cat 3 got '\0a')) expected)
1720 ~[leaf+"structural overlap output differs from expected"]
1821 ~
tests/lib/jibb-import.hoon+6−2
@@ -22,6 +22,10 @@
2222 ^- @t
2323 (rap 3 (turn lines |=(line=@t (cat 3 line '\0a'))))
2424::
25+++ report
26+ ^- @t
27+ (of-wain:format (fixture-output:jibb-import (lines-to-cord small) (lines-to-cord epic) (lines-to-cord presence) (lines-to-cord docs) (lines-to-cord shadow) (lines-to-cord shadow-static) (lines-to-cord ford) (lines-to-cord mark) (lines-to-cord mark-rec) (lines-to-cord mark-gate) (lines-to-cord mark-basic) (lines-to-cord origin-trans) (lines-to-cord origin-first) (lines-to-cord origin-other)))
28+::
2529++ test-importer-golden
2630 ^- tang
2731 ?~ small ~[leaf+"small importer fixture is missing"]
@@ -39,8 +43,8 @@
3943 ?~ origin-first ~[leaf+"origin alias fixture is missing"]
4044 ?~ origin-other ~[leaf+"distinct origin fixture is missing"]
4145 ?~ expected ~[leaf+"importer golden output is missing"]
42− =/ actual (fixture-output:jibb-import (lines-to-cord small) (lines-to-cord epic) (lines-to-cord presence) (lines-to-cord docs) (lines-to-cord shadow) (lines-to-cord shadow-static) (lines-to-cord ford) (lines-to-cord mark) (lines-to-cord mark-rec) (lines-to-cord mark-gate) (lines-to-cord mark-basic) (lines-to-cord origin-trans) (lines-to-cord origin-first) (lines-to-cord origin-other))
43− ?. =(actual expected)
46+ =/ got=@t report
47+ ?. =((to-wain:format (cat 3 got '\0a')) expected)
4448 ~[leaf+"importer projection differs from tests/importer/tree.txt"]
4549 ~
4650--
tests/lib/jibb-list-alias-guards.hoon+5−1
@@ -18,10 +18,14 @@
1818 =/ broken (golden-types-with-prelude:jibb /ui/test/jibb src ~ ~ ~ malformed)
1919 =/ cycle (golden-types-with-prelude:jibb /ui/test/jibb src ~ ~ ~ cyclic)
2020 (of-wain:format ~['canonical' good 'altered' bad 'omitted' missing 'duplicate' repeated 'malformed' broken 'cyclic' cycle])
21+++ report
22+ ^- @t
23+ list-alias-output
2124++ test-list-alias-guards
2225 ^- tang
2326 ?~ expected ~[leaf+"list alias expected output is missing"]
24− ?. =((to-wain:format (cat 3 list-alias-output '\0a')) expected)
27+ =/ got=@t report
28+ ?. =((to-wain:format (cat 3 got '\0a')) expected)
2529 ~[leaf+"list alias preparation differs from its golden"]
2630 ~
2731--
tests/lib/jibb-mark-bridge.hoon+4−1
@@ -10,6 +10,9 @@
1010 |= lines=wain
1111 ^- @t
1212 (rap 3 (turn lines |=(line=@t (cat 3 line '\0a'))))
13+++ report
14+ ^- @t
15+ (bridge-output (text declared) (text missing) (text sur) (text collision))
1316++ test-mark-bridge
1417 ^- tang
1518 ?~ declared ~[leaf+"mark bridge declared fixture is missing"]
@@ -17,7 +20,7 @@
1720 ?~ sur ~[leaf+"mark bridge /sur fixture is missing"]
1821 ?~ collision ~[leaf+"mark bridge collision fixture is missing"]
1922 ?~ expected ~[leaf+"mark bridge expected output is missing"]
20− =/ got (bridge-output (text declared) (text missing) (text sur) (text collision))
23+ =/ got=@t report
2124 ?. =((to-wain:format (cat 3 got '\0a')) expected)
2225 ~[leaf+"mark bridge output differs from tests/type-mark/expected.txt"]
2326 ~
tests/lib/jibb-module-scope.hoon+4−1
@@ -8,10 +8,13 @@
88/* real-right %jibb /tests/golden/types-prelude-interface/modules/ui/right/jibb
99/* real-expected %txt /tests/golden/types-prelude-interface/types/txt
1010|%
11+++ report
12+ ^- @t
13+ scope-output
1114++ test-module-scope
1215 ^- tang
1316 ?~ expected ~[leaf+"module scope expected output is missing"]
14− =/ got scope-output
17+ =/ got=@t report
1518 ?. =((to-wain:format (cat 3 got '\0a')) expected)
1619 ~[leaf+"module scope output differs from tests/type-module-scope/expected.txt"]
1720 ~
tests/lib/jibb-poke-bridge.hoon+4−1
@@ -20,6 +20,9 @@
2020 |= lines=wain
2121 ^- @t
2222 (rap 3 (turn lines |=(line=@t (cat 3 line '\0a'))))
23+++ report
24+ ^- @t
25+ (bridge-output prelude internal (text mark) (text api) (text client) (text direct) (text alias) (text public) (text fake) (text exported) (text transitive) (text inner) (text impostor-client) (text impostor))
2326++ test-poke-bridge
2427 ^- tang
2528 ?~ mark ~[leaf+"poke bridge mark fixture is missing"]
@@ -35,7 +38,7 @@
3538 ?~ impostor-client ~[leaf+"poke bridge impostor client is missing"]
3639 ?~ impostor ~[leaf+"poke bridge impostor fixture is missing"]
3740 ?~ expected ~[leaf+"poke bridge expected output is missing"]
38− =/ got (bridge-output prelude internal (text mark) (text api) (text client) (text direct) (text alias) (text public) (text fake) (text exported) (text transitive) (text inner) (text impostor-client) (text impostor))
41+ =/ got=@t report
3942 ?. =((to-wain:format (cat 3 got '\0a')) expected)
4043 ~[leaf+"poke bridge output differs from tests/type-poke/expected.txt"]
4144 ~
tests/lib/jibb-tlon-bridge.hoon+4−1
@@ -9,12 +9,15 @@
99 |= lines=wain
1010 ^- @t
1111 (rap 3 (turn lines |=(line=@t (cat 3 line '\0a'))))
12+++ report
13+ ^- @t
14+ (bridge-output (text presence) (text source))
1215++ test-tlon-bridge
1316 ^- tang
1417 ?~ presence ~[leaf+"Tlon presence fixture is missing"]
1518 ?~ source ~[leaf+"Tlon bridge source is missing"]
1619 ?~ expected ~[leaf+"Tlon bridge expected output is missing"]
17− =/ got (bridge-output (text presence) (text source))
20+ =/ got=@t report
1821 ?. =((to-wain:format (cat 3 got '\0a')) expected)
1922 ~[leaf+"Tlon bridge output differs from tests/type-tlon/expected.txt"]
2023 ~
tests/lib/jibb-todo-api.hoon+7−1
@@ -72,9 +72,15 @@
7272 ?~ bad 'real todo interface and atomic guards passed'
7373 (of-wain:format bad)
7474 [report bad-report guards]
75+++ todo-out
76+ ^- [report=@t bad-report=@t guards=@t]
77+ (todo-run prelude internal (text sur) (text action) (text todos) (text update) (text item) (text api) (text source) (text negative) (text unsupported))
78+++ report
79+ ^- @t
80+ report:todo-out
7581++ test-todo-api
7682 ^- tang
77− =/ out (todo-run prelude internal (text sur) (text action) (text todos) (text update) (text item) (text api) (text source) (text negative) (text unsupported))
83+ =/ out todo-out
7884 ?. =((to-wain:format (cat 3 report.out '\0a')) expected)
7985 ~[leaf+"todo API report differs from expected"]
8086 ?. =((to-wain:format (cat 3 bad-report.out '\0a')) negative-expected)
tests/lib/jibb-todo-full.hoon+6−3
@@ -63,6 +63,10 @@
6363 ?~ main 'full todo main missing'
6464 (cat 3 'full todo accepted\0a' (crip (show-itype:jibb typ.u.main ~)))
6565::
66+++ report
67+ ^- @t
68+ (todo-full-report prelude internal (text sur) (text action) (text todos) (text update) (text item) (text api) (text source))
69+::
6670++ todo-full-legacy-report
6771 |= [public=@t private=@t sur=@t action=@t todos=@t update=@t item=@t api=@t src=@t]
6872 ^- @t
@@ -123,9 +127,8 @@
123127::
124128++ test-todo-full
125129 ^- tang
126− =/ report=@t
127− (todo-full-report prelude internal (text sur) (text action) (text todos) (text update) (text item) (text api) (text source))
128− ?. =((to-wain:format (cat 3 report '\0a')) expected)
130+ =/ got=@t report
131+ ?. =((to-wain:format (cat 3 got '\0a')) expected)
129132 ~[leaf+"full todo report differs"]
130133 =/ legacy=@t
131134 (todo-full-legacy-report prelude internal (text sur) (text action) (text todos) (text update) (text item) (text api) (text source))
tests/lib/jibb-todo-partial.hoon+5−2
@@ -47,12 +47,15 @@
4747 (cat 3 label.c ': BAD accepted')
4848 =/ missing-module=@t (golden-types-with-prepared-prelude:jibb at source-text inputs marks ~ prepared)
4949 (of-wain:format (weld ~['unchanged todo: partial inference only' normal 'negative API imports'] (weld failures ~['missing module: partial report' missing-module])))
50+++ report
51+ ^- @t
52+ (todo-island-report prelude internal (text sur) (text action) (text todos) (text update) (text item) (text api) (text source))
5053++ test-todo-partial
5154 ^- tang
5255 ?~ source ~[leaf+"todo source fixture is missing"]
5356 ?~ expected ~[leaf+"todo partial report is missing"]
54− =/ report=@t (todo-island-report prelude internal (text sur) (text action) (text todos) (text update) (text item) (text api) (text source))
55− ?. =((to-wain:format (cat 3 report '\0a')) expected)
57+ =/ actual=@t report
58+ ?. =((to-wain:format (cat 3 actual '\0a')) expected)
5659 ~[leaf+"unchanged todo partial report differs from its golden"]
5760 ~
5861--
tests/lib/jibb-typecheck.hoon+7−5
@@ -2,13 +2,15 @@
22/+ jibb
33/* expected %txt /tests/checker/unification/txt
44|%
5+++ report
6+ ^- @t
7+ =/ failures=(list tape) itype-unify-test:jibb
8+ ?~ failures 'unification passed'
9+ (of-wain:format (turn failures crip))
510++ test-unification
611 ^- tang
712 ?~ expected ~[leaf+"unification golden is missing"]
8− =/ failures=(list tape) itype-unify-test:jibb
9− =/ actual=wain
10− ?~ failures ~['unification passed']
11− (turn failures crip)
12− ?: =(actual expected) ~
13+ =/ got=@t report
14+ ?: =((to-wain:format (cat 3 got '\0a')) expected) ~
1315 ~[leaf+"unification output differs from tests/checker/unification.txt"]
1416--
tests/lib/jibb-union-alias-overlap.hoon+4−1
@@ -98,10 +98,13 @@
9898 |= lines=wain
9999 ^- @t
100100 (rap 3 (turn lines |=(line=@t (cat 3 line '\0a'))))
101+++ report
102+ ^- @t
103+ (overlap-output (text positive) (text negative) (text nonzero) (text multi) (text opaque) (text wrong) (text duplicate) (text qualified) (text flag-source))
101104++ test-union-alias-overlap
102105 ^- tang
103106 ?~ expected ~[leaf+"expected output missing"]
104− =/ actual=@t (overlap-output (text positive) (text negative) (text nonzero) (text multi) (text opaque) (text wrong) (text duplicate) (text qualified) (text flag-source))
107+ =/ actual=@t report
105108 ?. =((to-wain:format (cat 3 actual '\0a')) expected) ~[leaf+"generic union overlap output differs"]
106109 ~
107110--
tests/lib/jibb-union-source.hoon+4−1
@@ -143,10 +143,13 @@
143143 |= lines=wain
144144 ^- @t
145145 (rap 3 (turn lines |=(line=@t (cat 3 line '\0a'))))
146+++ report
147+ ^- @t
148+ (source-output prelude internal (text good) (text same) (text zero) (text nested) (text duplicate) (text wrong) (text duplicate-params) (text hidden-ref) (text qualified) (text direct-source) (text wide-source) (text free-source) (text late-source) (text shadow-source) (text mixed-source))
146149++ test-union-source
147150 ^- tang
148151 ?~ expected ~[leaf+"expected output missing"]
149− =/ actual=@t (source-output prelude internal (text good) (text same) (text zero) (text nested) (text duplicate) (text wrong) (text duplicate-params) (text hidden-ref) (text qualified) (text direct-source) (text wide-source) (text free-source) (text late-source) (text shadow-source) (text mixed-source))
152+ =/ actual=@t report
150153 ?. =((to-wain:format (cat 3 actual '\0a')) expected) ~[leaf+"generic union source output differs"]
151154 ~
152155--
tests/my-app-copies.txtnew file+56
@@ -0,0 +1,56 @@
1+# Files under tests/ that copy a my-app source, for the checks that
2+# cannot read my-app, which is not on the jibb-dev desk. tools/test-arms
3+# checks every pair before it runs anything (--copies runs only that).
4+#
5+# COPY SOURCE [without LINE]: the copy equals the source, or the source
6+# with the first occurrence of LINE and its newline removed.
7+
8+tests/golden/doc-grammar-02-buttons/source.jibb my-app/ui/components/buttons.jibb
9+tests/golden/doc-grammar-06-cart-store/source.jibb my-app/ui/stores/cart.jibb
10+tests/golden/doc-grammar-07-basket/source.jibb my-app/ui/basket.jibb
11+tests/golden/doc-overview-02-theme/source.jibb my-app/ui/theme.jibb
12+tests/golden/doc-overview-04-todo-api/source.jibb my-app/ui/api/todo.jibb
13+tests/golden/doc-overview-08-about/source.jibb my-app/ui/about.jibb
14+tests/golden/doc-overview-09-blog-index/source.jibb my-app/ui/blog/index.jibb
15+tests/golden/doc-overview-10-todo-list/source.jibb my-app/ui/todo-list.jibb
16+tests/golden/doc-overview-11-index/source.jibb my-app/ui/index.jibb
17+tests/golden/fixture-blog-api/source.jibb my-app/ui/api/blog.jibb
18+tests/golden/fixture-blog-card/source.jibb my-app/ui/components/card.jibb
19+tests/golden/module-import-api-derived-clash/mar/full.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
20+tests/golden/module-import-api-import-error/mar/full.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
21+tests/golden/module-import-api-mark-prelude-value/mar/same.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
22+tests/golden/module-import-api-mark-value/mar/full.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
23+tests/golden/module-import-api-nested-path/mar/full.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
24+tests/golden/module-import-api-paths-mark-value/mar/full.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
25+tests/golden/module-import-api-paths-mark-value/mar/other.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
26+tests/golden/module-import-api-paths-scope-conflict/mar/full.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
27+tests/golden/module-import-api-poke-clash/mar/full.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
28+tests/golden/module-import-api-request-reason/mar/full.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
29+tests/golden/module-import-api-scope-conflict/mar/full.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
30+tests/golden/module-import-root-import-shadow/mar/label.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
31+tests/golden/types-import-mark/mar/label.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
32+tests/golden/types-module-fixtures/modules/ui/api/blog.jibb my-app/ui/api/blog.jibb
33+tests/golden/types-module-fixtures/modules/ui/components/card.jibb my-app/ui/components/card.jibb
34+tests/golden/types-module-fixtures/source.jibb my-app/ui/blog/index.jibb
35+tests/golden/types-module-mixed/mar/label.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
36+tests/golden/types-request-normal/mar/full.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
37+tests/type-api-paths/api.txt my-app/ui/api/todo.jibb
38+tests/type-api-paths/todo-action.txt my-app/mar/todo-action.hoon without /- todo
39+tests/type-api-paths/todo-item.txt my-app/mar/todo-item.hoon without /- todo
40+tests/type-api-paths/todo-sur.txt my-app/sur/todo.hoon
41+tests/type-api-paths/todo-update.txt my-app/mar/todo-update.hoon without /- todo
42+tests/type-api-paths/todos.txt my-app/mar/todos.hoon without /- todo
43+tests/type-gate-free/todo.txt my-app/ui/todo-list.jibb
44+tests/type-page-main/blog-api.txt my-app/ui/api/blog.jibb
45+tests/type-page-main/blog-index.txt my-app/ui/blog/index.jibb
46+tests/type-page-main/blog-sur.txt my-app/sur/blog.hoon
47+tests/type-page-main/card.txt my-app/ui/components/card.jibb
48+tests/type-page-main/index.txt my-app/ui/index.jibb
49+tests/type-page-main/posts-mark.txt my-app/mar/posts.hoon without /- blog
50+tests/type-page-main/static.txt my-app/ui/about.jibb
51+tests/type-page-main/todo-api.txt my-app/ui/api/todo.jibb
52+tests/type-page-main/todo-island.txt my-app/ui/todo-list.jibb
53+tests/type-poke/mark.txt my-app/mar/label.hoon without :: Fixture for the Hoon mark importer; not supplied by the design doc.
54+tests/type-store/basket.txt my-app/ui/basket.jibb
55+tests/type-store/cart.txt my-app/ui/stores/cart.jibb
56+tests/type-theme/source.txt my-app/ui/theme.jibb
tests/type-api-evidence/expected.txtdeleted−1
@@ -1 +0,0 @@
1−normal watchable; scry not watchable; missing and duplicate unknown; request parts checked; support definitions checked
tests/type-gate-free/about.txt+1−1
@@ -1 +1 @@
1−The unchanged todo island source is used only to resolve its model mold through the actual todo API, /sur and mark readers. The eval runner verifies its copy matches the application source. Controls also add a callback or noun field and exercise unavailable, malformed and ambiguous input. This is partial mold analysis only: no complete module, island kind, runtime or watchability claim is made.
1+The unchanged todo island source is used only to resolve its model mold through the actual todo API, /sur and mark readers. tools/test-arms checks its copy against the application source through tests/my-app-copies.txt. Controls also add a callback or noun field and exercise unavailable, malformed and ambiguous input. This is partial mold analysis only: no complete module, island kind, runtime or watchability claim is made.
tests/type-todo-api/about.txt+1−1
@@ -1 +1 @@
1−The exact my-app todo API is checked with its actual /sur and mark reader fixtures. The eval runner verifies that the API fixture matches the application source. Positive and negative reports cover request callback polymorphism, the named one-diff fold, typed path arguments, poke, exported molds and a typed subscription expression. The interface guards check source and request evidence and reject missing or duplicate inputs, unsupported sibling declarations and private imports. Reports are partial inference, not a complete module check or runtime/watchability proof.
1+The exact my-app todo API is checked with its actual /sur and mark reader fixtures. tools/test-arms checks the API fixture against the application source through tests/my-app-copies.txt. Positive and negative reports cover request callback polymorphism, the named one-diff fold, typed path arguments, poke, exported molds and a typed subscription expression. The interface guards check source and request evidence and reject missing or duplicate inputs, unsupported sibling declarations and private imports. Reports are partial inference, not a complete module check or runtime/watchability proof.
tests/type-todo-full/about.txt+1−1
@@ -1,3 +1,3 @@
1−source: docs/spec/overview.md, worked example 3; my-app/ui/todo-list.jibb must remain byte-identical to tests/type-gate-free/todo.txt.
1+source: docs/spec/overview.md, worked example 3; my-app/ui/todo-list.jibb must remain byte-identical to tests/type-gate-free/todo.txt, which tools/test-arms checks through tests/my-app-copies.txt.
22tests: Full detailed and legacy checking of the unchanged todo island through the real Hoon readers and API. Assert the exact closed main type and structural downstream import, plus a variant whose initializer is a gate cast to its full type, which only ordinary inference accepts, so it fails if a keyed view skips ordinary inference again, and wrong model/message/result, ambiguous or open mapper, aliased mapper, non-gate view, and wrong watch rejection. The report does not execute Jibb or establish runtime watching.
33expect: shared eval and ship guards
tests/type-todo-partial/about.txt+1−1
@@ -1,4 +1,4 @@
11source: Overview, Worked examples: “`main.todo-list` is a record of exactly `init`, `update`, `view` and `subs`, whose types fix the data, model and messages.”
2−tests: The unchanged todo island is resolved using the real prelude, todo API, source-aware Hoon `/sur`, and mark readers. The report records partial inference only; it does not claim the module, island kind, gate-free conditions, runtime, or watchability were checked. Missing and duplicate marks, an unavailable selected `/sur` mold, and an unavailable API module remain rejected or explicitly unavailable. The eval runner verifies the mounted todo and API fixtures match their app sources.
2+tests: The unchanged todo island is resolved using the real prelude, todo API, source-aware Hoon `/sur`, and mark readers. The report records partial inference only; it does not claim the module, island kind, gate-free conditions, runtime, or watchability were checked. Missing and duplicate marks, an unavailable selected `/sur` mold, and an unavailable API module remain rejected or explicitly unavailable. `tools/test-arms` checks the mounted todo and API fixtures against their app sources through `tests/my-app-copies.txt`.
33expect: parses
44expect-types: a partial inference report
tools/check+16−56
@@ -71,64 +71,25 @@ def hoon(name, *args, expect):
7171
7272# Every check, in the order they start: the eval group, slowest first,
7373# then the ship group, in the order they must run. Times are from one
74−# run of every check, three at a time on four CPUs (2026-11-02).
74+# run on four CPUs (2026-11-03).
75+#
76+# arms-1 to arms-4 run the test- arms of every tests/lib suite under
77+# eval, in shards of about equal time (tools/test-arms --list --shard
78+# 2/4 shows the second). A new suite in tests/lib joins a shard by
79+# itself; a slow one belongs in COSTS in tools/test-arms.
80+ARM_SHARDS = 4
81+
7582CHECKS = [
76− tool('type-todo-full-test'), # about 580 s
77− tool('type-deferred-prepared-test'), # about 410 s
78− tool('golden'),
79− tool('importer-test'),
80− tool('type-import-default-test'),
81− tool('type-import-test'),
82− tool('type-import-overlap-test'),
83− tool('type-import-structural-test'),
84− tool('type-union-source-test'),
85− tool('type-union-alias-overlap-test'),
86− tool('type-full-overlap-test'),
87− tool('type-tlon-test'),
88− tool('type-import-diagnostic-test'),
89− tool('type-mark-test'),
90− tool('type-poke-test'),
91− tool('type-api-paths-test'),
92− tool('type-api-evidence-test'),
93− tool('type-hole-guards-test'),
94− tool('type-list-alias-test'),
95− tool('type-generic-alias-test'),
96− tool('type-positional-face-guards-test'),
97− tool('type-qath-guards-test'),
98− tool('type-todo-partial-test'),
99− tool('type-todo-api-test'),
100− tool('type-direct-gate-test'),
101− tool('type-page-main-test'),
102− tool('type-buttons-test'),
103− tool('type-doc-examples-test'),
104− tool('type-theme-test'),
105− tool('type-program-main-test'),
106− tool('type-program-init-test'),
107− tool('type-program-update-test'),
108− tool('type-program-watch-test'),
109− tool('type-store-test'),
110− tool('type-generic-recursion-test'),
111− tool('type-generic-construction-test'),
112− tool('type-generic-pattern-test'),
113− tool('type-deferred-test'),
114− tool('type-deferred-resolver-test'),
115− tool('type-deferred-context-test'),
116− tool('type-cell-branch-test'),
117− tool('type-closed-gate-guards-test'),
118− tool('type-constructor-fit-guards-test'),
119− tool('type-nested-union-guards-test'),
120− tool('type-empty-test'),
121− tool('type-gate-free-guards-test'),
122− tool('type-gate-free-source-test'),
123− tool('type-sub-guards-test'),
124− tool('type-ask-guards-test'),
125− tool('type-request-guards-test'),
126− tool('type-proj-guards-test'),
127− tool('type-arithmetic-guards-test'),
128− tool('type-module-scope-test'),
83+ tool('testdata/selftest'), # about 115 s
84+ tool('golden'), # about 60 to 100 s
85+] + [
86+ Check('arms-%d' % i, 'eval', # 55 to 80 s each
87+ ['tools/test-arms', '--shard', '%d/%d' % (i, ARM_SHARDS)])
88+ for i in range(1, ARM_SHARDS + 1)
89+] + [
90+ Check('my-app-copies', 'eval', ['tools/test-arms', '--copies']),
12991 # These print their verdict and exit 0 either way.
13092 hoon('check-spans-test', 'check-spans-test', expect=r'<<>>\n'),
131− hoon('itype-unify-test', 'itype-unify-test', expect=r'<<>>\n'),
13293 hoon('zing-hoon-reference', '-f',
13394 'tools/testdata/zing-hoon-reference.hoon',
13495 expect=r"'Hoon flattening reference: \d+ cases passed'\n"),
@@ -138,7 +99,6 @@ CHECKS = [
13899 hoon('succ-hoon-reference', '-f',
139100 'tools/testdata/succ-hoon-reference.hoon',
140101 expect=r"'Hoon successor reference: \d+ comparisons passed'\n"),
141− tool('testdata/selftest'),
142102 Check('doc-blocks', 'eval', ['tools/doc-blocks', 'docs/spec']),
143103 tool('testdata/clay-fixtures-selftest'),
144104 # The ship group. ship-selftest leaves its fixture files on the
tools/importer-testdeleted−37
@@ -1,37 +0,0 @@
1−#!/usr/bin/env python3
2−"""Compare the Hoon importer's projections with their golden file."""
3−
4−from pathlib import Path
5−import subprocess
6−import sys
7−
8−root = Path(__file__).resolve().parent.parent
9−fixture = root / 'tests' / 'importer'
10−command = [str(root / 'tools' / 'hoon'), '--lib', str(root / 'jibb-dev' / 'lib' / 'jibb-import.hoon'),
11− '--raw', '--cord', 'small=' + str(fixture / 'small.txt'),
12− '--cord', 'epic=' + str(fixture / 'tlon-epic.txt'),
13− '--cord', 'presence=' + str(fixture / 'tlon-presence.txt'),
14− '--cord', 'docs=' + str(fixture / 'tlon-docs.txt'),
15− '--cord', 'shadow=' + str(fixture / 'shadow.txt'),
16− '--cord', 'shadow-static=' + str(fixture / 'shadow-static.txt'),
17− '--cord', 'ford=' + str(fixture / 'ford.txt'),
18− '--cord', 'mark=' + str(fixture / 'mark.txt'),
19− '--cord', 'mark-rec=' + str(fixture / 'mark-recursive.txt'),
20− '--cord', 'mark-gate=' + str(fixture / 'mark-gate.txt'),
21− '--cord', 'mark-basic=' + str(fixture / 'mark-list.txt'),
22− '--cord', 'origin-trans=' + str(fixture / 'origin-transitive.txt'),
23− '--cord', 'origin-first=' + str(fixture / 'origin-first.txt'),
24− '--cord', 'origin-other=' + str(fixture / 'origin-other.txt'),
25− '(fixture-output small epic presence docs shadow shadow-static ford mark mark-rec mark-gate mark-basic origin-trans origin-first origin-other)']
26−result = subprocess.run(command, stdout=subprocess.PIPE)
27−if result.returncode:
28− sys.exit(result.returncode)
29−expected = (fixture / 'tree.txt').read_bytes()
30−if result.stdout != expected:
31− import difflib
32− sys.stderr.writelines(difflib.unified_diff(
33− expected.decode().splitlines(keepends=True),
34− result.stdout.decode().splitlines(keepends=True),
35− fromfile='expected tree.txt', tofile='actual types'))
36− sys.exit(1)
37−print('importer golden: 221 projections passed')
tools/test-armsnew file+568
@@ -0,0 +1,568 @@
1+#!/usr/bin/env python3
2+"""Run the test- arms of tests/lib/*.hoon under urbit eval.
3+
4+ tools/test-arms every suite, in one eval
5+ tools/test-arms jibb-store 'jibb-program-*'
6+ tools/test-arms --shard 2/4 the second of four balanced shards
7+ tools/test-arms --list the suites, their arms and reports
8+ tools/test-arms --report jibb-poke-bridge
9+ tools/test-arms --update jibb-poke-bridge
10+ tools/test-arms --copies only the my-app copy check
11+
12+The ship runs the same arms with -test /=jibb-dev=/tests (tools/ship
13+test). Here each suite gets the subject Ford would give it on the
14+jibb-dev desk: every /+ library and every /* file, found where tools/ship
15+assembles them, on top of zuse. Many suites share one eval, so the
16+library is built once per eval. Each arm runs under mule and prints OK,
17+FAILED or CRASHED, as -test does, with what it returned or the trace it
18+crashed with, placed in the suite and the library. A suite that doesn't
19+build is reported as FAILED (build) after the eval is retried one suite
20+at a time.
21+
22+A suite whose core has a `report` arm and an `expected` /* file is a
23+golden report: --report prints report's text, --update writes it to the
24+expected file, and a failing arm shows the difference.
25+
26+tests/lib/jibb.hoon, which tools/ship generates from tests/golden, is
27+left out: tools/golden runs those cases under eval.
28+
29+Golden files, the /* %txt files bound to a face with "expected" in its
30+name, must end in exactly one newline (a wain can't show it) and hold no
31+line that starts "BAD " or ends ": BAD" (a check's own failure marker).
32+That is checked before any eval, as are, when no suite or shard is named,
33+the files tests/my-app-copies.txt lists, which must match their my-app
34+sources (the jibb-dev desk has no my-app; --copies checks only them).
35+
36+Exit status: 0 when every arm passes, 1 when one fails, 2 on a usage
37+error.
38+"""
39+
40+import argparse
41+import difflib
42+import fnmatch
43+import importlib.machinery
44+import importlib.util
45+import os
46+import re
47+import sys
48+import time
49+
50+sys.dont_write_bytecode = True
51+TOOLS = os.path.dirname(os.path.realpath(__file__))
52+sys.path.insert(0, TOOLS)
53+
54+import urbit_eval as ue # noqa: E402
55+from noun import atom_to_bytes, to_list # noqa: E402
56+
57+ROOT = os.path.dirname(TOOLS)
58+LIB_DIR = os.path.join(ROOT, 'tests', 'lib')
59+COPIES = os.path.join(ROOT, 'tests', 'my-app-copies.txt')
60+GENERATED = 'jibb' # tests/lib/jibb.hoon, from tools/ship gen-tests
61+LIBRARY = 'jibb' # /+ jibb: the library under test, --lib
62+
63+# For balancing shards: about how many seconds each suite's arms take
64+# under eval, debug on, beyond building the libraries (measured
65+# 2026-11-03, one suite at a time, four at once on four CPUs). Each
66+# eval builds jibb.hoon first, about 17 s, and each /+ library the
67+# shard's suites use once, as LIB_COSTS says. A suite not listed counts
68+# as DEFAULT_COST.
69+COSTS = {
70+ 'jibb-deferred-prepared': 32, 'jibb-todo-full': 23, 'jibb-bridge': 20,
71+ 'jibb-api-evidence': 19, 'jibb-api-paths': 18, 'jibb-doc-examples': 17,
72+ 'jibb-program-init': 12, 'jibb-cell-branch': 11,
73+ 'jibb-direct-gate-source': 11, 'jibb-ask-guards': 10,
74+ 'jibb-buttons': 10, 'jibb-deferred-resolver': 10, 'jibb-empty': 10,
75+ 'jibb-import': 10, 'jibb-page-main': 10,
76+ 'jibb-constructor-fit-guards': 9, 'jibb-deferred': 9,
77+ 'jibb-deferred-context': 9, 'jibb-full-overlap-graph': 9,
78+ 'jibb-gate-free-guards': 9, 'jibb-arithmetic-guards': 8,
79+ 'jibb-closed-gate-guards': 8, 'jibb-direct-gate-guards': 8,
80+ 'jibb-full-overlap-basic': 8, 'jibb-program-update': 8,
81+ 'jibb-gate-free-source': 7, 'jibb-store': 6,
82+}
83+DEFAULT_COST = 3
84+LIB_COSTS = {'jibb-import': 20}
85+
86+HEADER = re.compile(r'^(/\+|/\*)\s+(.*)$')
87+STAR = re.compile(r'^(\S+)\s+%(\S+)\s+(/\S+)$')
88+ARM = re.compile(r'^\+\+ (test-[a-z0-9-]+)\s*$', re.M)
89+REPORT = re.compile(r'^\+\+ report\s*$', re.M)
90+
91+
92+class Unusable(Exception):
93+ pass
94+
95+
96+def load_ship():
97+ """tools/ship as a module, for its desk assembly."""
98+ path = os.path.join(TOOLS, 'ship')
99+ loader = importlib.machinery.SourceFileLoader('jibb_ship_tool', path)
100+ spec = importlib.util.spec_from_loader('jibb_ship_tool', loader)
101+ mod = importlib.util.module_from_spec(spec)
102+ loader.exec_module(mod)
103+ return mod
104+
105+
106+class Suite:
107+ """One tests/lib file: its libraries, files, arms and core."""
108+
109+ def __init__(self, path, desk):
110+ self.path = path
111+ self.name = os.path.splitext(os.path.basename(path))[0]
112+ self.rel = ue.display_path(path)
113+ with open(path, encoding='utf-8') as f:
114+ text = f.read()
115+ at = text.find('\n|%\n')
116+ if at < 0:
117+ raise Unusable('%s: no |%% core after its runes' % self.rel)
118+ head = text[:at + 1].split('\n')[:-1]
119+ self.libs, self.files = [], []
120+ for n, line in enumerate(head, 1):
121+ if not line.strip() or line.startswith('::'):
122+ continue
123+ m = HEADER.match(line)
124+ if not m:
125+ raise Unusable('%s:%d: only /+ and /* lines may come before '
126+ 'the core, not %s' % (self.rel, n, line))
127+ if m.group(1) == '/+':
128+ for lib in (l.strip() for l in m.group(2).split(',')):
129+ self.libs.append(lib)
130+ continue
131+ s = STAR.match(m.group(2).strip())
132+ if not s:
133+ raise Unusable('%s:%d: a /* line is FACE %%MARK /PATH, not %s'
134+ % (self.rel, n, m.group(2)))
135+ face, mark, clay = s.groups()
136+ if mark not in ('txt', 'jibb'):
137+ raise Unusable('%s:%d: only %%txt and %%jibb files can be '
138+ 'bound here, not %%%s' % (self.rel, n, mark))
139+ self.files.append((face, mark, desk_file(desk, clay, self.rel, n)))
140+ # The header lines become comments, so the core keeps its line
141+ # numbers in error reports.
142+ self.core = '\n'.join('::' + l[2:] if l.startswith(('/+', '/*'))
143+ else l for l in head) + text[at:]
144+ self.arms = ARM.findall(text[at:])
145+ self.reports = bool(REPORT.search(text[at:]))
146+ self.expected = next((p for f, _, p in self.files if f == 'expected'),
147+ None)
148+
149+ def cost(self):
150+ return COSTS.get(self.name, DEFAULT_COST)
151+
152+
153+def desk_file(desk, clay, rel, n):
154+ """The repo file a /* path names on the assembled jibb-dev desk."""
155+ parts = clay.strip('/').split('/')
156+ if len(parts) < 2:
157+ raise Unusable('%s:%d: %s has no file extension' % (rel, n, clay))
158+ desk_rel = os.path.join(*parts[:-1]) + '.' + parts[-1]
159+ entry = desk.files.get(desk_rel)
160+ if entry is None:
161+ raise Unusable('%s:%d: %s is not on the jibb-dev desk'
162+ % (rel, n, clay))
163+ path = os.path.join(ROOT, entry[1])
164+ if not os.path.isfile(path):
165+ raise Unusable('%s:%d: %s is generated, not a repo file'
166+ % (rel, n, clay))
167+ return path
168+
169+
170+def lib_source(desk, name):
171+ """A /+ library's file, as Ford finds it: /lib/a-b.hoon, /lib/a/b.hoon."""
172+ for rel in (os.path.join('lib', name + '.hoon'),
173+ os.path.join('lib', *name.split('-')) + '.hoon'):
174+ entry = desk.files.get(rel)
175+ if entry is not None:
176+ return os.path.join(ROOT, entry[1])
177+ raise Unusable('no /lib/%s.hoon on the jibb-dev desk' % name)
178+
179+
180+# ---------------------------------------------------------------- copies
181+
182+
183+def check_copies():
184+ """The tests/ files that copy my-app sources must match them."""
185+ problems, pairs = [], 0
186+ with open(COPIES, encoding='utf-8') as f:
187+ lines = f.read().split('\n')
188+ for n, line in enumerate(lines, 1):
189+ if not line.strip() or line.startswith('#'):
190+ continue
191+ words = line.split(None, 2)
192+ without = None
193+ if len(words) == 3:
194+ if not words[2].startswith('without '):
195+ words = []
196+ else:
197+ without = words[2][len('without '):].encode() + b'\n'
198+ if len(words) < 2:
199+ problems.append('tests/my-app-copies.txt:%d: COPY SOURCE '
200+ '[without LINE], not %s' % (n, line))
201+ continue
202+ copy, source = words[0], words[1]
203+ try:
204+ with open(os.path.join(ROOT, copy), 'rb') as f:
205+ got = f.read()
206+ with open(os.path.join(ROOT, source), 'rb') as f:
207+ want = f.read()
208+ except OSError as e:
209+ problems.append('tests/my-app-copies.txt:%d: %s' % (n, e))
210+ continue
211+ if without is not None:
212+ if without not in want:
213+ problems.append('tests/my-app-copies.txt:%d: %s has no line %s'
214+ % (n, source, without.decode().rstrip()))
215+ continue
216+ want = want.replace(without, b'', 1)
217+ pairs += 1
218+ if got != want:
219+ problems.append('%s differs from %s%s' % (
220+ copy, source, '' if without is None else
221+ ' without %s' % without.decode().rstrip()))
222+ return pairs, problems
223+
224+
225+def golden_problems(text):
226+ """What is wrong with a golden file's or report's bytes, or None."""
227+ if not text.endswith(b'\n') or text.endswith(b'\n\n'):
228+ return 'does not end in exactly one newline'
229+ for line in text.split(b'\n'):
230+ if line.startswith(b'BAD ') or line.endswith(b': BAD'):
231+ return 'holds a BAD line: %s' % line.decode('utf-8', 'replace')
232+ return None
233+
234+
235+def check_goldens(suites):
236+ problems = []
237+ for suite in suites:
238+ for face, mark, path in suite.files:
239+ if mark != 'txt' or 'expected' not in face:
240+ continue
241+ with open(path, 'rb') as f:
242+ problem = golden_problems(f.read())
243+ if problem:
244+ problems.append('%s (%s in %s) %s' % (
245+ ue.display_path(path), face, suite.name, problem))
246+ return problems
247+
248+
249+# ---------------------------------------------------------------- program
250+
251+
252+def suite_expression(i, suite, binds):
253+ """A wain of OK/FAILED/CRASHED lines for one suite's arms, or, with
254+ binds=report, the text of its report arm."""
255+ pins = []
256+ for lib in suite.libs:
257+ pins.append('%s=%s' % (lib, 'jibb-lib' if lib == LIBRARY
258+ else 'lib-' + lib))
259+ for face, mark, _ in suite.files:
260+ cord = 's%d-%s' % (i, face)
261+ pins.append('%s=`@t`%s' % (face, cord) if mark == 'jibb'
262+ else '%s=(to-wain:format %s)' % (face, cord))
263+ subject = (':* ' + '\n '.join(pins + ['arms-show=arms-show', '..zuse'])
264+ + '\n==\n')
265+ show = '(arms-show p.r)'
266+ if binds == 'report':
267+ tail = '^- wain\n~[`@t`report:suite]\n'
268+ else:
269+ checks = []
270+ for arm in suite.arms:
271+ label = '%s %s' % (suite.name, arm)
272+ checks.append(
273+ ' =/ r (mule |.(`tang`%s:suite))\n'
274+ ' ^- wain\n'
275+ ' ?: ?=(%%| -.r) [\'CRASHED %s\' %s]\n'
276+ ' ?~ p.r ~[\'OK %s\']\n'
277+ ' [\'FAILED %s\' %s]\n' % (arm, label, show, label,
278+ label, show))
279+ tail = ('^- wain\n%- zing\n^- (list wain)\n:~\n'
280+ + ' ::\n'.join(checks) + '==\n')
281+ return ('=> ' + subject + '=/ suite\n', tail)
282+
283+
284+def program_for(suites, lib, debug, mode='arms'):
285+ """One eval program for several suites, and the files it binds."""
286+ prog = ue.library_program(lib, debug=debug)
287+ prog.add('=/ jibb-lib .\n'
288+ '=/ arms-show\n'
289+ ' |= t=tang\n'
290+ ' ^- wain\n'
291+ ' =| out=wain\n'
292+ ' |- ^- wain\n'
293+ ' ?~ t (flop out)\n'
294+ ' =/ w=wall (wash [2 100] i.t)\n'
295+ ' |- ^- wain\n'
296+ ' ?~ w ^$(t t.t)\n'
297+ ' $(w t.w, out [(crip i.w) out])',
298+ '(test-arms)', 'harness')
299+ libs = sorted({l for s in suites for l in s.libs if l != LIBRARY})
300+ for name, path in ((l, lib_source(DESK, l)) for l in libs):
301+ # Compiled on zuse, as Ford compiles a /+ library.
302+ prog.add('=/ lib-%s\n=> ..zuse' % name, '(test-arms)', 'harness')
303+ prog.add(ue.read_text(path), ue.display_path(path), 'expr')
304+ for i, suite in enumerate(suites):
305+ for face, mark, path in suite.files:
306+ with open(path, 'rb') as f:
307+ data = f.read()
308+ pieces = [p for p in ue.cord_pieces(data) if p]
309+ value = ("''" if not pieces else '(rap 3 `(list @t)`~[%s])'
310+ % ' '.join(ue.cord_literal(p) for p in pieces))
311+ prog.add('=/ s%d-%s=@t %s' % (i, face, value),
312+ '(%s %s)' % (suite.rel, face), 'harness')
313+ if mode == 'report':
314+ suite = suites[0]
315+ head, tail = suite_expression(0, suite, 'report')
316+ prog.add(head, '(test-arms)', 'harness')
317+ prog.add(suite.core, suite.rel, 'expr')
318+ prog.add(tail, '(test-arms)', 'harness')
319+ return prog
320+ prog.add('^- wain\n%- zing\n^- (list wain)\n:~', '(test-arms)',
321+ 'harness')
322+ for i, suite in enumerate(suites):
323+ head, tail = suite_expression(i, suite, 'arms')
324+ prog.add(' :: ' + suite.rel + '\n' + head, '(test-arms)', 'harness')
325+ prog.add(suite.core, suite.rel, 'expr')
326+ prog.add(tail, '(test-arms)', 'harness')
327+ prog.add('==', '(test-arms)', 'harness')
328+ return prog
329+
330+
331+def wain_of(res):
332+ return [atom_to_bytes(l).decode('utf-8', 'replace')
333+ for l in to_list(res.noun)]
334+
335+
336+def placed(prog, lines):
337+ """The lines, with each CRASHED arm's trace placed in the suites and
338+ the library, as eval places its own, and an excerpt of the innermost
339+ spot in them."""
340+ out, i = [], 0
341+ while i < len(lines):
342+ out.append(lines[i])
343+ crashed = lines[i].startswith('CRASHED ')
344+ i += 1
345+ block = []
346+ while i < len(lines) and lines[i].startswith(' '):
347+ block.append(lines[i])
348+ i += 1
349+ if not crashed:
350+ out += block
351+ continue
352+ mapped, spots = ue.map_trace(prog, block, keep=('lib', 'expr'))
353+ out += ue.fold_repeats(mapped)
354+ # mule's trace, unlike eval's, starts at the innermost spot.
355+ at = next((sp for sp in spots if sp.kind in ('lib', 'expr')), None)
356+ if at is not None:
357+ out.append(' at %s' % at.label())
358+ ex = at.excerpt(indent=' ')
359+ if ex:
360+ out += ex.split('\n')
361+ return out
362+
363+
364+def run(suites, lib, debug, timeout):
365+ """Run suites in one eval; on a build failure, one suite at a time."""
366+ prog = program_for(suites, lib, debug)
367+ res = ue.run_eval(prog, jam=True, timeout=timeout)
368+ if res.ok:
369+ return placed(prog, wain_of(res))
370+ if res.timed_out:
371+ return (['FAILED %s (timeout)' % s.name for s in suites]
372+ + [' the eval ran past %gs; run the suites one at a time '
373+ 'to find the slow one' % timeout])
374+ if len(suites) > 1:
375+ out = []
376+ for suite in suites:
377+ out += run([suite], lib, debug, timeout)
378+ return out
379+ suite = suites[0]
380+ what = ("doesn't build" if res.is_compile_error() else
381+ 'crashed: %s' % res.describe())
382+ # The harness's own frames only wrap the suite's.
383+ report = ue.failure_report(prog, res, '%s %s' % (suite.rel, what),
384+ keep=('lib', 'expr'))
385+ return (['FAILED %s (build)' % suite.name]
386+ + [' ' + l for l in report.split('\n')])
387+
388+
389+def report_text(suite, lib, debug, timeout):
390+ prog = program_for([suite], lib, debug, mode='report')
391+ res = ue.run_eval(prog, jam=True, timeout=timeout)
392+ if not res.ok:
393+ raise Unusable(ue.failure_report(
394+ prog, res, '%s: its report arm failed' % suite.rel))
395+ return '\n'.join(wain_of(res)) + '\n'
396+
397+
398+# ---------------------------------------------------------------- shards
399+
400+
401+def shard(suites, index, count):
402+ """The index-th of count shards, balanced by COSTS and LIB_COSTS
403+ (largest first, each to the shard it makes least loaded), so the same
404+ suites always go together."""
405+ loads = [[0, [], set()] for _ in range(count)]
406+
407+ def added(load, suite):
408+ return suite.cost() + sum(LIB_COSTS.get(l, 0) for l in suite.libs
409+ if l not in load[2])
410+
411+ for suite in sorted(suites, key=lambda s: (-s.cost(), s.name)):
412+ best = min(loads, key=lambda l: l[0] + added(l, suite))
413+ best[0] += added(best, suite)
414+ best[1].append(suite)
415+ best[2].update(suite.libs)
416+ return sorted(loads[index - 1][1], key=lambda s: s.name)
417+
418+
419+def select(folder, names):
420+ every = sorted(os.path.splitext(f)[0] for f in os.listdir(folder)
421+ if f.endswith('.hoon')
422+ and os.path.splitext(f)[0] != GENERATED)
423+ if not names:
424+ return every
425+ picked = []
426+ for pattern in names:
427+ pattern = os.path.splitext(os.path.basename(pattern))[0]
428+ hits = fnmatch.filter(every, pattern)
429+ if not hits:
430+ raise Unusable('no suite in %s matches %s'
431+ % (ue.display_path(folder), pattern))
432+ picked += [h for h in hits if h not in picked]
433+ return picked
434+
435+
436+def main(argv):
437+ ap = argparse.ArgumentParser(
438+ prog='tools/test-arms',
439+ formatter_class=argparse.RawDescriptionHelpFormatter,
440+ description=__doc__.split('\n\n')[0])
441+ ap.add_argument('suites', nargs='*', metavar='SUITE',
442+ help='tests/lib suites by name or glob (default: all)')
443+ ap.add_argument('--shard', metavar='I/N',
444+ help='run only the I-th of N balanced shards')
445+ ap.add_argument('--dir', default=LIB_DIR, metavar='DIR',
446+ help='the folder of suites (default: tests/lib)')
447+ ap.add_argument('--lib', default=ue.DEFAULT_LIB, metavar='PATH',
448+ help='the library (default: jibb-dev/lib/jibb.hoon)')
449+ ap.add_argument('--timeout', type=float, default=1800, metavar='SECONDS',
450+ help='how long one eval may run (default: 1800)')
451+ ap.add_argument('--no-debug', dest='debug', action='store_false',
452+ help="leave out !:, for timings; errors lose positions")
453+ ap.add_argument('--list', action='store_true',
454+ help='print the suites that would run, and their arms')
455+ mode = ap.add_mutually_exclusive_group()
456+ mode.add_argument('--report', action='store_true',
457+ help="print one suite's report arm")
458+ mode.add_argument('--update', action='store_true',
459+ help="write suites' report arms to their expected "
460+ "files")
461+ mode.add_argument('--copies', action='store_true',
462+ help='only check tests/my-app-copies.txt')
463+ opts = ap.parse_args(argv)
464+
465+ if opts.copies or not (opts.suites or opts.shard or opts.list
466+ or opts.report or opts.update
467+ or os.path.realpath(opts.dir) != LIB_DIR):
468+ pairs, problems = check_copies()
469+ for p in problems:
470+ print('FAILED my-app copy: %s' % p)
471+ if opts.copies:
472+ if not problems:
473+ print('%d my-app copies match their sources' % pairs)
474+ return 1 if problems else 0
475+ if problems:
476+ return 1
477+
478+ global DESK
479+ try:
480+ if not os.path.isfile(opts.lib):
481+ raise Unusable('no library at %s' % ue.display_path(opts.lib))
482+ ship = load_ship()
483+ try:
484+ DESK = ship.assemble('jibb-dev')
485+ except ship.Unable as e:
486+ raise Unusable(str(e))
487+ if not os.path.isdir(opts.dir):
488+ raise Unusable('no folder %s' % ue.display_path(opts.dir))
489+ suites = [Suite(os.path.join(opts.dir, n + '.hoon'), DESK)
490+ for n in select(opts.dir, opts.suites)]
491+ if opts.shard:
492+ m = re.fullmatch(r'(\d+)/(\d+)', opts.shard)
493+ if not m or not 1 <= int(m.group(1)) <= int(m.group(2)):
494+ raise Unusable('--shard takes I/N with 1 <= I <= N')
495+ suites = shard(suites, int(m.group(1)), int(m.group(2)))
496+ if opts.list:
497+ for s in suites:
498+ print('%s (%ds)%s: %s' % (s.name, s.cost(),
499+ ', report' if s.reports else '',
500+ ' '.join(s.arms) or 'no arms'))
501+ return 0
502+ if opts.report or opts.update:
503+ golden = [s for s in suites if s.reports and s.expected]
504+ if opts.report and len(suites) != 1:
505+ raise Unusable('--report takes one suite')
506+ if not golden:
507+ raise Unusable('no report arm with an expected file in %s'
508+ % ', '.join(s.name for s in suites))
509+ for s in golden:
510+ text = report_text(s, opts.lib, opts.debug, opts.timeout)
511+ if opts.report:
512+ sys.stdout.write(text)
513+ continue
514+ problem = golden_problems(text.encode('utf-8'))
515+ if problem:
516+ raise Unusable('%s: not updated, its report %s'
517+ % (ue.display_path(s.expected), problem))
518+ with open(s.expected, 'w', encoding='utf-8') as f:
519+ f.write(text)
520+ print('updated %s' % ue.display_path(s.expected))
521+ return 0
522+ if not suites:
523+ print('no suites in this shard')
524+ return 0
525+ problems = check_goldens(suites)
526+ if problems:
527+ for p in problems:
528+ print('FAILED golden file: %s' % p)
529+ return 1
530+ start = time.time()
531+ lines = run(suites, opts.lib, opts.debug, opts.timeout)
532+ except (Unusable, ue.ToolError) as e:
533+ print('test-arms: %s' % e, file=sys.stderr)
534+ return 2
535+
536+ failed = []
537+ for line in lines:
538+ print(line)
539+ if line.startswith(('FAILED ', 'CRASHED ')):
540+ failed.append(line.split()[1])
541+ for s in suites:
542+ if s.name in failed and s.reports and s.expected:
543+ show_difference(s, opts)
544+ arms = sum(1 for l in lines if l.startswith(('OK ', 'FAILED ',
545+ 'CRASHED ')))
546+ print('%d suites, %d arms: %s in %.0f s' % (
547+ len(suites), arms,
548+ 'all passed' if not failed else '%d failed' % len(failed),
549+ time.time() - start))
550+ return 1 if failed else 0
551+
552+
553+def show_difference(suite, opts):
554+ try:
555+ text = report_text(suite, opts.lib, opts.debug, opts.timeout)
556+ except Unusable:
557+ return
558+ with open(suite.expected, encoding='utf-8') as f:
559+ want = f.read()
560+ sys.stdout.writelines(difflib.unified_diff(
561+ want.splitlines(keepends=True), text.splitlines(keepends=True),
562+ fromfile=ue.display_path(suite.expected), tofile='report'))
563+
564+
565+DESK = None
566+
567+if __name__ == '__main__':
568+ sys.exit(main(sys.argv[1:]))
tools/testdata/selftest+106−3
@@ -1,8 +1,9 @@
11#!/usr/bin/env python3
2−"""Test tools/golden and tools/hoon against tools/testdata/stub.hoon,
3−and tools/doc-blocks against Markdown it writes.
2+"""Test tools/golden, tools/hoon and tools/test-arms against
3+tools/testdata/stub.hoon, and tools/doc-blocks against Markdown it
4+writes.
45
5− tools/testdata/selftest all checks, about half a minute
6+ tools/testdata/selftest all checks, about two minutes
67 tools/testdata/selftest -k crash only checks whose name has "crash"
78
89The cases in tools/testdata/golden pass with the stub. Each check that
@@ -25,6 +26,7 @@ ROOT = os.path.dirname(TOOLS)
2526GOLDEN = os.path.join(TOOLS, 'golden')
2627HOON = os.path.join(TOOLS, 'hoon')
2728DOC_BLOCKS = os.path.join(TOOLS, 'doc-blocks')
29+TEST_ARMS = os.path.join(TOOLS, 'test-arms')
2830STUB =os.path.join(HERE, 'stub.hoon')
2931CASES = os.path.join(HERE, 'golden')
3032
@@ -621,6 +623,107 @@ def check_doc_blocks(c, tmp):
621623 'no labelled block: %d\n%s' % (status, out))
622624
623625
626+ARM_SUITES = {
627+ 'pass': """:: one arm that passes
628+/+ jibb
629+|%
630+++ test-tree
631+ ^- tang
632+ ?: =('hello' tree:(golden:jibb /a/jibb 'hello')) ~
633+ ~[leaf+"wrong tree"]
634+--
635+""",
636+ 'fail': """/+ jibb
637+|%
638+++ test-wrong
639+ ^- tang
640+ ~[leaf+"first problem" leaf+"second problem"]
641+++ test-right
642+ ^- tang
643+ ~
644+--
645+""",
646+ 'crash': """/+ jibb
647+|%
648+++ test-crash
649+ ^- tang
650+ ?: =('' tree:(golden:jibb /a/jibb 'crash')) ~
651+ ~
652+--
653+""",
654+ 'nobuild': """/+ jibb
655+|%
656+++ test-nothing
657+ ^- tang
658+ no-such-face
659+--
660+""",
661+}
662+
663+
664+def test_arms(*args):
665+ return run(TEST_ARMS, '--lib', STUB, *args)
666+
667+
668+def check_test_arms(c, tmp):
669+ lib = os.path.join(tmp, 'lib')
670+ os.makedirs(lib)
671+ for name, text in ARM_SUITES.items():
672+ with open(os.path.join(lib, name + '.hoon'), 'w') as f:
673+ f.write(text)
674+ status, out = test_arms('--dir', lib)
675+ c.expect(status == 1, 'exit status %d, not 1:\n%s' % (status, out))
676+ for line in ('OK pass test-tree', 'FAILED fail test-wrong',
677+ ' first problem', ' second problem', 'OK fail test-right',
678+ 'CRASHED crash test-crash', 'FAILED nobuild (build)'):
679+ c.expect(re.search('^%s$' % re.escape(line), out, re.M),
680+ 'no line %r:\n%s' % (line, out))
681+ c.expect('[%stub-crash /a/jibb]' in out,
682+ "the crash's ~| trace is missing:\n" + out)
683+ c.expect('(test-arms)' not in out,
684+ "the runner's own frames should be dropped:\n" + out)
685+ line = stub_line('?> =(1 2)')
686+ c.expect('tools/testdata/stub.hoon:%d:3' % line in out and
687+ re.search(r'crash\.hoon:5:', out) and '/:<[' not in out and
688+ 'at tools/testdata/stub.hoon:%d:3' % line in out,
689+ "the crash's trace should be placed in the stub and the suite:\n"
690+ + out)
691+ c.expect(re.search(r'nobuild\.hoon:5:', out),
692+ 'the build error should point at nobuild.hoon line 5:\n' + out)
693+ c.expect('4 suites, 5 arms: 3 failed' in out, 'no summary line:\n' + out)
694+ status, out = test_arms('--dir', lib, 'pass', 'f*')
695+ c.expect(status == 1 and 'OK pass test-tree' in out and
696+ 'crash' not in out and '2 suites, 3 arms: 1 failed' in out,
697+ 'suites by name and glob: %d\n%s' % (status, out))
698+ status, out = test_arms('--dir', lib, 'pass')
699+ c.expect(status == 0 and '1 suites, 1 arms: all passed' in out,
700+ 'a passing suite: %d\n%s' % (status, out))
701+ shards = []
702+ for i in (1, 2):
703+ status, out = test_arms('--dir', lib, '--list', '--shard', '%d/2' % i)
704+ c.expect(status == 0, 'list shard %d: %d\n%s' % (i, status, out))
705+ shards.append(set(re.findall(r'^(\w+) \(', out, re.M)))
706+ c.expect(shards[0] | shards[1] == set(ARM_SUITES) and
707+ not shards[0] & shards[1] and all(shards),
708+ 'the shards should split the suites: %r' % shards)
709+ status, out = test_arms('--dir', lib, '--report', 'pass')
710+ c.expect(status == 2 and 'no report arm' in out,
711+ 'a suite without a report: %d\n%s' % (status, out))
712+ status, out = test_arms('--dir', lib, 'nothing*')
713+ c.expect(status == 2 and 'matches nothing*' in out,
714+ 'a glob that matches nothing: %d\n%s' % (status, out))
715+ with open(os.path.join(lib, 'loop.hoon'), 'w') as f:
716+ f.write(ARM_SUITES['crash'].replace("'crash'", "'loop'"))
717+ status, out = test_arms('--dir', lib, '--timeout', '6', 'loop')
718+ c.expect(status == 1 and 'FAILED loop (timeout)' in out,
719+ 'a suite that never ends: %d\n%s' % (status, out))
720+ with open(os.path.join(lib, 'header.hoon'), 'w') as f:
721+ f.write('/- todo\n' + ARM_SUITES['pass'])
722+ status, out = test_arms('--dir', lib, 'header')
723+ c.expect(status == 2 and 'only /+ and /* lines' in out,
724+ 'a /- line: %d\n%s' % (status, out))
725+
726+
624727CHECKS =[(name[len('check_'):], fn) for name, fn in globals().items()
625728 if name.startswith('check_')]
626729
tools/type-api-evidence-testdeleted−40
@@ -1,40 +0,0 @@
1−#!/usr/bin/env python3
2−"""Check partial path-declaration evidence against synthetic and real todo inputs."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
14−tests = (root / 'tests/lib/jibb-api-evidence.hoon').read_text()
15−tests = tests[tests.index('\n|%\n') + 1:]
16−expression = ('=/ jibb .\n=/ jibb-import\n' + reader + '\n' +
17− ''.join('=/ ' + name + '=wain (to-wain:format ' + name + '-text)\n'
18− for name in ('sur', 'action', 'todos', 'update', 'item', 'api')) +
19− '=/ suite\n' + tests +
20− '\n=/ synthetic=@t synthetic-evidence-status:suite\n' +
21− '=/ actual=@t (real-evidence-status:suite prelude internal sur-text action-text todos-text update-text item-text api-text)\n' +
22− "^- @t\n?: !=(actual 'real todo path evidence passed') actual\nsynthetic\n")
23−fixtures = {'sur': 'todo-sur', 'action': 'todo-action', 'todos': 'todos',
24− 'update': 'todo-update', 'item': 'todo-item', 'api': 'scry'}
25−with tempfile.TemporaryDirectory(prefix='jibb-api-evidence-') as tmp:
26− program = Path(tmp) / 'evidence.hoon'
27− program.write_text(expression)
28− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(program),
29− '--cord', 'prelude=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
30− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
31− for name, filename in fixtures.items():
32− command += ['--cord', name + '-text=' + str(root / 'tests/type-api-paths' / (filename + '.txt'))]
33− result = subprocess.run(command, stdout=subprocess.PIPE)
34−if result.returncode:
35− sys.exit(result.returncode)
36−expected = (root / 'tests/type-api-evidence/expected.txt').read_bytes()
37−if result.stdout != expected:
38− sys.stderr.buffer.write(result.stdout)
39− sys.exit(1)
40−print('partial API path evidence guards passed')
tools/type-api-paths-testdeleted−52
@@ -1,52 +0,0 @@
1−#!/usr/bin/env python3
2−"""Compare partial API path analysis with real Ford-style todo marks under eval."""
3−
4−from pathlib import Path
5−import argparse
6−import difflib
7−import subprocess
8−import sys
9−import tempfile
10−
11−root = Path(__file__).resolve().parent.parent
12−parser = argparse.ArgumentParser(description=__doc__)
13−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
14−parser.add_argument('--update', action='store_true')
15−args = parser.parse_args()
16−fixture = root / 'tests/type-api-paths'
17−names = {'sur': 'todo-sur', 'action': 'todo-action', 'todos': 'todos',
18− 'update': 'todo-update', 'item': 'todo-item', 'api': 'api',
19− 'missing-decl': 'missing-decl', 'value-clash': 'value-clash',
20− 'poke-clash': 'poke-clash', 'scry': 'scry', 'scry-bad': 'scry-bad'}
21−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
22−tests = (root / 'tests/lib/jibb-api-paths.hoon').read_text()
23−tests = tests[tests.index('\n|%\n') + 1:]
24−expression = ('=/ jibb .\n=/ jibb-import\n' + reader + '\n' +
25− ''.join('=/ ' + name + '=wain (to-wain:format ' + name + '-text)\n' for name in names) +
26− '=/ expected=wain ~\n=/ bridge\n' + tests +
27− '\n(of-wain:format (fixture-output:bridge prelude internal ' +
28− ' '.join(name + '-text' for name in names) + '))\n')
29−with tempfile.TemporaryDirectory(prefix='jibb-type-api-paths-') as tmp:
30− program = Path(tmp) / 'bridge.hoon'
31− program.write_text(expression)
32− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(program),
33− '--cord', 'prelude=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
34− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
35− for name, filename in names.items():
36− command += ['--cord', name + '-text=' + str(fixture / (filename + '.txt'))]
37− result = subprocess.run(command, stdout=subprocess.PIPE)
38−if result.returncode:
39− sys.exit(result.returncode)
40−expected_path = fixture / 'expected.txt'
41−if args.update:
42− expected_path.write_bytes(result.stdout)
43− print('updated partial API path analysis golden')
44− sys.exit(0)
45−expected = expected_path.read_bytes()
46−if result.stdout != expected:
47− sys.stderr.writelines(difflib.unified_diff(
48− expected.decode().splitlines(keepends=True),
49− result.stdout.decode().splitlines(keepends=True),
50− fromfile='expected.txt', tofile='actual paths'))
51− sys.exit(1)
52−print('partial API path analysis golden passed')
tools/type-arithmetic-guards-testdeleted−28
@@ -1,28 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared arithmetic unifier guards under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−tests = (root / 'tests/lib/jibb-arithmetic-guards.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ suite\n' + tests +
16− '\n=/ failures=(list tape) arithmetic-guard-errors:suite\n'
17− '^- @t\n?~ failures \'arithmetic guards passed\'\n'
18− '(of-wain:format (turn failures crip))\n')
19−with tempfile.TemporaryDirectory(prefix='jibb-arithmetic-guards-') as tmp:
20− program = Path(tmp) / 'guards.hoon'
21− program.write_text(expression)
22− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(program)], stdout=subprocess.PIPE)
23−if result.returncode:
24− sys.exit(result.returncode)
25−if result.stdout != b'arithmetic guards passed\n':
26− sys.stderr.buffer.write(result.stdout)
27− sys.exit(1)
28−print('arithmetic unifier guards passed')
tools/type-ask-guards-testdeleted−31
@@ -1,31 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the partial ask source-identity and canonical-template guards under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−tests = (root / 'tests/lib/jibb-ask-guards.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ suite\n' + tests +
16− '\n=/ failures=(list tape) ask-guard-errors:suite\n^- @t\n' +
17− "?~ failures 'ask guards passed'\n" +
18− '(of-wain:format (turn failures crip))\n')
19−with tempfile.TemporaryDirectory(prefix='jibb-ask-guards-') as tmp:
20− program = Path(tmp) / 'guards.hoon'
21− program.write_text(expression)
22− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib, '--raw',
23− '--cord', 'public=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
24− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb'),
25− '-f', str(program)], stdout=subprocess.PIPE)
26−if result.returncode:
27− sys.exit(result.returncode)
28−if result.stdout != b'ask guards passed\n':
29− sys.stderr.buffer.write(result.stdout)
30− sys.exit(1)
31−print('ask source and canonical-template guards passed')
tools/type-buttons-testdeleted−40
@@ -1,40 +0,0 @@
1−#!/usr/bin/env python3
2−"""Check the documented buttons definitions and unresolved-tag error."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−parser.add_argument('--timeout', type=float, default=300,
13− help='seconds allowed for urbit eval (default: 300)')
14−args = parser.parse_args()
15−tests = (root / 'tests/lib/jibb-buttons.hoon').read_text()
16−tests = tests[tests.index('\n|%\n') + 1:]
17−tests = tests[:tests.index('\n++ test-buttons')] + '\n--\n'
18−program = ('=/ jibb .\n=/ expected=wain (to-wain:format expected-text)\n'
19− '=/ error=wain (to-wain:format error-text)\n=/ suite\n' + tests +
20− '\n=/ failures=(list tape) (buttons-errors:suite prelude internal source valid)\n'
21− '^- @t\n?~ failures \'documented buttons passed\'\n'
22− '(of-wain:format (turn failures crip))\n')
23−with tempfile.TemporaryDirectory(prefix='jibb-buttons-') as tmp:
24− path = Path(tmp) / 'buttons.hoon'
25− path.write_text(program)
26− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(path),
27− '--timeout', str(args.timeout),
28− '--cord', 'prelude=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
29− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb'),
30− '--cord', 'source=' + str(root / 'tests/golden/doc-grammar-02-buttons/source.jibb'),
31− '--cord', 'valid=' + str(root / 'tests/type-buttons/valid.txt'),
32− '--cord', 'expected-text=' + str(root / 'tests/type-buttons/expected.txt'),
33− '--cord', 'error-text=' + str(root / 'tests/type-buttons/error.txt')]
34− result = subprocess.run(command, stdout=subprocess.PIPE)
35−if result.returncode:
36− sys.exit(result.returncode)
37−if result.stdout != b'documented buttons passed\n':
38− sys.stderr.buffer.write(result.stdout)
39− sys.exit(1)
40−print('documented buttons detailed/legacy types and exact unresolved-tag diagnostic passed')
tools/type-cell-branch-testdeleted−43
@@ -1,43 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared closed-cell branch guard, including its ship test arm."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−p = argparse.ArgumentParser(description=__doc__)
11−p.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−a = p.parse_args()
13−core = (root / 'tests/lib/jibb-cell-branch.hoon').read_text()
14−core = core[core.index('\n|%\n') + 1:]
15−program = ('=/ jibb .\n'
16− '=/ public=@t public-text\n'
17− '=/ internal=@t internal-text\n'
18− '=/ good=wain (to-wain:format good-text)\n'
19− '=/ bad=wain (to-wain:format bad-text)\n'
20− '=/ suite\n' + core +
21− '\n^- @t\n=/ checked=tang test-cell-branch:suite\n'
22− '?~ checked \'cell branch guards passed\'\n(crip "{<checked>}")\n')
23−fixtures = {
24− 'public': root / 'jibb-dev/lib/jibb/prelude.jibb',
25− 'internal': root / 'jibb-dev/lib/jibb/internal.jibb',
26− 'good': root / 'tests/type-cell-branch/good.txt',
27− 'bad': root / 'tests/type-cell-branch/bad.txt',
28−}
29−with tempfile.TemporaryDirectory(prefix='jibb-cell-branch-') as d:
30− path = Path(d) / 'guard.hoon'
31− path.write_text(program)
32− command = [str(root / 'tools/hoon'), '--lib', a.lib, '--raw', '-f', str(path)]
33− for name, fixture in fixtures.items():
34− if not fixture.is_file() or fixture.stat().st_size == 0:
35− sys.exit('missing or empty fixture: ' + str(fixture))
36− command.extend(['--cord', name + '-text=' + str(fixture)])
37− result = subprocess.run(command, stdout=subprocess.PIPE)
38−if result.returncode:
39− sys.exit(result.returncode)
40−if result.stdout != b'cell branch guards passed\n':
41− sys.stderr.write(result.stdout.decode(errors='replace'))
42− sys.exit(1)
43−print('cell branch guards passed')
tools/type-closed-gate-guards-testdeleted−29
@@ -1,29 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared closed gate fit guards under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−tests = (root / 'tests/lib/jibb-closed-gate-guards.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ suite\n' + tests +
16− '\n=/ failures=(list tape) closed-gate-guard-errors:suite\n^- @t\n' +
17− "?~ failures 'closed gate guards passed'\n" +
18− '(of-wain:format (turn failures crip))\n')
19−with tempfile.TemporaryDirectory(prefix='jibb-positional-guards-') as tmp:
20− program = Path(tmp) / 'guards.hoon'
21− program.write_text(expression)
22− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib,
23− '--raw', '-f', str(program)], stdout=subprocess.PIPE)
24−if result.returncode:
25− sys.exit(result.returncode)
26−if result.stdout != b'closed gate guards passed\n':
27− sys.stderr.buffer.write(result.stdout)
28− sys.exit(1)
29−print('closed gate fit guards passed')
tools/type-constructor-fit-guards-testdeleted−29
@@ -1,29 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared constructor-fit source/typing guards under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−tests = (root / 'tests/lib/jibb-constructor-fit-guards.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ suite\n' + tests +
16− '\n=/ failures=(list tape) constructor-fit-guard-errors:suite\n^- @t\n' +
17− "?~ failures 'constructor-fit guards passed'\n" +
18− '(of-wain:format (turn failures crip))\n')
19−with tempfile.TemporaryDirectory(prefix='jibb-positional-guards-') as tmp:
20− program = Path(tmp) / 'guards.hoon'
21− program.write_text(expression)
22− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib,
23− '--raw', '-f', str(program)], stdout=subprocess.PIPE)
24−if result.returncode:
25− sys.exit(result.returncode)
26−if result.stdout != b'constructor-fit guards passed\n':
27− sys.stderr.buffer.write(result.stdout)
28− sys.exit(1)
29−print('constructor-fit source/typing guards passed')
tools/type-deferred-context-testdeleted−31
@@ -1,31 +0,0 @@
1−#!/usr/bin/env python3
2−"""Evaluate source-driven deferred context and replay guards."""
3−from pathlib import Path
4−import argparse, subprocess, sys, tempfile
5−root = Path(__file__).resolve().parent.parent
6−p = argparse.ArgumentParser(description=__doc__)
7−p.add_argument('--lib', default=str(root/'jibb-dev/lib/jibb.hoon'))
8−p.add_argument('--hoon', default=str(root/'tools/hoon'))
9−a = p.parse_args()
10−core = (root / 'tests/lib/jibb-deferred-context.hoon').read_text()
11−core = core[core.index('\n|%\n') + 1:]
12−names = ['rich', 'plain', 'simple', 'missing', 'wrong', 'duplicate', 'dangling', 'collision-early', 'collision-late', 'report']
13−bindings = ''.join('=/ '+('expected' if n == 'report' else n)+'=wain (to-wain:format '+n+'-text)\n' for n in names)
14−program = ('=/ jibb .\n' + bindings + '=/ suite\n' + core +
15− "\n^- @t\n=/ checked=tang test-context:suite\n?~ checked 'deferred context guards passed'\n(crip \"{<checked>}\")\n")
16−with tempfile.TemporaryDirectory(prefix='jibb-deferred-context-') as d:
17− f = Path(d) / 'report.hoon'
18− f.write_text(program)
19− cmd = [a.hoon, '--lib', a.lib, '--raw', '-f', str(f)]
20− for n in names:
21− fixture = root/'tests/type-deferred-context'/(n+'.txt')
22− if not fixture.is_file() or fixture.stat().st_size == 0:
23− sys.exit('missing or empty fixture: '+str(fixture))
24− cmd.extend(['--cord', n+'-text='+str(fixture)])
25− got = subprocess.run(cmd, stdout=subprocess.PIPE)
26−if got.returncode:
27− sys.exit(got.returncode)
28−if got.stdout != b'deferred context guards passed\n':
29− sys.stderr.write(got.stdout.decode(errors='replace'))
30− sys.exit(1)
31−print('deferred context guards passed')
tools/type-deferred-prepared-testdeleted−49
@@ -1,49 +0,0 @@
1−#!/usr/bin/env python3
2−"""Evaluate prepared-prelude initializer recovery and report guards."""
3−from pathlib import Path
4−import argparse, subprocess, sys, tempfile
5−root = Path(__file__).resolve().parent.parent
6−p = argparse.ArgumentParser(description=__doc__)
7−p.add_argument('--lib', default=str(root/'jibb-dev/lib/jibb.hoon'))
8−p.add_argument('--hoon', default=str(root/'tools/hoon'))
9−a = p.parse_args()
10−core = (root / 'tests/lib/jibb-deferred-prepared.hoon').read_text()
11−core = core[core.index('\n|%\n') + 1:]
12−names = ['good', 'tuple-only', 'wrong-unit', 'wrong-draft', 'unrelated-tag', 'mold-collision',
13− 'no-final-cast', 'no-prelude', 'main', 'imported', 'expected', 'expected-control',
14− 'expected-tuple-only']
15−bindings = ''.join('=/ '+('main-source' if n == 'main' else n)+'=wain (to-wain:format '+n+'-text)\n' for n in names)
16−at = '/ui/prepared/jibb'
17−checks = ['(check-prepared:suite %s %s %s)' % (where, source, valid)
18− for where, source, valid in (
19− (at, 'good', '&'), (at, 'tuple-only', '&'), (at, 'no-prelude', '&'),
20− (at, 'wrong-unit', '|'), (at, 'wrong-draft', '|'),
21− (at, 'unrelated-tag', '|'), (at, 'mold-collision', '|'),
22− (at, 'no-final-cast', '|'), (at, 'main-source', '|'),
23− (at, 'imported', '|'),
24− ('/ui/api/prepared/jibb', 'good', '|'),
25− ('/ui/stores/prepared/jibb', 'good', '|'))]
26−checks += ['check-no-prelude:suite', 'check-ordinary:suite', 'check-prepared-binding:suite',
27− '(check-report:suite good expected)', '(check-report:suite tuple-only expected-tuple-only)',
28− '(check-report:suite no-final-cast expected-control)']
29−with tempfile.TemporaryDirectory(prefix='jibb-deferred-prepared-') as d:
30− f = Path(d) / 'report.hoon'
31− for check in checks:
32− program = ('=/ jibb .\n' + bindings + '=/ suite\n' + core +
33− "\n^- @t\n=/ checked=tang " + check + "\n?~ checked 'prepared deferred inference guards passed'\n(crip \"{<checked>}\")\n")
34− f.write_text(program)
35− cmd = [a.hoon, '--lib', a.lib, '--raw', '-f', str(f),
36− '--cord', 'prelude='+str(root/'jibb-dev/lib/jibb/prelude.jibb'),
37− '--cord', 'internal='+str(root/'jibb-dev/lib/jibb/internal.jibb')]
38− for n in names:
39− fixture = root/'tests/type-deferred-prepared'/(n+'.txt')
40− if not fixture.is_file() or fixture.stat().st_size == 0:
41− sys.exit('missing or empty fixture: '+str(fixture))
42− cmd.extend(['--cord', n+'-text='+str(fixture)])
43− got = subprocess.run(cmd, stdout=subprocess.PIPE)
44− if got.returncode:
45− sys.exit(got.returncode)
46− if got.stdout != b'prepared deferred inference guards passed\n':
47− sys.stderr.write(got.stdout.decode(errors='replace'))
48− sys.exit(1)
49−print('prepared deferred inference guards passed')
tools/type-deferred-resolver-testdeleted−33
@@ -1,33 +0,0 @@
1−#!/usr/bin/env python3
2−"""Evaluate the source-level deferred-resolver report."""
3−from pathlib import Path
4−import argparse, subprocess, sys, tempfile
5−root = Path(__file__).resolve().parent.parent
6−p = argparse.ArgumentParser(description=__doc__)
7−p.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
8−a = p.parse_args()
9−core = (root / 'tests/lib/jibb-deferred-resolver.hoon').read_text()
10−core = core[core.index('\n|%\n') + 1:]
11−names = ['good', 'conflict', 'missing', 'hole', 'duplicate', 'face', 'store', 'stability-early', 'stability-late', 'stability-simple-early', 'stability-simple-late', 'stability-output-early', 'stability-output-late', 'stability-slot-early', 'stability-slot-late', 'public', 'internal']
12−bindings = ''.join('=/ '+n+'=wain (to-wain:format '+n+'-text)\n' for n in names if n not in ('public', 'internal'))
13−bindings += ''.join('=/ '+n+'=@t '+n+'-text\n' for n in ('public', 'internal'))
14−program = ('=/ jibb .\n' + bindings + '=/ expected=wain (to-wain:format expected-text)\n=/ suite\n' + core +
15− '\n^- @t\n=/ checked=tang test-deferred-resolver:suite\n?~ checked \'deferred resolver guards passed\'\n(crip "{<checked>}")\n')
16−with tempfile.TemporaryDirectory(prefix='jibb-deferred-') as d:
17− f = Path(d) / 'report.hoon'
18− f.write_text(program)
19− cmd = [str(root/'tools/hoon'), '--lib', a.lib, '--raw', '-f', str(f)]
20− for n in names:
21− fixture = (root/'jibb-dev/lib/jibb'/('prelude.jibb' if n == 'public' else 'internal.jibb')) if n in ('public', 'internal') else root/'tests/type-deferred-resolver'/(n+'.txt')
22− if not fixture.is_file() or fixture.stat().st_size == 0:
23− sys.exit('missing or empty fixture: ' + str(fixture))
24− cmd.extend(['--cord', n+'-text='+str(fixture)])
25− cmd.extend(['--cord', 'expected-text='+str(root/'tests/type-deferred-resolver/expected.txt')])
26− got = subprocess.run(cmd, stdout=subprocess.PIPE)
27−if got.returncode:
28− sys.exit(got.returncode)
29−want = b'deferred resolver guards passed\n'
30−if got.stdout != want:
31− sys.stderr.write(got.stdout.decode(errors='replace'))
32− sys.exit(1)
33−print('deferred resolver guards passed')
tools/type-deferred-testdeleted−32
@@ -1,32 +0,0 @@
1−#!/usr/bin/env python3
2−"""Evaluate the shared partial deferred-transaction report."""
3−from pathlib import Path
4−import argparse, subprocess, sys, tempfile
5−root = Path(__file__).resolve().parent.parent
6−p = argparse.ArgumentParser(description=__doc__)
7−p.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
8−a = p.parse_args()
9−core = (root / 'tests/lib/jibb-deferred.hoon').read_text()
10−core = core[core.index('\n|%\n') + 1:]
11−names = ['nested-src', 'principal-src', 'missing-src', 'conflict-src', 'duplicate-src', 'hole-src', 'local-src', 'mutual-src', 'mold-hole-src', 'face-good-src', 'face-bad-src']
12−bindings = ''.join('=/ '+n+'=wain (to-wain:format '+n+'-text)\n' for n in names)
13−program = ('=/ jibb .\n' + bindings + '=/ expected=wain (to-wain:format expected-text)\n=/ suite\n' + core +
14− '\n^- @t\n=/ checked=tang test-deferred:suite\n?~ checked \'deferred partial transaction guards passed\'\n(crip "{<checked>}")\n')
15−with tempfile.TemporaryDirectory(prefix='jibb-deferred-') as d:
16− f = Path(d) / 'report.hoon'
17− f.write_text(program)
18− cmd = [str(root/'tools/hoon'), '--lib', a.lib, '--raw', '-f', str(f)]
19− for n in names:
20− fixture = root/'tests/type-deferred'/(n+'.txt')
21− if not fixture.is_file() or fixture.stat().st_size == 0:
22− sys.exit('missing or empty fixture: ' + str(fixture))
23− cmd.extend(['--cord', n+'-text='+str(fixture)])
24− cmd.extend(['--cord', 'expected-text='+str(root/'tests/type-deferred/expected.txt')])
25− got = subprocess.run(cmd, stdout=subprocess.PIPE)
26−if got.returncode:
27− sys.exit(got.returncode)
28−want = b'deferred partial transaction guards passed\n'
29−if got.stdout != want:
30− sys.stderr.write(got.stdout.decode(errors='replace'))
31− sys.exit(1)
32−print('deferred partial transaction guards passed')
tools/type-direct-gate-testdeleted−64
@@ -1,64 +0,0 @@
1−#!/usr/bin/env python3
2−"""Check source-backed direct gate layouts and provenance under eval."""
3−from pathlib import Path
4−import argparse
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−parser = argparse.ArgumentParser(description=__doc__)
12−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
13−parser.add_argument('--update', action='store_true')
14−args = parser.parse_args()
15−fixture = root / 'tests/type-direct-gate'
16−prelude = root / 'jibb-dev/lib/jibb/prelude.jibb'
17−internal = root / 'jibb-dev/lib/jibb/internal.jibb'
18−
19−def body(name):
20− text = (root / 'tests/lib' / name).read_text()
21− return text[text.index('\n|%\n') + 1:]
22−
23−def run(program, cords=()):
24− with tempfile.TemporaryDirectory(prefix='jibb-direct-gate-') as tmp:
25− path = Path(tmp) / 'test.hoon'
26− path.write_text(program)
27− return subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib, '--raw',
28− '-f', str(path), *cords], stdout=subprocess.PIPE)
29−
30−source_program = ('=/ jibb .\n=/ real-prelude=@t prelude\n=/ real-internal=@t internal\n'
31− '=/ source=wain (to-wain:format source-text)\n=/ expected=wain ~\n'
32− '=/ suite\n' + body('jibb-direct-gate-source.hoon') +
33− '\n^- @t\n=/ prepared=(unit iprelude:jibb) (direct-gate-prepared:suite real-prelude real-internal)\n'
34− '=/ failures=(list tape) (direct-gate-projection-errors:suite prepared)\n'
35− '?~ failures (direct-gate-source-output:suite source-text prepared)\n'
36− '(of-wain:format (turn failures crip))\n')
37−result = run(source_program, ['--cord', 'source-text=' + str(fixture / 'source.txt'),
38− '--cord', 'prelude=' + str(prelude),
39− '--cord', 'internal=' + str(internal)])
40−if result.returncode:
41− sys.exit(result.returncode)
42−expected_path = fixture / 'expected.txt'
43−if args.update:
44− expected_path.write_bytes(result.stdout)
45−else:
46− expected = expected_path.read_bytes()
47− if result.stdout != expected:
48− sys.stderr.writelines(difflib.unified_diff(
49− expected.decode().splitlines(keepends=True),
50− result.stdout.decode().splitlines(keepends=True),
51− fromfile='expected.txt', tofile='actual types'))
52− sys.exit(1)
53−
54−guard_program = ('=/ jibb .\n=/ suite\n' + body('jibb-direct-gate-guards.hoon') +
55− '\n=/ failures=(list tape) direct-gate-guard-errors:suite\n^- @t\n'
56− "?~ failures 'direct gate guards passed'\n"
57− '(of-wain:format (turn failures crip))\n')
58−result = run(guard_program)
59−if result.returncode:
60− sys.exit(result.returncode)
61−if result.stdout != b'direct gate guards passed\n':
62− sys.stderr.buffer.write(result.stdout)
63− sys.exit(1)
64−print('direct gate source and provenance guards passed')
tools/type-doc-examples-testdeleted−49
@@ -1,49 +0,0 @@
1−#!/usr/bin/env python3
2−"""Fully check the remaining doc fragments in their intended contexts."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−parser.add_argument('--timeout', type=float, default=300,
13− help='seconds allowed for urbit eval (default: 300)')
14−args = parser.parse_args()
15−tests = (root / 'tests/lib/jibb-doc-examples.hoon').read_text()
16−tests = tests[tests.index('\n|%\n') + 1:]
17−tests = tests[:tests.index('\n++ test-doc-examples')] + '\n--\n'
18−program = ('=/ jibb .\n=/ jibb-import\n' +
19− (root / 'jibb-dev/lib/jibb-import.hoon').read_text() +
20− '=/ suite\n' + tests +
21− '\n=/ failures=(list tape) (doc-examples-errors:suite prelude internal imports view-day step cmd-sub todo-sur todo-action blog-sur card)\n'
22− '^- @t\n?~ failures \'documented fragments passed\'\n'
23− '(of-wain:format (turn failures crip))\n')
24−fixtures = {
25− 'prelude': 'jibb-dev/lib/jibb/prelude.jibb',
26− 'internal': 'jibb-dev/lib/jibb/internal.jibb',
27− 'imports': 'tests/golden/doc-grammar-01-imports/source.jibb',
28− 'view-day': 'tests/golden/doc-grammar-03-view-day/source.jibb',
29− 'step': 'tests/golden/doc-grammar-04-step/source.jibb',
30− 'cmd-sub': 'tests/golden/doc-overview-01-cmd-sub/source.jibb',
31− 'todo-sur': 'tests/type-api-paths/todo-sur.txt',
32− 'todo-action': 'tests/type-api-paths/todo-action.txt',
33− 'blog-sur': 'tests/type-page-main/blog-sur.txt',
34− 'card': 'tests/type-page-main/card.txt',
35−}
36−with tempfile.TemporaryDirectory(prefix='jibb-doc-examples-') as tmp:
37− path = Path(tmp) / 'doc-examples.hoon'
38− path.write_text(program)
39− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(path),
40− '--timeout', str(args.timeout)]
41− for name, filename in fixtures.items():
42− command += ['--cord', name + '=' + str(root / filename)]
43− result = subprocess.run(command, stdout=subprocess.PIPE)
44−if result.returncode:
45− sys.exit(result.returncode)
46−if result.stdout != b'documented fragments passed\n':
47− sys.stderr.buffer.write(result.stdout)
48− sys.exit(1)
49−print('documented imports, view-day, step and cmd/sub detailed/legacy checks passed')
tools/type-empty-testdeleted−55
@@ -1,55 +0,0 @@
1−#!/usr/bin/env python3
2−"""Check source-backed empty molds and uninhabited union cases under eval."""
3−from pathlib import Path
4−import argparse
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−parser = argparse.ArgumentParser(description=__doc__)
12−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
13−parser.add_argument('--update', action='store_true')
14−args = parser.parse_args()
15−fixture = root / 'tests/type-empty'
16−source = (root / 'tests/lib/jibb-empty.hoon').read_text()
17−source = source[source.index('\n|%\n') + 1:]
18−names = ['good', 'overlap', 'dead', 'missing', 'standard-good', 'list-dead', 'unit-dead', 'late-cap', 'list-live', 'list-open', 'face-source']
19−cords = [item for name in names for item in ('--cord', f'{name}-text={fixture / (name + ".txt")}')]
20−cords += ['--cord', f'prelude={root / "jibb-dev/lib/jibb/prelude.jibb"}',
21− '--cord', f'internal={root / "jibb-dev/lib/jibb/internal.jibb"}']
22−if not args.update:
23− cords += ['--cord', f'expected-text={fixture / "expected.txt"}']
24−bindings = ''.join(f'=/ {name}=wain (to-wain:format {name}-text)\n' for name in names)
25−program = ('=/ jibb .\n=/ real-prelude=@t prelude\n'
26− '=/ real-internal=@t internal\n' + bindings +
27− ('=/ expected=wain ~\n' if args.update else '=/ expected=wain (to-wain:format expected-text)\n') +
28− '=/ suite\n' + source +
29− '\n=/ output=@t (empty-output:suite prelude internal ' +
30− ' '.join(name + '-text' for name in names) + ')\n' +
31− ('output\n' if args.update else
32− "=/ actual-test=tang test-empty:suite\n?~ actual-test output\n'BAD ship test arm'\n"))
33−with tempfile.TemporaryDirectory(prefix='jibb-empty-') as tmp:
34− path = Path(tmp) / 'test.hoon'
35− path.write_text(program)
36− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib, '--raw',
37− '-f', str(path), *cords], stdout=subprocess.PIPE)
38−if result.returncode:
39− sys.exit(result.returncode)
40−if any(line.startswith(b'BAD ') or line.endswith(b': BAD') for line in result.stdout.splitlines()):
41− sys.stderr.write('empty-mold guard assertion failed:\n')
42− sys.stderr.buffer.write(result.stdout)
43− sys.exit(1)
44−expected_path = fixture / 'expected.txt'
45−if args.update:
46− expected_path.write_bytes(result.stdout)
47−else:
48− expected = expected_path.read_bytes()
49− if result.stdout != expected:
50− sys.stderr.writelines(difflib.unified_diff(
51− expected.decode().splitlines(keepends=True),
52− result.stdout.decode().splitlines(keepends=True),
53− fromfile='expected.txt', tofile='actual'))
54− sys.exit(1)
55−print('source-backed empty-mold guards passed')
tools/type-full-overlap-testdeleted−49
@@ -1,49 +0,0 @@
1−#!/usr/bin/env python3
2−"""Check source-bound full-module overlap evidence under eval."""
3−from pathlib import Path
4−import argparse
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−parser = argparse.ArgumentParser(description=__doc__)
12−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
13−parser.add_argument('--update', action='store_true')
14−args = parser.parse_args()
15−fixture = root / 'tests/type-full-overlap'
16−cases = {
17− 'basic': ['same', 'zero', 'unsupported', 'precedence', 'duplicate', 'invalid', 'distinct', 'parent', 'child', 'generic', 'duplicate-generic', 'atoms', 'flag', 'nested', 'order'],
18− 'graph': ['parent', 'child', 'distinct'],
19−}
20−for kind, names in cases.items():
21− source = (root / 'tests/lib' / f'jibb-full-overlap-{kind}.hoon').read_text()
22− source = source[source.index('\n|%\n') + 1:]
23− cords = [item for name in names for item in ('--cord', f'{name}-text={fixture / (name + ".txt")}')]
24− expected = fixture / f'expected-{kind}.txt'
25− if not args.update:
26− cords += ['--cord', f'expected-text={expected}']
27− bindings = ''.join(f'=/ {name}=wain (to-wain:format {name}-text)\n' for name in names)
28− program = ('=/ jibb .\n' + bindings +
29− ('=/ expected=wain ~\n' if args.update else '=/ expected=wain (to-wain:format expected-text)\n') +
30− '=/ suite\n' + source + '\n=/ output=@t (output:suite ' +
31− ' '.join(name + '-text' for name in names) + ')\n' +
32− ('output\n' if args.update else
33− f"=/ actual-test=tang test-full-overlap-{kind}:suite\n?~ actual-test output\n'BAD ship test arm'\n"))
34− with tempfile.TemporaryDirectory(prefix='jibb-full-overlap-') as tmp:
35− path = Path(tmp) / 'driver.hoon'
36− path.write_text(program)
37− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(path), *cords], stdout=subprocess.PIPE)
38− if result.returncode:
39− sys.exit(result.returncode)
40− if any(line.startswith(b'BAD ') or line.endswith(b': BAD') for line in result.stdout.splitlines()):
41− sys.stderr.write(f'{kind} overlap guard assertion failed:\n')
42− sys.stderr.buffer.write(result.stdout)
43− sys.exit(1)
44− if args.update:
45− expected.write_bytes(result.stdout)
46− elif result.stdout != expected.read_bytes():
47− sys.stderr.writelines(difflib.unified_diff(expected.read_text().splitlines(keepends=True), result.stdout.decode().splitlines(keepends=True), fromfile=str(expected), tofile='actual'))
48− sys.exit(1)
49−print('source-bound full-module overlap guards passed')
tools/type-gate-free-guards-testdeleted−29
@@ -1,29 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared gate-free type guards under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−tests = (root / 'tests/lib/jibb-gate-free-guards.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ suite\n' + tests +
16− '\n=/ failures=(list tape) gate-free-guard-errors:suite\n^- @t\n' +
17− "?~ failures 'gate-free guards passed'\n" +
18− '(of-wain:format (turn failures crip))\n')
19−with tempfile.TemporaryDirectory(prefix='jibb-gate-free-guards-') as tmp:
20− program = Path(tmp) / 'guards.hoon'
21− program.write_text(expression)
22− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib,
23− '--raw', '-f', str(program)], stdout=subprocess.PIPE)
24−if result.returncode:
25− sys.exit(result.returncode)
26−if result.stdout != b'gate-free guards passed\n':
27− sys.stderr.buffer.write(result.stdout)
28− sys.exit(1)
29−print('gate-free type guards passed')
tools/type-gate-free-source-testdeleted−50
@@ -1,50 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run real-reader gate-free mold analysis without claiming island checking."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−fixture = root / 'tests/type-gate-free/todo.txt'
14−if fixture.read_bytes() != (root / 'my-app/ui/todo-list.jibb').read_bytes():
15− sys.exit('todo source fixture differs from my-app/ui/todo-list.jibb')
16−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
17−tests = (root / 'tests/lib/jibb-gate-free-source.hoon').read_text()
18−tests = tests[tests.index('\n|%\n') + 1:]
19−names = ('sur', 'action', 'todos', 'update', 'item', 'api', 'source',
20− 'gate-source', 'noun-source', 'expected')
21−program = ('=/ jibb .\n=/ jibb-import\n' + reader + '\n' +
22− ''.join('=/ ' + name + '=wain (to-wain:format ' + name + '-text)\n'
23− for name in names) +
24− '=/ suite\n' + tests +
25− '\n^- @t\n(gate-free-source-report:suite prelude internal sur-text action-text todos-text update-text item-text api-text source-text gate-source-text noun-source-text)\n')
26−fixtures = {'sur': 'tests/type-api-paths/todo-sur.txt',
27− 'action': 'tests/type-api-paths/todo-action.txt',
28− 'todos': 'tests/type-api-paths/todos.txt',
29− 'update': 'tests/type-api-paths/todo-update.txt',
30− 'item': 'tests/type-api-paths/todo-item.txt',
31− 'api': 'tests/type-api-paths/api.txt',
32− 'source': 'tests/type-gate-free/todo.txt',
33− 'gate-source': 'tests/type-gate-free/todo-gate.txt',
34− 'noun-source': 'tests/type-gate-free/todo-noun.txt',
35− 'expected': 'tests/type-gate-free/expected.txt'}
36−with tempfile.TemporaryDirectory(prefix='jibb-gate-free-source-') as tmp:
37− path = Path(tmp) / 'source.hoon'
38− path.write_text(program)
39− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(path),
40− '--cord', 'prelude=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
41− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
42− for name, filename in fixtures.items():
43− command += ['--cord', name + '-text=' + str(root / filename)]
44− result = subprocess.run(command, stdout=subprocess.PIPE)
45−if result.returncode:
46− sys.exit(result.returncode)
47−if result.stdout != (root / 'tests/type-gate-free/expected.txt').read_bytes():
48− sys.stderr.buffer.write(result.stdout)
49− sys.exit('gate-free source report differs from expected')
50−print('real todo gate-free mold analysis passed')
tools/type-generic-alias-testdeleted−28
@@ -1,28 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared source-backed generic alias guards under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−tests = (root / 'tests/lib/jibb-generic-alias.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ suite\n' + tests +
16− '\n=/ failures=(list tape) generic-alias-errors:suite\n'
17− "^- @t\n?~ failures 'generic alias guards passed'\n"
18− '(of-wain:format (turn failures crip))\n')
19−with tempfile.TemporaryDirectory(prefix='jibb-generic-alias-') as tmp:
20− program = Path(tmp) / 'guards.hoon'
21− program.write_text(expression)
22− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(program)], stdout=subprocess.PIPE)
23−if result.returncode:
24− sys.exit(result.returncode)
25−if result.stdout != b'generic alias guards passed\n':
26− sys.stderr.buffer.write(result.stdout)
27− sys.exit(1)
28−print('generic alias guards passed')
tools/type-generic-construction-testdeleted−49
@@ -1,49 +0,0 @@
1−#!/usr/bin/env python3
2−"""Check source-backed generic recursive construction under eval."""
3−from pathlib import Path
4−import argparse
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−parser = argparse.ArgumentParser(description=__doc__)
12−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
13−parser.add_argument('--update', action='store_true')
14−args = parser.parse_args()
15−fixture = root / 'tests/type-generic-construction'
16−source = (root / 'tests/lib/jibb-generic-construction.hoon').read_text()
17−source = source[source.index('\n|%\n') + 1:]
18−names = ['tree', 'alias', 'client', 'alias-client', 'tree-no-event',
19− 'no-event-client', 'owner-positive', 'owner-negative', 'sibling-values']
20−cords = [item for name in names
21− for item in ('--cord', f'{name}-text={fixture / (name + ".txt")}')]
22−cords += ['--cord', f'prelude={root / "jibb-dev/lib/jibb/prelude.jibb"}',
23− '--cord', f'internal={root / "jibb-dev/lib/jibb/internal.jibb"}']
24−bindings = ''.join(f'=/ {name}=wain (to-wain:format {name}-text)\n'
25− for name in names)
26−program = ("=/ jibb .\n=/ real-prelude=@t prelude\n"
27− "=/ real-internal=@t internal\n" + bindings +
28− "=/ expected=wain ~\n=/ suite\n" + source +
29− "\n^- @t\n(construction-output:suite prelude internal " +
30− ' '.join(name + '-text' for name in names) + ")\n")
31−with tempfile.TemporaryDirectory(prefix='jibb-generic-construction-') as tmp:
32− path = Path(tmp) / 'test.hoon'
33− path.write_text(program)
34− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib, '--raw',
35− '-f', str(path), *cords], stdout=subprocess.PIPE)
36−if result.returncode:
37− sys.exit(result.returncode)
38−expected_path = fixture / 'expected.txt'
39−if args.update:
40− expected_path.write_bytes(result.stdout)
41−else:
42− expected = expected_path.read_bytes()
43− if result.stdout != expected:
44− sys.stderr.writelines(difflib.unified_diff(
45− expected.decode().splitlines(keepends=True),
46− result.stdout.decode().splitlines(keepends=True),
47− fromfile='expected.txt', tofile='actual'))
48− sys.exit(1)
49−print('source-backed generic construction guards passed')
tools/type-generic-pattern-testdeleted−52
@@ -1,52 +0,0 @@
1−#!/usr/bin/env python3
2−"""Check recursive pattern coverage, state and arm bounds under eval."""
3−from pathlib import Path
4−import argparse
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−parser = argparse.ArgumentParser(description=__doc__)
12−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
13−parser.add_argument('--update', action='store_true')
14−args = parser.parse_args()
15−fixture = root / 'tests/type-generic-pattern'
16−shared = root / 'tests/type-generic-construction'
17−source = (root / 'tests/lib/jibb-generic-pattern.hoon').read_text()
18−source = source[source.index('\n|%\n') + 1:]
19−reused = ['tree', 'alias', 'tree-no-event']
20−names = ['client', 'no-event', 'values', 'poly-values', 'owner', 'owner-bad']
21−cords = [item for name in reused
22− for item in ('--cord', f'{name}-text={shared / (name + ".txt")}')]
23−cords += [item for name in names
24− for item in ('--cord', f'{name}-text={fixture / (name + ".txt")}')]
25−cords += ['--cord', f'prelude={root / "jibb-dev/lib/jibb/prelude.jibb"}',
26− '--cord', f'internal={root / "jibb-dev/lib/jibb/internal.jibb"}']
27−bindings = ''.join(f'=/ {name}=wain (to-wain:format {name}-text)\n'
28− for name in reused + names)
29−program = ("=/ jibb .\n=/ real-prelude=@t prelude\n"
30− "=/ real-internal=@t internal\n" + bindings +
31− "=/ expected=wain ~\n=/ suite\n" + source +
32− "\n^- @t\n(pattern-output:suite prelude internal " +
33− ' '.join(name + '-text' for name in reused + names) + ")\n")
34−with tempfile.TemporaryDirectory(prefix='jibb-generic-pattern-') as tmp:
35− path = Path(tmp) / 'test.hoon'
36− path.write_text(program)
37− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib, '--raw',
38− '-f', str(path), *cords], stdout=subprocess.PIPE)
39−if result.returncode:
40− sys.exit(result.returncode)
41−expected_path = fixture / 'expected.txt'
42−if args.update:
43− expected_path.write_bytes(result.stdout)
44−else:
45− expected = expected_path.read_bytes()
46− if result.stdout != expected:
47− sys.stderr.writelines(difflib.unified_diff(
48− expected.decode().splitlines(keepends=True),
49− result.stdout.decode().splitlines(keepends=True),
50− fromfile='expected.txt', tofile='actual'))
51− sys.exit(1)
52−print('source-backed generic pattern guards passed')
tools/type-generic-recursion-testdeleted−61
@@ -1,61 +0,0 @@
1−#!/usr/bin/env python3
2−"""Check indexed recursive source identity, aliases and cache under eval."""
3−from pathlib import Path
4−import argparse
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−parser = argparse.ArgumentParser(description=__doc__)
12−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
13−parser.add_argument('--update', action='store_true')
14−args = parser.parse_args()
15−fixture = root / 'tests/type-generic-recursion'
16−source = (root / 'tests/lib/jibb-generic-recursion.hoon').read_text()
17−source = source[source.index('\n|%\n') + 1:]
18−names = ['tree', 'changed', 'alias', 'client', 'bad-mold', 'bad-constructor',
19− 'bad-parameter', 'local-shadow', 'local-distinct', 'local-only',
20− 'list-shadow', 'chain', 'bad-match']
21−files = ['tree', 'tree-changed', 'alias', 'client', 'bad-mold', 'bad-constructor',
22− 'bad-parameter', 'local-shadow', 'local-distinct', 'local-only',
23− 'list-shadow', 'chain', 'bad-match']
24−cords = [item for name, file in zip(names, files)
25− for item in ('--cord', f'{name}-text={fixture / (file + ".txt")}')]
26−cords += ['--cord', f'prelude={root / "jibb-dev/lib/jibb/prelude.jibb"}',
27− '--cord', f'internal={root / "jibb-dev/lib/jibb/internal.jibb"}']
28−bindings = ''.join(f'=/ {name}=wain (to-wain:format {name}-text)\n'
29− for name in names)
30−program = ("=/ jibb .\n=/ real-prelude=@t prelude\n"
31− "=/ real-internal=@t internal\n" + bindings +
32− "=/ expected=wain ~\n=/ suite\n" + source +
33− "\n^- @t\n=/ invalid=(list [label=@t src=@t])\n"
34− " :~ ['unused mold hole declined' bad-mold-text]\n"
35− " ['invalid constructor declined' bad-constructor-text]\n"
36− " ['invalid matching declined' bad-match-text]\n"
37− " ['nonuniform recursion declined' bad-parameter-text]\n"
38− " ['identical local shadow declined' local-shadow-text]\n"
39− " ['different local shadow declined' local-distinct-text]\n"
40− " ['local recursion declined' local-only-text]\n"
41− " ==\n"
42− "(generic-output:suite prelude internal tree-text changed-text alias-text client-text invalid list-shadow-text chain-text)\n")
43−with tempfile.TemporaryDirectory(prefix='jibb-generic-recursion-') as tmp:
44− path = Path(tmp) / 'test.hoon'
45− path.write_text(program)
46− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib, '--raw',
47− '-f', str(path), *cords], stdout=subprocess.PIPE)
48−if result.returncode:
49− sys.exit(result.returncode)
50−expected_path = fixture / 'expected.txt'
51−if args.update:
52− expected_path.write_bytes(result.stdout)
53−else:
54− expected = expected_path.read_bytes()
55− if result.stdout != expected:
56− sys.stderr.writelines(difflib.unified_diff(
57− expected.decode().splitlines(keepends=True),
58− result.stdout.decode().splitlines(keepends=True),
59− fromfile='expected.txt', tofile='actual'))
60− sys.exit(1)
61−print('source-backed generic recursion guards passed')
tools/type-hole-guards-testdeleted−32
@@ -1,32 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared hole-defaulting and API guard checks under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−tests = (root / 'tests/lib/jibb-hole-guards.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ real-prelude=@t prelude\n'
16− '=/ real-internal=@t internal\n=/ suite\n' + tests +
17− '\n=/ failures=(list tape) hole-guard-errors:suite\n^- @t\n'
18− "?~ failures 'hole guards passed'\n"
19− '(of-wain:format (turn failures crip))\n')
20−with tempfile.TemporaryDirectory(prefix='jibb-hole-guards-') as tmp:
21− program = Path(tmp) / 'guards.hoon'
22− program.write_text(expression)
23− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(program),
24− '--cord', 'prelude=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
25− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
26− result = subprocess.run(command, stdout=subprocess.PIPE)
27−if result.returncode:
28− sys.exit(result.returncode)
29−if result.stdout != b'hole guards passed\n':
30− sys.stderr.buffer.write(result.stdout)
31− sys.exit(1)
32−print('hole defaulting and API guards passed')
tools/type-import-default-testdeleted−38
@@ -1,38 +0,0 @@
1−#!/usr/bin/env python3
2−"""Compare the source-aware default-wrapper fixture under urbit eval."""
3−
4−from pathlib import Path
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−fixture = root / 'tests/type-import-default'
12−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
13−tests = (root / 'tests/lib/jibb-import-default.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb-import\n' + reader +
16− '\n=/ tlon=wain ~\n=/ controls=wain ~\n'
17− '=/ parent=wain ~\n=/ expected=wain ~\n'
18− '=/ fixture\n' + tests +
19− '\n(fixture-output:fixture tlon-text controls-text parent-text)\n')
20−with tempfile.TemporaryDirectory(prefix='jibb-import-default-') as tmp:
21− program = Path(tmp) / 'fixture.hoon'
22− program.write_text(expression)
23− result = subprocess.run([
24− str(root / 'tools/hoon'), '--raw', '-f', str(program),
25− '--cord', 'tlon-text=' + str(fixture / 'tlon.txt'),
26− '--cord', 'controls-text=' + str(fixture / 'controls.txt'),
27− '--cord', 'parent-text=' + str(fixture / 'parent.txt')],
28− stdout=subprocess.PIPE)
29−if result.returncode:
30− sys.exit(result.returncode)
31−expected = (fixture / 'expected.txt').read_bytes()
32−if result.stdout != expected:
33− sys.stderr.writelines(difflib.unified_diff(
34− expected.decode().splitlines(keepends=True),
35− result.stdout.decode().splitlines(keepends=True),
36− fromfile='expected.txt', tofile='actual types'))
37− sys.exit(1)
38−print('default-wrapper importer golden passed')
tools/type-import-diagnostic-testdeleted−43
@@ -1,43 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the importer/checker bridge fixture under urbit eval."""
3−
4−from pathlib import Path
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−fixture = root / 'tests' / 'type-import-diagnostic'
12−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
13−tests = (root / 'tests/lib/jibb-import-diagnostic.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ jibb-import\n' + reader +
16− '\n=/ sur=wain (to-wain:format sur-text)\n'
17− '=/ mark=wain (to-wain:format mark-text)\n'
18− '=/ source=wain (to-wain:format source-text)\n'
19− '=/ nested=wain (to-wain:format nested-text)\n'
20− '=/ expected=wain (to-wain:format expected-text)\n'
21− '=/ bridge\n' + tests +
22− '\n(diagnostic-output:bridge sur-text mark-text source-text nested-text)\n')
23−with tempfile.TemporaryDirectory(prefix='jibb-type-import-') as tmp:
24− program = Path(tmp) / 'bridge.hoon'
25− program.write_text(expression)
26− result = subprocess.run([
27− str(root / 'tools/hoon'), '--raw', '-f', str(program),
28− '--cord', 'sur-text=' + str(fixture / 'sur.txt'),
29− '--cord', 'mark-text=' + str(fixture / 'mark.txt'),
30− '--cord', 'source-text=' + str(fixture / 'source.txt'),
31− '--cord', 'nested-text=' + str(fixture / 'nested.txt'),
32− '--cord', 'expected-text=' + str(fixture / 'expected.txt')],
33− stdout=subprocess.PIPE)
34−if result.returncode:
35− sys.exit(result.returncode)
36−expected = (fixture / 'expected.txt').read_bytes()
37−if result.stdout != expected:
38− sys.stderr.writelines(difflib.unified_diff(
39− expected.decode().splitlines(keepends=True),
40− result.stdout.decode().splitlines(keepends=True),
41− fromfile='expected.txt', tofile='actual types'))
42− sys.exit(1)
43−print('importer diagnostic bridge golden passed')
tools/type-import-overlap-testdeleted−33
@@ -1,33 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared source-aware overlap bridge under urbit eval."""
3−from pathlib import Path
4−import difflib
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−fixture = root / 'tests/type-import-overlap'
11−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
12−tests = (root / 'tests/lib/jibb-import-overlap.hoon').read_text()
13−tests = tests[tests.index('\n|%\n') + 1:]
14−program = ('=/ jibb .\n=/ jibb-import\n' + reader +
15− '\n=/ sur=wain (to-wain:format sur-text)\n=/ source=wain (to-wain:format source-text)\n=/ expected=wain (to-wain:format expected-text)\n=/ bridge\n' + tests + '\n(overlap-output:bridge sur-text source-text)\n')
16−with tempfile.TemporaryDirectory(prefix='jibb-import-overlap-') as tmp:
17− path = Path(tmp) / 'bridge.hoon'
18− path.write_text(program)
19− result = subprocess.run([str(root / 'tools/hoon'), '--raw', '-f', str(path),
20− '--cord', 'sur-text=' + str(fixture / 'sur.txt'),
21− '--cord', 'source-text=' + str(fixture / 'source.txt'),
22− '--cord', 'expected-text=' + str(fixture / 'expected.txt')], stdout=subprocess.PIPE)
23−if result.returncode:
24− sys.exit(result.returncode)
25−if '--capture' in sys.argv:
26− sys.stdout.buffer.write(result.stdout)
27− sys.exit()
28−expected = (fixture / 'expected.txt').read_bytes()
29−if result.stdout != expected:
30− sys.stderr.writelines(difflib.unified_diff(expected.decode().splitlines(keepends=True),
31− result.stdout.decode().splitlines(keepends=True), fromfile='expected', tofile='actual'))
32− sys.exit(1)
33−print('source-aware overlap bridge passed')
tools/type-import-structural-testdeleted−36
@@ -1,36 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared structural source-overlap fixture under urbit eval."""
3−from pathlib import Path
4−import difflib
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−fixture = root / 'tests/type-import-structural'
11−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
12−tests = (root / 'tests/lib/jibb-import-structural.hoon').read_text()
13−tests = tests[tests.index('\n|%\n') + 1:]
14−program = ('=/ jibb .\n=/ jibb-import\n' + reader +
15− '\n=/ sur=wain (to-wain:format sur-text)\n'
16− '=/ source=wain (to-wain:format source-text)\n'
17− '=/ expected=wain (to-wain:format expected-text)\n'
18− '=/ bridge\n' + tests + '\n(structural-output:bridge sur-text source-text)\n')
19−with tempfile.TemporaryDirectory(prefix='jibb-import-structural-') as tmp:
20− path = Path(tmp) / 'bridge.hoon'
21− path.write_text(program)
22− result = subprocess.run([str(root / 'tools/hoon'), '--raw', '-f', str(path),
23− '--cord', 'sur-text=' + str(fixture / 'sur.txt'),
24− '--cord', 'source-text=' + str(fixture / 'source.txt'),
25− '--cord', 'expected-text=' + str(fixture / 'expected.txt')], stdout=subprocess.PIPE)
26−if result.returncode:
27− sys.exit(result.returncode)
28−if '--capture' in sys.argv:
29− sys.stdout.buffer.write(result.stdout)
30− sys.exit()
31−expected = (fixture / 'expected.txt').read_bytes()
32−if result.stdout != expected:
33− sys.stderr.writelines(difflib.unified_diff(expected.decode().splitlines(keepends=True),
34− result.stdout.decode().splitlines(keepends=True), fromfile='expected', tofile='actual'))
35− sys.exit(1)
36−print('structural source-overlap bridge passed')
tools/type-import-testdeleted−39
@@ -1,39 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the importer/checker bridge fixture under urbit eval."""
3−
4−from pathlib import Path
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−fixture = root / 'tests' / 'type-import'
12−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
13−tests = (root / 'tests/lib/jibb-bridge.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ jibb-import\n' + reader +
16− '\n=/ sur=wain (to-wain:format sur-text)\n'
17− '=/ source=wain (to-wain:format source-text)\n'
18− '=/ expected=wain (to-wain:format expected-text)\n'
19− '=/ bridge\n' + tests +
20− '\n(bridge-output:bridge sur-text source-text)\n')
21−with tempfile.TemporaryDirectory(prefix='jibb-type-import-') as tmp:
22− program = Path(tmp) / 'bridge.hoon'
23− program.write_text(expression)
24− result = subprocess.run([
25− str(root / 'tools/hoon'), '--raw', '-f', str(program),
26− '--cord', 'sur-text=' + str(fixture / 'sur.txt'),
27− '--cord', 'source-text=' + str(fixture / 'source.txt'),
28− '--cord', 'expected-text=' + str(fixture / 'expected.txt')],
29− stdout=subprocess.PIPE)
30−if result.returncode:
31− sys.exit(result.returncode)
32−expected = (fixture / 'expected.txt').read_bytes()
33−if result.stdout != expected:
34− sys.stderr.writelines(difflib.unified_diff(
35− expected.decode().splitlines(keepends=True),
36− result.stdout.decode().splitlines(keepends=True),
37− fromfile='expected.txt', tofile='actual types'))
38− sys.exit(1)
39−print('importer/checker bridge golden passed')
tools/type-list-alias-testdeleted−33
@@ -1,33 +0,0 @@
1−#!/usr/bin/env python3
2−"""Compare source-backed list alias preparation under eval."""
3−from pathlib import Path
4−import argparse
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−parser = argparse.ArgumentParser(description=__doc__)
12−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
13−parser.add_argument('--update', action='store_true')
14−args = parser.parse_args()
15−tests = (root / 'tests/lib/jibb-list-alias-guards.hoon').read_text()
16−tests = tests[tests.index('\n|%\n') + 1:]
17−expression = '=/ jibb .\n=/ expected=wain ~\n=/ suite\n' + tests + '\nlist-alias-output:suite\n'
18−with tempfile.TemporaryDirectory(prefix='jibb-list-alias-') as tmp:
19− program = Path(tmp) / 'guards.hoon'
20− program.write_text(expression)
21− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(program)], stdout=subprocess.PIPE)
22−if result.returncode:
23− sys.exit(result.returncode)
24−expected_path = root / 'tests/type-list-alias/expected.txt'
25−if args.update:
26− expected_path.write_bytes(result.stdout)
27− print('updated list alias guards golden')
28− sys.exit(0)
29−expected = expected_path.read_bytes()
30−if result.stdout != expected:
31− sys.stderr.writelines(difflib.unified_diff(expected.decode().splitlines(keepends=True), result.stdout.decode().splitlines(keepends=True), fromfile='expected.txt', tofile='actual'))
32− sys.exit(1)
33−print('list alias guards golden passed')
tools/type-mark-testdeleted−35
@@ -1,35 +0,0 @@
1−#!/usr/bin/env python3
2−"""Compare the mark/checker bridge fixture under urbit eval."""
3−
4−from pathlib import Path
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−fixture = root / 'tests' / 'type-mark'
12−tests = (root / 'tests/lib/jibb-mark-bridge.hoon').read_text()
13−tests = tests[tests.index('\n|%\n') + 1:]
14−expression = ('=/ jibb .\n' +
15− ''.join('=/ ' + n + '=wain (to-wain:format ' + n + '-text)\n'
16− for n in ('declared', 'missing', 'sur', 'collision', 'expected')) +
17− '=/ bridge\n' + tests +
18− '\n(bridge-output:bridge declared-text missing-text sur-text collision-text)\n')
19−with tempfile.TemporaryDirectory(prefix='jibb-type-mark-') as tmp:
20− program = Path(tmp) / 'bridge.hoon'
21− program.write_text(expression)
22− command = [str(root / 'tools/hoon'), '--raw', '-f', str(program)]
23− for name in ('declared', 'missing', 'sur', 'collision', 'expected'):
24− command += ['--cord', name + '-text=' + str(fixture / (name + '.txt'))]
25− result = subprocess.run(command, stdout=subprocess.PIPE)
26−if result.returncode:
27− sys.exit(result.returncode)
28−expected = (fixture / 'expected.txt').read_bytes()
29−if result.stdout != expected:
30− sys.stderr.writelines(difflib.unified_diff(
31− expected.decode().splitlines(keepends=True),
32− result.stdout.decode().splitlines(keepends=True),
33− fromfile='expected.txt', tofile='actual types'))
34− sys.exit(1)
35−print('mark/checker bridge golden passed')
tools/type-module-scope-testdeleted−40
@@ -1,40 +0,0 @@
1−#!/usr/bin/env python3
2−"""Compare the module/prelude scope report under urbit eval."""
3−
4−from pathlib import Path
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−fixture = root / 'tests/type-module-scope/expected.txt'
12−tests = (root / 'tests/lib/jibb-module-scope.hoon').read_text()
13−tests = tests[tests.index('\n|%\n') + 1:]
14−expression = ('=/ jibb .\n=/ expected=wain (to-wain:format expected-text)\n'
15− '=/ real-prelude=@t prelude-text\n=/ real-internal=@t internal-text\n=/ real-source=@t source-text\n'
16− '=/ real-left=@t left-text\n=/ real-right=@t right-text\n'
17− '=/ real-expected=wain (to-wain:format types-text)\n'
18− '=/ suite\n' + tests + '\nscope-output:suite\n')
19−with tempfile.TemporaryDirectory(prefix='jibb-module-scope-') as tmp:
20− program = Path(tmp) / 'scope.hoon'
21− program.write_text(expression)
22− result = subprocess.run([str(root / 'tools/hoon'), '--raw', '-f', str(program),
23− '--cord', 'expected-text=' + str(fixture),
24− '--cord', 'prelude-text=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
25− '--cord', 'internal-text=' + str(root / 'jibb-dev/lib/jibb/internal.jibb'),
26− '--cord', 'source-text=' + str(root / 'tests/golden/types-prelude-interface/source.jibb'),
27− '--cord', 'left-text=' + str(root / 'tests/golden/types-prelude-interface/modules/ui/left.jibb'),
28− '--cord', 'right-text=' + str(root / 'tests/golden/types-prelude-interface/modules/ui/right.jibb'),
29− '--cord', 'types-text=' + str(root / 'tests/golden/types-prelude-interface/types.txt')],
30− stdout=subprocess.PIPE)
31−if result.returncode:
32− sys.exit(result.returncode)
33−expected = fixture.read_bytes()
34−if result.stdout != expected:
35− sys.stderr.writelines(difflib.unified_diff(
36− expected.decode().splitlines(keepends=True),
37− result.stdout.decode().splitlines(keepends=True),
38− fromfile='expected.txt', tofile='actual types'))
39− sys.exit(1)
40−print('module/prelude scope golden passed')
tools/type-nested-union-guards-testdeleted−29
@@ -1,29 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared nested union context guards under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−tests = (root / 'tests/lib/jibb-nested-union-guards.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ suite\n' + tests +
16− '\n=/ failures=(list tape) nested-union-guard-errors:suite\n^- @t\n' +
17− "?~ failures 'nested union guards passed'\n" +
18− '(of-wain:format (turn failures crip))\n')
19−with tempfile.TemporaryDirectory(prefix='jibb-nested-union-guards-') as tmp:
20− program = Path(tmp) / 'guards.hoon'
21− program.write_text(expression)
22− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib,
23− '--raw', '-f', str(program)], stdout=subprocess.PIPE)
24−if result.returncode:
25− sys.exit(result.returncode)
26−if result.stdout != b'nested union guards passed\n':
27− sys.stderr.buffer.write(result.stdout)
28− sys.exit(1)
29−print('nested union context guards passed')
tools/type-page-main-testdeleted−86
@@ -1,86 +0,0 @@
1−#!/usr/bin/env python3
2−"""Check static and direct data pages through real readers under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−parser.add_argument('--timeout', type=float, default=600,
13− help='seconds allowed for urbit eval (default: 600)')
14−args = parser.parse_args()
15−for fixture, actual in (
16− ('tests/type-page-main/static.txt', 'my-app/ui/about.jibb'),
17− ('tests/type-page-main/blog-index.txt', 'my-app/ui/blog/index.jibb'),
18− ('tests/type-page-main/index.txt', 'my-app/ui/index.jibb'),
19− ('tests/type-page-main/blog-api.txt', 'my-app/ui/api/blog.jibb'),
20− ('tests/type-page-main/card.txt', 'my-app/ui/components/card.jibb'),
21− ('tests/type-page-main/blog-sur.txt', 'my-app/sur/blog.hoon'),
22− ('tests/type-page-main/todo-api.txt', 'my-app/ui/api/todo.jibb'),
23− ('tests/type-page-main/todo-island.txt', 'my-app/ui/todo-list.jibb')):
24− if (root / fixture).read_bytes() != (root / actual).read_bytes():
25− sys.exit(f'{fixture} differs from {actual}')
26−# As with the todo readers, eval supplies the imported core in the subject;
27−# only the Ford import line is removed from the real mark source.
28−posts = (root / 'my-app/mar/posts.hoon').read_bytes().replace(b'/- blog\n', b'', 1)
29−if (root / 'tests/type-page-main/posts-mark.txt').read_bytes() != posts:
30− sys.exit('posts reader fixture differs from my-app/mar/posts.hoon without /- blog')
31−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
32−tests = (root / 'tests/lib/jibb-page-main.hoon').read_text()
33−tests = tests[tests.index('\n|%\n') + 1:]
34−fixtures = {
35− 'sur': 'tests/type-api-paths/todo-sur.txt',
36− 'action': 'tests/type-api-paths/todo-action.txt',
37− 'todos': 'tests/type-api-paths/todos.txt',
38− 'update': 'tests/type-api-paths/todo-update.txt',
39− 'item': 'tests/type-api-paths/todo-item.txt',
40− **{name: f'tests/type-page-main/{name}.txt' for name in (
41− 'todo-api', 'todo-island', 'blog-sur', 'posts', 'blog-api',
42− 'card', 'static', 'blog-index', 'index', 'ctor-page', 'wrong-static',
43− 'arbitrary-main', 'page-alias', 'indirect-load', 'pure-load',
44− 'hand-built-load', 'typed-load', 'diff-load')},
45−}
46−fixtures['posts'] = 'tests/type-page-main/posts-mark.txt'
47−# The Hoon face for the static source is about; its metadata remains about.txt.
48−cords = dict(fixtures)
49−cords['about'] = cords.pop('static')
50−prefix = ('=/ jibb .\n=/ jibb-import\n' + reader + '\n' +
51− ''.join('=/ ' + name + '=wain (to-wain:format ' + name + '-text)\n'
52− for name in cords) + '=/ suite\n' + tests)
53−negative_names = ('wrong-static', 'arbitrary-main', 'page-alias',
54− 'indirect-load', 'pure-load', 'hand-built-load',
55− 'typed-load', 'diff-load')
56−negative_labels = ('wrong static message', 'arbitrary main', 'page alias',
57− 'indirect load', 'pure load', 'hand-built load',
58− 'typed load', 'diff load')
59−negatives = ''.join(f" ['{label}' (text:suite {name})]\n"
60− for label, name in zip(negative_labels, negative_names))
61−ordered = ('sur', 'action', 'todos', 'update', 'item', 'todo-api',
62− 'todo-island', 'blog-sur', 'posts', 'blog-api', 'card',
63− 'about', 'blog-index', 'index', 'ctor-page')
64−arguments = ' '.join(f'(text:suite {name})' for name in ordered)
65−expression = (prefix + '\n=/ negatives=(list [label=@t src=@t])\n :~\n' +
66− negatives + ' ==\n' +
67− '=/ failures=(list tape) (page-main-errors:suite prelude internal ' +
68− arguments + ' negatives)\n^- @t\n'
69− "?~ failures 'static and direct data-page checks passed'\n"
70− '(of-wain:format (turn failures crip))\n')
71−with tempfile.TemporaryDirectory(prefix='jibb-page-main-') as tmp:
72− path = Path(tmp) / 'page-main.hoon'
73− path.write_text(expression)
74− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(path),
75− '--timeout', str(args.timeout),
76− '--cord', 'prelude=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
77− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
78− for name, filename in cords.items():
79− command += ['--cord', name + '-text=' + str(root / filename)]
80− result = subprocess.run(command, stdout=subprocess.PIPE)
81−if result.returncode:
82− sys.exit(result.returncode)
83−if result.stdout != b'static and direct data-page checks passed\n':
84− sys.stderr.buffer.write(result.stdout)
85− sys.exit(1)
86−print('byte-identical static/data pages, exact types, imports and negatives passed')
tools/type-poke-testdeleted−50
@@ -1,50 +0,0 @@
1−#!/usr/bin/env python3
2−"""Compare the source-backed private poke/API fixture under urbit eval."""
3−
4−from pathlib import Path
5−import argparse
6−import difflib
7−import subprocess
8−import sys
9−import tempfile
10−
11−root = Path(__file__).resolve().parent.parent
12−parser = argparse.ArgumentParser(description=__doc__)
13−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
14−parser.add_argument('--update', action='store_true')
15−args = parser.parse_args()
16−fixture = root / 'tests/type-poke'
17−names = ('mark', 'api', 'client', 'direct', 'alias', 'public', 'fake',
18− 'exported', 'transitive', 'inner', 'impostor-client', 'impostor')
19−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
20−tests = (root / 'tests/lib/jibb-poke-bridge.hoon').read_text()
21−tests = tests[tests.index('\n|%\n') + 1:]
22−expression = ('=/ jibb .\n=/ jibb-import\n' + reader +
23− '\n=/ prelude=@t prelude-text\n=/ internal=@t internal-text\n' +
24− ''.join('=/ ' + n + '=wain (to-wain:format ' + n + '-text)\n' for n in names) +
25− '=/ expected=wain (to-wain:format expected-text)\n' +
26− '=/ bridge\n' + tests +
27− '\n(bridge-output:bridge prelude internal ' + ' '.join(n + '-text' for n in names) + ')\n')
28−with tempfile.TemporaryDirectory(prefix='jibb-type-poke-') as tmp:
29− program = Path(tmp) / 'bridge.hoon'
30− program.write_text(expression)
31− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(program),
32− '--cord', 'prelude-text=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
33− '--cord', 'internal-text=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
34− for name in names + ('expected',):
35− command += ['--cord', name + '-text=' + str(fixture / (name + '.txt'))]
36− result = subprocess.run(command, stdout=subprocess.PIPE)
37−if result.returncode:
38− sys.exit(result.returncode)
39−expected = (fixture / 'expected.txt').read_bytes()
40−if args.update:
41− (fixture / 'expected.txt').write_bytes(result.stdout)
42− print('updated private poke/API bridge golden')
43− sys.exit(0)
44−if result.stdout != expected:
45− sys.stderr.writelines(difflib.unified_diff(
46− expected.decode().splitlines(keepends=True),
47− result.stdout.decode().splitlines(keepends=True),
48− fromfile='expected.txt', tofile='actual types'))
49− sys.exit(1)
50−print('private poke/API bridge golden passed')
tools/type-positional-face-guards-testdeleted−29
@@ -1,29 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared positional sample-face guards under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−tests = (root / 'tests/lib/jibb-positional-face-guards.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ suite\n' + tests +
16− '\n=/ failures=(list tape) positional-face-guard-errors:suite\n^- @t\n' +
17− "?~ failures 'positional guards passed'\n" +
18− '(of-wain:format (turn failures crip))\n')
19−with tempfile.TemporaryDirectory(prefix='jibb-positional-guards-') as tmp:
20− program = Path(tmp) / 'guards.hoon'
21− program.write_text(expression)
22− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib,
23− '--raw', '-f', str(program)], stdout=subprocess.PIPE)
24−if result.returncode:
25− sys.exit(result.returncode)
26−if result.stdout != b'positional guards passed\n':
27− sys.stderr.buffer.write(result.stdout)
28− sys.exit(1)
29−print('positional sample-face guards passed')
tools/type-program-init-testdeleted−55
@@ -1,55 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run transactional direct-program initializer context checks under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−
14−def body(name):
15− text = (root / 'tests/lib' / name).read_text()
16− return text[text.index('\n|%\n') + 1:]
17−
18−alternates = ('initializer-unfaced', 'initializer-pun', 'initializer-alias',
19− 'initializer-open-update', 'initializer-open-view',
20− 'initializer-nested-branch')
21−names = ('initializer', 'initializer-consumer') + alternates + (
22− 'initializer-error', 'initializer-earlier', 'initializer-model',
23− 'initializer-message', 'initializer-generic', 'initializer-missing',
24− 'initializer-tag', 'initializer-no-main', 'initializer-subs')
25−expression = ('=/ jibb .\n=/ prelude=@t prelude-text\n'
26− '=/ internal=@t internal-text\n' +
27− ''.join('=/ ' + name + '=wain (to-wain:format ' + name + '-text)\n'
28− for name in names) +
29− '=/ suite\n' + body('jibb-program-init.hoon') +
30− '\n=/ negatives=(list @t)\n :~ (text:suite initializer-error)\n'
31− ' (text:suite initializer-earlier)\n (text:suite initializer-model)\n'
32− ' (text:suite initializer-message)\n (text:suite initializer-generic)\n'
33− ' (text:suite initializer-missing)\n (text:suite initializer-tag)\n'
34− ' (text:suite initializer-no-main)\n (text:suite initializer-subs)\n ==\n'
35− '=/ alternates=(list [name=@ta src=@t])\n :~ ' +
36− '\n '.join("[%" + name + " (text:suite " + name + ")]" for name in alternates) +
37− '\n ==\n'
38− '=/ failures=(list tape) (program-init-errors:suite prelude internal (text:suite initializer) (text:suite initializer-consumer) alternates negatives)\n'
39− '^- @t\n?~ failures \'program initializer checks passed\'\n'
40− '(of-wain:format (turn failures crip))\n')
41−with tempfile.TemporaryDirectory(prefix='jibb-program-init-') as tmp:
42− program = Path(tmp) / 'program-init.hoon'
43− program.write_text(expression)
44− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(program),
45− '--cord', 'prelude-text=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
46− '--cord', 'internal-text=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
47− for name in names:
48− command += ['--cord', name + '-text=' + str(root / 'tests/type-program-main' / (name + '.txt'))]
49− result = subprocess.run(command, stdout=subprocess.PIPE)
50−if result.returncode:
51− sys.exit(result.returncode)
52−if result.stdout != b'program initializer checks passed\n':
53− sys.stderr.buffer.write(result.stdout)
54− sys.exit(1)
55−print('transactional direct-program initializer context guards passed')
tools/type-program-main-testdeleted−46
@@ -1,46 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared closed program-main checks under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−
14−def body(name):
15− text = (root / 'tests/lib' / name).read_text()
16− return text[text.index('\n|%\n') + 1:]
17−
18−names = ('source', 'consumer', 'gate-model', 'gate-data', 'nonempty-subs',
19− 'mismatched-model', 'arbitrary-main', 'alias-main', 'open-message')
20−expression = ('=/ jibb .\n=/ prelude=@t prelude-text\n'
21− '=/ internal=@t internal-text\n' +
22− ''.join('=/ ' + name + '=wain (to-wain:format ' + name + '-text)\n'
23− for name in names) +
24− '=/ expected=wain ~\n=/ suite\n' + body('jibb-program-main.hoon') +
25− '\n=/ negatives=(list @t)\n :~ (text:suite gate-model)\n'
26− ' (text:suite gate-data)\n (text:suite nonempty-subs)\n'
27− ' (text:suite mismatched-model)\n (text:suite arbitrary-main)\n'
28− ' (text:suite alias-main)\n (text:suite open-message)\n ==\n'
29− '=/ failures=(list tape) (program-main-errors:suite prelude internal (text:suite source) (text:suite consumer) negatives)\n'
30− '^- @t\n?~ failures \'program main checks passed\'\n'
31− '(of-wain:format (turn failures crip))\n')
32−with tempfile.TemporaryDirectory(prefix='jibb-program-main-') as tmp:
33− program = Path(tmp) / 'program-main.hoon'
34− program.write_text(expression)
35− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(program),
36− '--cord', 'prelude-text=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
37− '--cord', 'internal-text=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
38− for name in names:
39− command += ['--cord', name + '-text=' + str(root / 'tests/type-program-main' / (name + '.txt'))]
40− result = subprocess.run(command, stdout=subprocess.PIPE)
41−if result.returncode:
42− sys.exit(result.returncode)
43−if result.stdout != b'program main checks passed\n':
44− sys.stderr.buffer.write(result.stdout)
45− sys.exit(1)
46−print('closed program-main interface and rejection guards passed')
tools/type-program-update-testdeleted−46
@@ -1,46 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run transactional direct-program update context checks under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−
14−def body(name):
15− text = (root / 'tests/lib' / name).read_text()
16− return text[text.index('\n|%\n') + 1:]
17−
18−names = ('source', 'consumer', 'wrong-result', 'wrong-model', 'wrong-message',
19− 'malformed-sample', 'three-slot-sample', 'non-main', 'unrelated-tag', 'missing-list')
20−expression = ('=/ jibb .\n=/ prelude=@t prelude-text\n'
21− '=/ internal=@t internal-text\n' +
22− ''.join('=/ ' + name + '=wain (to-wain:format ' + name + '-text)\n'
23− for name in names) +
24− '=/ suite\n' + body('jibb-program-update.hoon') +
25− '\n=/ negatives=(list @t)\n :~ (text:suite wrong-result)\n'
26− ' (text:suite wrong-model)\n (text:suite wrong-message)\n'
27− ' (text:suite malformed-sample)\n (text:suite three-slot-sample)\n'
28− ' (text:suite non-main)\n (text:suite unrelated-tag)\n (text:suite missing-list)\n ==\n'
29− '=/ failures=(list tape) (program-update-errors:suite prelude internal (text:suite source) (text:suite consumer) negatives)\n'
30− '^- @t\n?~ failures \'program update checks passed\'\n'
31− '(of-wain:format (turn failures crip))\n')
32−with tempfile.TemporaryDirectory(prefix='jibb-program-update-') as tmp:
33− program = Path(tmp) / 'program-update.hoon'
34− program.write_text(expression)
35− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(program),
36− '--cord', 'prelude-text=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
37− '--cord', 'internal-text=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
38− for name in names:
39− command += ['--cord', name + '-text=' + str(root / 'tests/type-program-update' / (name + '.txt'))]
40− result = subprocess.run(command, stdout=subprocess.PIPE)
41−if result.returncode:
42− sys.exit(result.returncode)
43−if result.stdout != b'program update checks passed\n':
44− sys.stderr.buffer.write(result.stdout)
45− sys.exit(1)
46−print('transactional direct-program update context guards passed')
tools/type-program-watch-testdeleted−48
@@ -1,48 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run direct request-value watchability checks under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−fixture = root / 'tests/type-api-paths/api.txt'
14−actual = root / 'my-app/ui/api/todo.jibb'
15−if fixture.read_bytes() != actual.read_bytes():
16− sys.exit('todo API fixture differs from my-app/ui/api/todo.jibb')
17−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
18−tests = (root / 'tests/lib/jibb-program-watch.hoon').read_text()
19−tests = tests[tests.index('\n|%\n') + 1:]
20−names = ('sur', 'action', 'todos', 'update', 'item', 'api')
21−program = ('=/ jibb .\n=/ jibb-import\n' + reader + '\n' +
22− ''.join('=/ ' + name + '=wain (to-wain:format ' + name + '-text)\n'
23− for name in names) +
24− '=/ suite\n' + tests +
25− '\n=/ failures=(list tape) (program-watch-errors:suite prelude internal (text:suite sur) (text:suite action) (text:suite todos) (text:suite update) (text:suite item) (text:suite api))\n'
26− '^- @t\n?~ failures \'program request-value watchability passed\'\n'
27− '(of-wain:format (turn failures crip))\n')
28−fixtures = {'sur': 'tests/type-api-paths/todo-sur.txt',
29− 'action': 'tests/type-api-paths/todo-action.txt',
30− 'todos': 'tests/type-api-paths/todos.txt',
31− 'update': 'tests/type-api-paths/todo-update.txt',
32− 'item': 'tests/type-api-paths/todo-item.txt',
33− 'api': 'tests/type-api-paths/api.txt'}
34−with tempfile.TemporaryDirectory(prefix='jibb-program-watch-') as tmp:
35− path = Path(tmp) / 'program-watch.hoon'
36− path.write_text(program)
37− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(path),
38− '--cord', 'prelude=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
39− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
40− for name, filename in fixtures.items():
41− command += ['--cord', name + '-text=' + str(root / filename)]
42− result = subprocess.run(command, stdout=subprocess.PIPE)
43−if result.returncode:
44− sys.exit(result.returncode)
45−if result.stdout != b'program request-value watchability passed\n':
46− sys.stderr.buffer.write(result.stdout)
47− sys.exit(1)
48−print('direct request-value watchability and rejection guards passed')
tools/type-proj-guards-testdeleted−32
@@ -1,32 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared proj lowering and API reservation guards under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−tests = (root / 'tests/lib/jibb-proj-guards.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ real-prelude=@t prelude\n'
16− '=/ real-internal=@t internal\n=/ suite\n' + tests +
17− '\n=/ failures=(list tape) proj-guard-errors:suite\n^- @t\n'
18− "?~ failures 'proj guards passed'\n"
19− '(of-wain:format (turn failures crip))\n')
20−with tempfile.TemporaryDirectory(prefix='jibb-proj-guards-') as tmp:
21− program = Path(tmp) / 'guards.hoon'
22− program.write_text(expression)
23− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(program),
24− '--cord', 'prelude=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
25− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
26− result = subprocess.run(command, stdout=subprocess.PIPE)
27−if result.returncode:
28− sys.exit(result.returncode)
29−if result.stdout != b'proj guards passed\n':
30− sys.stderr.buffer.write(result.stdout)
31− sys.exit(1)
32−print('proj lowering and API reservation guards passed')
tools/type-qath-guards-testdeleted−31
@@ -1,31 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared qath fuel, face, and source-provenance guards under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−with tempfile.TemporaryDirectory(prefix='jibb-qath-guards-') as tmp:
14− for kind in ('fuel', 'source'):
15− tests = (root / f'tests/lib/jibb-qath-{kind}.hoon').read_text()
16− tests = tests[tests.index('\n|%\n') + 1:]
17− expression = ('=/ jibb .\n=/ real-internal=@t internal\n=/ suite\n' + tests +
18− f'\n=/ failures=(list tape) qath-{kind}-errors:suite\n^- @t\n' +
19− "?~ failures 'qath guards passed'\n" +
20− '(of-wain:format (turn failures crip))\n')
21− program = Path(tmp) / f'{kind}.hoon'
22− program.write_text(expression)
23− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(program),
24− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
25− result = subprocess.run(command, stdout=subprocess.PIPE)
26− if result.returncode:
27− sys.exit(result.returncode)
28− if result.stdout != b'qath guards passed\n':
29− sys.stderr.buffer.write(result.stdout)
30− sys.exit(1)
31−print('qath fuel, face, and source guards passed')
tools/type-request-guards-testdeleted−31
@@ -1,31 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the request certificate and cache provenance guards under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−tests = (root / 'tests/lib/jibb-request-guards.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ suite\n' + tests +
16− '\n=/ failures=(list tape) request-guard-errors:suite\n^- @t\n' +
17− "?~ failures 'request guards passed'\n" +
18− '(of-wain:format (turn failures crip))\n')
19−with tempfile.TemporaryDirectory(prefix='jibb-request-guards-') as tmp:
20− program = Path(tmp) / 'guards.hoon'
21− program.write_text(expression)
22− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib, '--raw',
23− '--cord', 'public=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
24− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb'),
25− '-f', str(program)], stdout=subprocess.PIPE)
26−if result.returncode:
27− sys.exit(result.returncode)
28−if result.stdout != b'request guards passed\n':
29− sys.stderr.buffer.write(result.stdout)
30− sys.exit(1)
31−print('request certificate and cache guards passed')
tools/type-store-testdeleted−41
@@ -1,41 +0,0 @@
1−#!/usr/bin/env python3
2−"""Check the unchanged cart store and basket under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−parser.add_argument('--timeout', type=float, default=300,
13− help='seconds allowed for urbit eval (default: 300)')
14−args = parser.parse_args()
15−for fixture, actual in (('tests/type-store/cart.txt', 'my-app/ui/stores/cart.jibb'),
16− ('tests/type-store/basket.txt', 'my-app/ui/basket.jibb')):
17− if (root / fixture).read_bytes() != (root / actual).read_bytes():
18− sys.exit(f'{fixture} differs from {actual}')
19−tests = (root / 'tests/lib/jibb-store.hoon').read_text()
20−tests = tests[tests.index('\n|%\n') + 1:]
21−tests = tests[:tests.index('\n++ test-store')] + '\n--\n'
22−program = ('=/ jibb .\n=/ suite\n' + tests +
23− '\n=/ failures=(list tape) (store-errors:suite prelude internal cart basket)\n'
24− '^- @t\n?~ failures \'unchanged cart store and basket passed\'\n'
25− '(of-wain:format (turn failures crip))\n')
26−with tempfile.TemporaryDirectory(prefix='jibb-store-') as tmp:
27− path = Path(tmp) / 'store.hoon'
28− path.write_text(program)
29− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(path),
30− '--timeout', str(args.timeout),
31− '--cord', 'prelude=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
32− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb'),
33− '--cord', 'cart=' + str(root / 'tests/type-store/cart.txt'),
34− '--cord', 'basket=' + str(root / 'tests/type-store/basket.txt')]
35− result = subprocess.run(command, stdout=subprocess.PIPE)
36−if result.returncode:
37− sys.exit(result.returncode)
38−if result.stdout != b'unchanged cart store and basket passed\n':
39− sys.stderr.buffer.write(result.stdout)
40− sys.exit(1)
41−print('unchanged cart/basket detailed/legacy, schemes, imports, watch evidence and negatives passed')
tools/type-sub-guards-testdeleted−31
@@ -1,31 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the shared sub source/typing guards under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−tests = (root / 'tests/lib/jibb-sub-guards.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ suite\n' + tests +
16− '\n=/ failures=(list tape) sub-guard-errors:suite\n^- @t\n' +
17− "?~ failures 'sub guards passed'\n" +
18− '(of-wain:format (turn failures crip))\n')
19−with tempfile.TemporaryDirectory(prefix='jibb-positional-guards-') as tmp:
20− program = Path(tmp) / 'guards.hoon'
21− program.write_text(expression)
22− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib,
23− '--raw', '--cord', 'public=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
24− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb'),
25− '-f', str(program)], stdout=subprocess.PIPE)
26−if result.returncode:
27− sys.exit(result.returncode)
28−if result.stdout != b'sub guards passed\n':
29− sys.stderr.buffer.write(result.stdout)
30− sys.exit(1)
31−print('sub source/typing guards passed')
tools/type-theme-testdeleted−44
@@ -1,44 +0,0 @@
1−#!/usr/bin/env python3
2−"""Fully check the byte-identical real theme and its mold under eval."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−parser.add_argument('--timeout', type=float, default=300,
13− help='seconds allowed for urbit eval (default: 300)')
14−args = parser.parse_args()
15−if (root / 'tests/type-theme/source.txt').read_bytes() != (root / 'my-app/ui/theme.jibb').read_bytes():
16− sys.exit('tests/type-theme/source.txt differs from my-app/ui/theme.jibb')
17−tests = (root / 'tests/lib/jibb-theme.hoon').read_text()
18−tests = tests[tests.index('\n|%\n') + 1:]
19−names = ('source', 'dark-absent', 'wrong-nested-aura', 'missing-field',
20− 'wrong-font', 'wrong-dark')
21−prefix = ('=/ jibb .\n' +
22− ''.join('=/ ' + name + '=wain (to-wain:format ' + name + '-text)\n'
23− for name in names) + '=/ suite\n' + tests)
24−arguments = ' '.join(f'(text:suite {name})' for name in names)
25−expression = (prefix + '\n=/ failures=(list tape) (theme-errors:suite prelude internal ' +
26− arguments + ')\n^- @t\n' +
27− "?~ failures 'theme checks passed'\n" +
28− '(of-wain:format (turn failures crip))\n')
29−with tempfile.TemporaryDirectory(prefix='jibb-theme-') as tmp:
30− path = Path(tmp) / 'theme.hoon'
31− path.write_text(expression)
32− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(path),
33− '--timeout', str(args.timeout),
34− '--cord', 'prelude=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
35− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
36− for name in names:
37− command += ['--cord', name + '-text=' + str(root / f'tests/type-theme/{name}.txt')]
38− result = subprocess.run(command, stdout=subprocess.PIPE)
39−if result.returncode:
40− sys.exit(result.returncode)
41−if result.stdout != b'theme checks passed\n':
42− sys.stderr.buffer.write(result.stdout)
43− sys.exit(1)
44−print('byte-identical theme, exact type, structural import and negatives passed')
tools/type-tlon-testdeleted−39
@@ -1,39 +0,0 @@
1−#!/usr/bin/env python3
2−"""Run the real Tlon importer/checker bridge fixture under urbit eval."""
3−
4−from pathlib import Path
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−fixture = root / 'tests' / 'type-tlon'
12−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
13−tests = (root / 'tests/lib/jibb-tlon-bridge.hoon').read_text()
14−tests = tests[tests.index('\n|%\n') + 1:]
15−expression = ('=/ jibb .\n=/ jibb-import\n' + reader +
16− '\n=/ presence=wain (to-wain:format sur-text)\n'
17− '=/ source=wain (to-wain:format source-text)\n'
18− '=/ expected=wain (to-wain:format expected-text)\n'
19− '=/ bridge\n' + tests +
20− '\n(bridge-output:bridge sur-text source-text)\n')
21−with tempfile.TemporaryDirectory(prefix='jibb-type-tlon-') as tmp:
22− program = Path(tmp) / 'bridge.hoon'
23− program.write_text(expression)
24− result = subprocess.run([
25− str(root / 'tools/hoon'), '--raw', '-f', str(program),
26− '--cord', 'sur-text=' + str(root / 'tests/importer/tlon-presence.txt'),
27− '--cord', 'source-text=' + str(fixture / 'source.txt'),
28− '--cord', 'expected-text=' + str(fixture / 'expected.txt')],
29− stdout=subprocess.PIPE)
30−if result.returncode:
31− sys.exit(result.returncode)
32−expected = (fixture / 'expected.txt').read_bytes()
33−if result.stdout != expected:
34− sys.stderr.writelines(difflib.unified_diff(
35− expected.decode().splitlines(keepends=True),
36− result.stdout.decode().splitlines(keepends=True),
37− fromfile='expected.txt', tofile='actual types'))
38− sys.exit(1)
39−print('Tlon importer/checker bridge golden passed')
tools/type-todo-api-testdeleted−62
@@ -1,62 +0,0 @@
1−#!/usr/bin/env python3
2−"""Check the exact todo API through the real /sur and mark readers."""
3−from pathlib import Path
4−import argparse
5−import subprocess
6−import sys
7−import tempfile
8−
9−root = Path(__file__).resolve().parent.parent
10−parser = argparse.ArgumentParser(description=__doc__)
11−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
12−args = parser.parse_args()
13−fixture = root / 'tests/type-api-paths/api.txt'
14−actual = root / 'my-app/ui/api/todo.jibb'
15−if fixture.read_bytes() != actual.read_bytes():
16− sys.exit('todo API fixture differs from my-app/ui/api/todo.jibb')
17−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
18−tests = (root / 'tests/lib/jibb-todo-api.hoon').read_text()
19−tests = tests[tests.index('\n|%\n') + 1:]
20−names = ('sur', 'action', 'todos', 'update', 'item', 'api', 'source',
21− 'negative', 'unsupported', 'expected', 'negative-expected')
22−program = ('=/ jibb .\n=/ jibb-import\n' + reader + '\n' +
23− ''.join('=/ ' + name + '=wain (to-wain:format ' + name + '-text)\n'
24− for name in names) +
25− '=/ suite\n' + tests +
26− '\n=/ out (todo-run:suite prelude internal sur-text action-text todos-text update-text item-text api-text source-text negative-text unsupported-text)\n'
27− "^- @t\n(of-wain:format ~[report.out '===NEGATIVE===' bad-report.out '===GUARD===' guards.out])\n")
28−fixtures = {'sur': 'tests/type-api-paths/todo-sur.txt',
29− 'action': 'tests/type-api-paths/todo-action.txt',
30− 'todos': 'tests/type-api-paths/todos.txt',
31− 'update': 'tests/type-api-paths/todo-update.txt',
32− 'item': 'tests/type-api-paths/todo-item.txt',
33− 'api': 'tests/type-api-paths/api.txt',
34− **{name: 'tests/type-todo-api/' + name + '.txt'
35− for name in ('source', 'negative', 'unsupported', 'expected', 'negative-expected')}}
36−with tempfile.TemporaryDirectory(prefix='jibb-todo-api-') as tmp:
37− path = Path(tmp) / 'todo.hoon'
38− path.write_text(program)
39− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(path),
40− '--cord', 'prelude=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
41− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
42− for name, filename in fixtures.items():
43− command += ['--cord', name + '-text=' + str(root / filename)]
44− result = subprocess.run(command, stdout=subprocess.PIPE)
45−if result.returncode:
46− sys.exit(result.returncode)
47−try:
48− positive, rest = result.stdout.split(b'\n===NEGATIVE===\n', 1)
49− negative, guard = rest.split(b'\n===GUARD===\n', 1)
50−except ValueError:
51− sys.stderr.buffer.write(result.stdout)
52− sys.exit('todo API test output was malformed')
53−if positive + b'\n' != (root / 'tests/type-todo-api/expected.txt').read_bytes():
54− sys.stderr.buffer.write(positive + b'\n')
55− sys.exit('todo API positive report differs from expected')
56−if negative + b'\n' != (root / 'tests/type-todo-api/negative-expected.txt').read_bytes():
57− sys.stderr.buffer.write(negative + b'\n')
58− sys.exit('todo API negative report differs from expected')
59−if guard != b'real todo interface and atomic guards passed\n':
60− sys.stderr.buffer.write(guard)
61− sys.exit('todo API interface guards failed')
62−print('real todo API reader and partial checker passed')
tools/type-todo-full-testdeleted−105
@@ -1,105 +0,0 @@
1−#!/usr/bin/env python3
2−"""Check the byte-identical full todo island through real readers."""
3−from pathlib import Path
4−import argparse
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−parser = argparse.ArgumentParser(description=__doc__)
12−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
13−parser.add_argument('--timeout', type=float, default=300,
14− help='seconds allowed for each urbit eval (default: 300)')
15−args = parser.parse_args()
16−for fixture, actual in (('tests/type-gate-free/todo.txt', 'my-app/ui/todo-list.jibb'),
17− ('tests/type-api-paths/api.txt', 'my-app/ui/api/todo.jibb')):
18− if (root / fixture).read_bytes() != (root / actual).read_bytes():
19− sys.exit(f'{fixture} differs from {actual}')
20−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
21−tests = (root / 'tests/lib/jibb-todo-full.hoon').read_text()
22−tests = tests[tests.index('\n|%\n') + 1:]
23−report_at = tests.index('\n++ todo-full-report')
24−legacy_at = tests.index('\n++ todo-full-legacy-report')
25−import_at = tests.index('\n++ todo-full-import-report')
26−negative_at = tests.index('\n++ todo-full-negative-report')
27−test_at = tests.index('\n++ test-todo-full')
28−shared = tests[:report_at]
29−suites = {'detailed': shared + tests[report_at:legacy_at] + '\n--\n',
30− 'legacy': shared + tests[legacy_at:import_at] + '\n--\n',
31− 'import': shared + tests[import_at:negative_at] + '\n--\n',
32− 'negative': shared + tests[negative_at:test_at] + '\n--\n'}
33−names = ('sur', 'action', 'todos', 'update', 'item', 'api', 'source',
34− 'wrong-model', 'wrong-message', 'wrong-result', 'ambiguous-mapper',
35− 'open-key', 'alias', 'wrong-watch', 'non-gate-view', 'cast-init', 'expected')
36−prefix = ('=/ jibb .\n=/ jibb-import\n' + reader + '\n' +
37− ''.join('=/ ' + name + '=wain (to-wain:format ' + name + '-text)\n'
38− for name in names) + '=/ suite\n')
39−fixtures = {'sur': 'tests/type-api-paths/todo-sur.txt',
40− 'action': 'tests/type-api-paths/todo-action.txt',
41− 'todos': 'tests/type-api-paths/todos.txt',
42− 'update': 'tests/type-api-paths/todo-update.txt',
43− 'item': 'tests/type-api-paths/todo-item.txt',
44− 'api': 'tests/type-api-paths/api.txt',
45− 'source': 'tests/type-gate-free/todo.txt',
46− **{name: f'tests/type-todo-full/{name}.txt'
47− for name in ('wrong-model', 'wrong-message', 'wrong-result',
48− 'ambiguous-mapper', 'open-key', 'alias', 'wrong-watch', 'non-gate-view')},
49− 'cast-init': 'tests/type-todo-full/cast-init.txt',
50− 'expected': 'tests/type-todo-full/expected.txt'}
51−
52−def evaluate(expression, kind):
53− print('running ' + expression.split(':', 1)[0].removeprefix('(todo-full-'), file=sys.stderr, flush=True)
54− with tempfile.TemporaryDirectory(prefix='jibb-todo-full-') as tmp:
55− path = Path(tmp) / 'todo.hoon'
56− path.write_text(prefix + suites[kind] + '\n^- @t\n' + expression + '\n')
57− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(path),
58− '--timeout', str(args.timeout),
59− '--cord', 'prelude=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
60− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
61− for name, filename in fixtures.items():
62− command += ['--cord', name + '-text=' + str(root / filename)]
63− result = subprocess.run(command, stdout=subprocess.PIPE)
64− if result.returncode:
65− sys.exit(result.returncode)
66− return result.stdout
67−
68−actual = evaluate('(todo-full-report:suite prelude internal sur-text action-text todos-text update-text item-text api-text source-text)', 'detailed')
69−expected = (root / 'tests/type-todo-full/expected.txt').read_bytes()
70−if actual != expected:
71− sys.stderr.writelines(difflib.unified_diff(
72− expected.decode().splitlines(keepends=True),
73− actual.decode().splitlines(keepends=True),
74− fromfile='expected.txt', tofile='actual'))
75− sys.exit('full todo report differs')
76−legacy = evaluate('(todo-full-legacy-report:suite prelude internal sur-text action-text todos-text update-text item-text api-text source-text)', 'legacy')
77−if legacy != expected:
78− sys.stderr.writelines(difflib.unified_diff(
79− expected.decode().splitlines(keepends=True),
80− legacy.decode().splitlines(keepends=True),
81− fromfile='expected.txt', tofile='legacy'))
82− sys.exit('legacy full todo report differs')
83−for expression, label in (('todo-full-report', 'detailed cast initializer'),
84− ('todo-full-legacy-report', 'legacy cast initializer')):
85− cast = evaluate(f'({expression}:suite prelude internal sur-text action-text todos-text update-text item-text api-text cast-init-text)', 'detailed' if expression == 'todo-full-report' else 'legacy')
86− if cast != expected:
87− sys.stderr.buffer.write(cast)
88− sys.exit(label + ' was rejected')
89−imported = evaluate('(todo-full-import-report:suite prelude internal sur-text action-text todos-text update-text item-text api-text source-text)', 'import')
90−if imported != b'downstream import accepted\n':
91− sys.stderr.buffer.write(imported)
92− sys.exit('downstream full todo import differs')
93−for name, label in (('wrong-model', 'wrong model'),
94− ('wrong-message', 'wrong message'),
95− ('wrong-result', 'wrong result'),
96− ('ambiguous-mapper', 'ambiguous mapper'),
97− ('open-key', 'open key'),
98− ('alias', 'mapper alias'),
99− ('wrong-watch', 'wrong watch'),
100− ('non-gate-view', 'non-gate view')):
101− actual = evaluate(f"(todo-full-negative-report:suite prelude internal sur-text action-text todos-text update-text item-text api-text '{label}' {name}-text)", 'negative')
102− if actual != f'{label}: rejected\n'.encode():
103− sys.stderr.buffer.write(actual)
104− sys.exit(f'{label} was not rejected')
105−print('byte-identical full todo detailed/legacy, types, graph, import and negatives passed')
tools/type-todo-partial-testdeleted−55
@@ -1,55 +0,0 @@
1−#!/usr/bin/env python3
2−"""Report partial inference of the unchanged todo island through real readers."""
3−from pathlib import Path
4−import argparse
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−stage = Path(__file__).resolve().parent.parent
11−parser = argparse.ArgumentParser(description=__doc__)
12−parser.add_argument('--repo', type=Path, default=stage, help=argparse.SUPPRESS)
13−parser.add_argument('--lib')
14−args = parser.parse_args()
15−root = args.repo.resolve()
16−if args.lib is None:
17− args.lib = str(root / 'jibb-dev/lib/jibb.hoon')
18−for fixture, actual in (('tests/type-gate-free/todo.txt', 'my-app/ui/todo-list.jibb'),
19− ('tests/type-api-paths/api.txt', 'my-app/ui/api/todo.jibb')):
20− if (root / fixture).read_bytes() != (root / actual).read_bytes():
21− sys.exit(f'{fixture} differs from {actual}')
22−reader = (root / 'jibb-dev/lib/jibb-import.hoon').read_text()
23−tests = (stage / 'tests/lib/jibb-todo-partial.hoon').read_text()
24−tests = tests[tests.index('\n|%\n') + 1:]
25−names = ('sur', 'action', 'todos', 'update', 'item', 'api', 'source')
26−program = ('=/ jibb .\n=/ jibb-import\n' + reader + '\n' +
27− ''.join('=/ ' + name + '=wain (to-wain:format ' + name + '-text)\n'
28− for name in names) + '=/ expected=wain ~\n=/ suite\n' + tests +
29− '\n^- @t\n(todo-island-report:suite prelude internal sur-text action-text todos-text update-text item-text api-text source-text)\n')
30−fixtures = {'sur': 'tests/type-api-paths/todo-sur.txt',
31− 'action': 'tests/type-api-paths/todo-action.txt',
32− 'todos': 'tests/type-api-paths/todos.txt',
33− 'update': 'tests/type-api-paths/todo-update.txt',
34− 'item': 'tests/type-api-paths/todo-item.txt',
35− 'api': 'tests/type-api-paths/api.txt',
36− 'source': 'tests/type-gate-free/todo.txt'}
37−with tempfile.TemporaryDirectory(prefix='jibb-todo-partial-') as tmp:
38− path = Path(tmp) / 'todo.hoon'
39− path.write_text(program)
40− command = [str(root / 'tools/hoon'), '--lib', args.lib, '--raw', '-f', str(path),
41− '--cord', 'prelude=' + str(root / 'jibb-dev/lib/jibb/prelude.jibb'),
42− '--cord', 'internal=' + str(root / 'jibb-dev/lib/jibb/internal.jibb')]
43− for name, filename in fixtures.items():
44− command += ['--cord', name + '-text=' + str(root / filename)]
45− result = subprocess.run(command, stdout=subprocess.PIPE)
46−if result.returncode:
47− sys.exit(result.returncode)
48−expected = (stage / 'tests/type-todo-partial/expected.txt').read_bytes()
49−if result.stdout != expected:
50− sys.stderr.writelines(difflib.unified_diff(
51− expected.decode().splitlines(keepends=True),
52− result.stdout.decode().splitlines(keepends=True),
53− fromfile='expected.txt', tofile='actual'))
54− sys.exit('todo partial report differs from expected')
55−print('unchanged todo partial reader report passed')
tools/type-union-alias-overlap-testdeleted−52
@@ -1,52 +0,0 @@
1−#!/usr/bin/env python3
2−"""Check source-backed generic-union overlap witnesses under eval."""
3−from pathlib import Path
4−import argparse
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−parser = argparse.ArgumentParser(description=__doc__)
12−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
13−parser.add_argument('--update', action='store_true')
14−args = parser.parse_args()
15−fixture = root / 'tests/type-union-alias-overlap'
16−source = (root / 'tests/lib/jibb-union-alias-overlap.hoon').read_text()
17−source = source[source.index('\n|%\n') + 1:]
18−names = ['positive', 'negative', 'nonzero', 'multi', 'opaque', 'wrong', 'duplicate', 'qualified', 'flag-source']
19−cords = [item for name in names for item in ('--cord', f'{name}-text={fixture / (name + ".txt")}')]
20−if not args.update:
21− cords += ['--cord', f'expected-text={fixture / "expected.txt"}']
22−bindings = ''.join(f'=/ {name}=wain (to-wain:format {name}-text)\n' for name in names)
23−program = ('=/ jibb .\n' + bindings +
24− ('=/ expected=wain ~\n' if args.update else '=/ expected=wain (to-wain:format expected-text)\n') +
25− '=/ suite\n' + source +
26− '\n=/ output=@t (overlap-output:suite ' +
27− ' '.join(name + '-text' for name in names) + ')\n' +
28− ('output\n' if args.update else
29− "=/ actual-test=tang test-union-alias-overlap:suite\n?~ actual-test output\n'BAD ship test arm'\n"))
30−with tempfile.TemporaryDirectory(prefix='jibb-union-overlap-') as tmp:
31− path = Path(tmp) / 'test.hoon'
32− path.write_text(program)
33− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib, '--raw',
34− '-f', str(path), *cords], stdout=subprocess.PIPE)
35−if result.returncode:
36− sys.exit(result.returncode)
37−if any(line.startswith(b'BAD ') or line.endswith(b': BAD') for line in result.stdout.splitlines()):
38− sys.stderr.write('generic-union guard assertion failed:\n')
39− sys.stderr.buffer.write(result.stdout)
40− sys.exit(1)
41−expected_path = fixture / 'expected.txt'
42−if args.update:
43− expected_path.write_bytes(result.stdout)
44−else:
45− expected = expected_path.read_bytes()
46− if result.stdout != expected:
47− sys.stderr.writelines(difflib.unified_diff(
48− expected.decode().splitlines(keepends=True),
49− result.stdout.decode().splitlines(keepends=True),
50− fromfile='expected.txt', tofile='actual'))
51− sys.exit(1)
52−print('source-backed generic-union overlap guards passed')
tools/type-union-source-testdeleted−55
@@ -1,55 +0,0 @@
1−#!/usr/bin/env python3
2−"""Check source-backed bounded generic-union proofs under eval."""
3−from pathlib import Path
4−import argparse
5−import difflib
6−import subprocess
7−import sys
8−import tempfile
9−
10−root = Path(__file__).resolve().parent.parent
11−parser = argparse.ArgumentParser(description=__doc__)
12−parser.add_argument('--lib', default=str(root / 'jibb-dev/lib/jibb.hoon'))
13−parser.add_argument('--update', action='store_true')
14−args = parser.parse_args()
15−fixture = root / 'tests/type-union-source'
16−source = (root / 'tests/lib/jibb-union-source.hoon').read_text()
17−source = source[source.index('\n|%\n') + 1:]
18−names = ['good', 'same', 'zero', 'nested', 'duplicate', 'wrong', 'duplicate-params', 'hidden-ref', 'qualified', 'direct-source', 'wide-source', 'free-source', 'late-source', 'shadow-source', 'mixed-source']
19−cords = [item for name in names for item in ('--cord', f'{name}-text={fixture / (name + ".txt")}')]
20−cords += ['--cord', f'prelude={root / "jibb-dev/lib/jibb/prelude.jibb"}',
21− '--cord', f'internal={root / "jibb-dev/lib/jibb/internal.jibb"}']
22−if not args.update:
23− cords += ['--cord', f'expected-text={fixture / "expected.txt"}']
24−bindings = ''.join(f'=/ {name}=wain (to-wain:format {name}-text)\n' for name in names)
25−program = ('=/ jibb .\n=/ real-prelude=@t prelude\n'
26− '=/ real-internal=@t internal\n' + bindings +
27− ('=/ expected=wain ~\n' if args.update else '=/ expected=wain (to-wain:format expected-text)\n') +
28− '=/ suite\n' + source +
29− '\n=/ output=@t (source-output:suite prelude internal ' +
30− ' '.join(name + '-text' for name in names) + ')\n' +
31− ('output\n' if args.update else
32− "=/ actual-test=tang test-union-source:suite\n?~ actual-test output\n'BAD ship test arm'\n"))
33−with tempfile.TemporaryDirectory(prefix='jibb-empty-') as tmp:
34− path = Path(tmp) / 'test.hoon'
35− path.write_text(program)
36− result = subprocess.run([str(root / 'tools/hoon'), '--lib', args.lib, '--raw',
37− '-f', str(path), *cords], stdout=subprocess.PIPE)
38−if result.returncode:
39− sys.exit(result.returncode)
40−if any(line.startswith(b'BAD ') or line.endswith(b': BAD') for line in result.stdout.splitlines()):
41− sys.stderr.write('generic-union guard assertion failed:\n')
42− sys.stderr.buffer.write(result.stdout)
43− sys.exit(1)
44−expected_path = fixture / 'expected.txt'
45−if args.update:
46− expected_path.write_bytes(result.stdout)
47−else:
48− expected = expected_path.read_bytes()
49− if result.stdout != expected:
50− sys.stderr.writelines(difflib.unified_diff(
51− expected.decode().splitlines(keepends=True),
52− result.stdout.decode().splitlines(keepends=True),
53− fromfile='expected.txt', tofile='actual'))
54− sys.exit(1)
55−print('source-backed generic-union guards passed')
tools/urbit_eval.py+5−3
@@ -442,12 +442,14 @@ def focus(spots):
442442 return spots[-1] if spots else None
443443
444444
445−def failure_report(prog, res, headline, harness_headline=None):
445+def failure_report(prog, res, headline, harness_headline=None,
446+ keep=('lib', 'expr', 'harness')):
446447 """eval's error output, mapped, with an excerpt of where it points.
447448
448449 harness_headline replaces headline when the error is in the harness:
449− the library compiled, but doesn't fit what the harness expects."""
450− lines, spots = map_trace(prog, res.trace)
450+ the library compiled, but doesn't fit what the harness expects.
451+ keep names the kinds of segment whose frames the trace shows."""
452+ lines, spots = map_trace(prog, res.trace, keep)
451453 lines = fold_repeats(lines)
452454 at = focus(spots)
453455 in_harness = at is not None and at.kind == 'harness'