You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

16 KiB

src/tests/modules — Source Module Test Suites

Purpose

Unit tests for editable source modules under src/modules/, src/modules_tcl8/, and src/modules_tcl9/. These tests use tcltest and run against the uninstalled source tree through src/tests/runtests.tcl.

Ownership

  • Agents should add or update tests here when changing module behavior in src/modules/ or Tcl-version-specific module trees.
  • Installed-module test packages under src/modules/test/ are packaging artifacts and are not the default place for source-tree behavior tests.
  • Do not delete, skip, or weaken existing tests without explicit user direction.

Local Contracts

  • The directory hierarchy mirrors module namespace paths, such as src/tests/modules/punk/args/ for punk::args.
  • Test files use .test extension and must package require any extra packages explicitly.
  • Test files must end with tcltest::cleanupTests so src/tests/runtests.tcl can produce trusted aggregate counts.
  • Test files may commonly use line-continuation backslashes, and existing Tcl expand-syntax structures in tests should not be refactored into line continuations.
  • Tests must exercise source modules as loaded by src/tests/runtests.tcl, not installed or built output modules.
  • testsuites/dev/ may hold known-bug or expected-fail tests; guard them with disabled tcltest constraints so standard source-tree runs skip them by default.

Work Guidance

  • Put new module tests under src/tests/modules/<namespacepath>/testsuites/<suite>/ following nearby layout.
  • For efficient agent runs, use -report compact -show-passes 0 and include the narrowest namespace path plus file tail when known.
  • Prefer try { ... } on error {result options} { ... } for structured error capture in test bodies.
  • Focused verification should mirror production pipelines inside tests using Punk pipeline syntax when that parity matters.
  • Capture enough stderr or failure context to identify the failing command or assertion.

Verification

  • Run targeted module tests with <tcl_interpreter> src/tests/runtests.tcl -report compact -show-passes 0 -include-paths modules/<namespacepath>/**.
  • Run a single test by name with <tcl_interpreter> src/tests/runtests.tcl -report compact -show-passes 0 -tcltestoptions {-match <test_name>} -include-paths modules/<namespacepath>/**.
  • Run a specific test file by adding its file tail, such as <tcl_interpreter> src/tests/runtests.tcl -report compact -show-passes 0 -include-paths modules/punk/args/** parsekey.test.
  • Use -report markdown+json when both detailed human-readable failure sections and a structured summary are useful.
  • If a compact result shows reason=missing-cleanupTests, add the missing tcltest::cleanupTests before trusting observed pass events.

Child DOX Index

  • opunk/console/ — ::opunk::Console backend subclass tests (testsuites/console/backends.test, G-001): virtual dispatch of subclass overrides through base-class calls and punk::console::console_spec_resolve (both unchanged), TestConsole determinism + probe-free at_eof, SshConsole capability/eof + the flagship size-via-ANSI-query-over-socket case (a scripted remote terminal answers CSI 6n), TkConsole widget size/eof (gated behind env PUNK_TEST_TK=1 - Tk in the shared testinterp has side effects; also verifiable standalone under a tk-capable kit e.g punk91 src <script>)
  • punkcheck/ — punkcheck module tests (install, summarize_install_resultdict, installtrack)
  • punk/ansi/ — punk::ansi tests (testsuites/ansi/): ansistrip/ansimerge, plus characterization of the ANSI-at-position mechanisms (ansistring.test: INDEX/INDEXCODE/INDEXCHAR/RANGE/INSERT grapheme indexing with SGR-prefix merging, INDEXCOLUMNS/COLUMNINDEX double-wide column mapping, trim/VIEW), code splitting invariants (ta.test: detect/detectcode distinction, split_codes/split_codes_single/split_at_codes shapes and round-trip) and single-code/effective-state semantics (codetype.test: is_sgr_reset/has_sgr_leadingreset, has_any/all_effective, sgr_merge, sequence_type classify), grepstr characterization (grepstr.test: return modes incl summarydict (linemap pinned as always-present - the -help says -n-only, reconciliation deferred to the planned hygiene pass), exact highlight SGR wrapping, -n line numbering, invert + empty-highlight strip, -C context/breaks, capture groups, and the tab deficiency: warns once per call on stderr, single-pass tab line survives - the multi-pass mangling is pinned at consumer level in punk/ns corp.test), and untabify characterization (untabify.test: -stops int/list/terminal, -with spaces/unicode/custom-pair, multiline, errors, plus the EXPERIMENTAL -plastic elastic-tabstop mode deliberately pinned-as-interim and retained for possible repl editbuf use). Console queries (get_tabstops/get_size + punk::console::tabwidth) are mocked per the overtype renderline.test pattern - they emit live terminal queries that block/error headless. ANSI codes in these tests are literal escape strings so results are colour-state independent
  • punk/args/ — punk::args tests (testsuites/args/): parsing, choices/choicegroups, forms, rendering/indentation characterization, synopsis display characterization (synopsis.test: basic italic argname/<type> styling, longopt --x= alias forms, literal/literalprefix/stringstartswith/stringendswith type-alternates rendering unitalicised, option alternate parenthesization, multi-element clause display incl ?type? members and argname tail-word hints, -typesynopsis value-element lists and option passthrough incl documenter ANSI, and the small-restricted-choice-set literal rule: 1-3 restricted choices render as unitalicised |-joined literals in leader/option/value positions with choicegroups counted, >3 or -choicerestricted 0 falling back to italics, -typesynopsis taking precedence), usage-marking characterization (usagemarking.test: -parsedargs/-badarg/-parsestatus/-scheme marking primitives plus goodchoice highlighting of selected/default-in-effect choice words, asserted by SGR-parameter subset against the live colour arrays; the G-049 nocolour/colour-leak GAP pins flipped 2026-07-10 to scheme-statelessness assertions), the G-049 parse-status structure (parsestatus.test: punk::args::parse_status overall/per-argument statuses, badarg for type/allocation failures, -caller attribution, errorcode -argspecs stripping), -parsekey characterization (parsekey.test: result/received/solos/multis keying, shared-key required satisfaction and defaults, mash-path and prefix-abbreviation keying, plus GAP pins for last-defined-member default precedence, cross-member -multiple value loss, parsekey/optname collision conflation, and values/leaders parsekey breakage - desired-behaviour pins disabled behind punkargsKnownBug in testsuites/dev/parsekey-knownbugs.test), and tclcore doc/interpreter behavioural parity (tclcoreparity.test, G-054, gated on have_tclcoredocs: 'string is' class choices equal the live-harvested set, per-class docids exist, error-vs-ok agreement across the probe matrix, version-note labels conditional on class presence - expectations derived from the running interpreter, green on 8.6/8.7/9.0; under 8.6 run the file directly via a plain tclkit + tcltest driver since runtests' harness needs newer infrastructure)
  • punk/nav/ns/ — punk::nav::ns tests (testsuites/nav/navns.test): the n/ n// n/// navigation state machine (ns/ transitions absolute/relative/glob-no-nav, failed-nav state preservation, quad-colon normalization, v-form content selection, ensemble annotation) and the ::punk::nav::ns::ns_current variable contract the repl/codethread/subshell seeding all consume; display content is covered in punk/ns nslist.test
  • punk/repl/ — punk::repl tests (testsuites/repl/): opunk console backend integration (consolebackends.test) and repl current-namespace retention (nscurrent.test: real codethread via repl::init driven by synchronous runscript sends - inscope evaluation of ns_current, retention across submissions, n/-navigation retained, auto-create-with-notice for missing namespaces, the 2026-07-14 stray-namespace seeding fix pinned behaviourally plus a source-text guard on repl::start's inline template; the end-to-end piped subshell session is covered at shell level by shell/testsuites/punkexe/shellnavns.test - which found the first-subshell shared-code-interp asymmetry and the piped-inscope gap recorded there)
  • punk/ns/ — punk::ns tests (testsuites/ns/): cmdwhich/cmdinfo/cmd_traverse doc-lookup flow (cmdflow.test, G-040 parity), n/ display machinery characterization (nslist.test: tier A get_ns_dicts classification buckets as the machine contract for display reworks - incl package tail/prefix derivation, alias edge cases, usageinfo scan-dependence; tier B per-element layout-agnostic marking - underline/underdouble/underdotted namespace package styles, command type tag colours, exported/imported markers, the punkargs doc icon; tier C REWORK-flagged pins of the current hardcoded 2-col/4-col layout and nspath subtables, to flip deliberately with the planned punk-tables/width-responsive rework; plus the KNOWN QUIRK pin that bare nslist without -types errors with a malformed message), corp proc-retrieval and syntax/untabify interplay (corp.test: name edge cases, -ranges/-n line handling, basic-highlight ansistrip equivalence, -untabify spaces/unicode tab-free output, the KNOWN-DEFICIENCY pin for default -untabify none on tabbed bodies - grepstr warns per pass and brace overlays mangle tabbed lines, deterministic under mocked console tabstops - and a ::tcl::CopyDirectory -untabify spaces smoke test; precursor coverage for the planned punk::ns hygiene pass), cmdtrace characterization (cmdtrace.test: -pause 0 non-interactive runs, linedict line-mark keys for flat and 2-word-form nested switches as correct-mark guards, and GAP pins for the upstream nested-switch mismark - core.tcl-lang.org tktview 5d5b1052280c976ea3d4, arm bodies whose split-list index lands on a literal switch-command word report container-relative lines; mark tests gated on have_tclcoredocs because cmdtrace's arm-offset correction parses against the ::switch argdoc; plus the fixed-canary asserting punk::lib::check::has_tclbug_nestedswitch_tracelines still reports the bug - a live behavioural probe, so a fixed Tcl release fails the canary first and triggers the documented flip workflow), cmdhelp usage-rendering integration (cmdhelp.test: scheme selection, goodarg/badarg marking incl type/allocation failures, goodchoice highlighting of supplied/default choice words, alias path, cmdinfo result shape, queried-command failure attribution, and -return dict parse-status returns (G-049 - its GAP pins flipped 2026-07-10); remaining GAP pins for pseudo-command cmdtype + space-form docid prefixes (G-051, real string is pins behind the have_tclcoredocs constraint), TclOO undocumented-method fallback (G-052), and synopsis marking absence (G-050)), and name/path primitive characterization (nsprimitives.test: string pins for nsparts/nsprefix/nstail/nsjoin/nsjoinall incl weird colon-run (:::) splitting, the trailing-colon parse ambiguity (::x: + y joins to the same string as ::x + :y and reparses leading-colon-greedy), prefix/tail/join round-trip and its absolutizing exceptions, and divergence pins showing the nsparts1/nsprefix1/nsprefix_orig/nstail1/nstail_orig twins are NOT drop-in equivalents (safe-deletion evidence for the planned hygiene pass); plus nseval fq-requirement/create-on-eval/evaluator-proc caching, the native-vs-punk p:::x resolution divergence (native namespace eval reaches child x, nseval creates/reaches literal :x), nseval_ifexists no-create + error propagation on plain and genuinely weird namespaces, nsexists/nschildren/nstree_raw weird-ns and relative-resolution pins, globmatchns */**/? semantics (incl * matching a single inner colon - the 'should be fixed' comment above nsglob_as_re is stale), and nspath_to_absolute/nspath_here_absolute caller-resolution pins; known warts recorded in-test for the pass: nsjoinall error message prefixed 'nsjoin:')
  • punk/mix/ — punk::mix::cli tests (prune helpers, punkcheck virtual sources), punk::mix::commandset::repo fossil move/rename characterization tests (testsuites/repo/, FOSSIL_HOME-isolated; GAP-marked tests pin behaviour G-022 will change), punk::mix::commandset::loadedlib tests (testsuites/loadedlib/libsearch.test: 'dev lib.search' match semantics via -return list — wrap-glob default, =exact prefix, case rules, explicit globs, version aggregation — plus the loadedlib 0.2.0 contract: deep discovery by default (deep .tm modules found without -refresh, registration persists), -refresh = genuine re-scan (epoch incr + rediscovery picks up .tm files added to already-scanned dirs), and highlight working without the shell-global a+ alias; shared provisioned child interp sourcing the source-tree libunknown directly — see the file's ORDERING NOTE), and the MULTISHELL polyglot build machinery (testsuites/scriptwrap/multishell.test: scriptset wrap via the punk.multishell.cmd template - structure/LF-only/determinism, checkfile 512-byte label validation of fresh wraps AND the committed bin/runtime.cmd, the runtime scriptset round-trip byte-identity pin, and platform-gated execution smoke: cmd.exe→powershell payload on windows, sh payload on unix or via the wsllinux capability constraint from src/tests/testsupport/wslprobe.tcl - staged to the WSL distro's native filesystem, G-059)
  • punk/lib/ — punk::lib tests (testsuites/lib/): range/index/parse/compat/interp_sync utilities, G-058 static-baseline seeding (staticseed.test: interp_sync_package_paths/snapshot_package_paths propagate a simulated ::punkboot static baseline and seed load {} <prefix> ifneeded mappings; no-op without a baseline), and the repl command-completeness engine (commandcomplete.test: punk::lib::system::incomplete pending-opener stacks - the info-complete quoting quirk progression (set x "{*}{" standalone vs in-proc-body), single openers, tabs, escapes, incomplete<->info-complete parity property; pre-repl-refactor characterization, see goals/G-044 detail preserve-list)
  • punk/packagepreference/ — punk::packagepreference tests (testsuites/packagepreference/): G-058 static-vs-bundled policy (staticpolicy.test: require of a baseline package triggers the index scan before resolution so a newer bundled copy wins, static beats older bundled, exact requires of bundled versions stay reachable, missing static mappings get seeded)
  • punk/libunknown/ — .tm same-version shadowing pin-tests (testsuites/shadowing/): tcl::add prepend rule, head-of-tm-list wins exact-version ties, version beats order, punk::libunknown parity — shipped behaviour depends on these (runtests tm ordering, punk_main package-mode precedence, G-033); mixed .tm/pkgIndex.tcl characterization is goal G-035; discovery/epoch-cache characterization (testsuites/discovery/discovery.test): sibling .tm registration happens only at the requested namespace depth (deeper modules invisible to 'package names' until requested), register_all_tm deep discovery (all-depths registration, per-epoch cached no-op, head-of-tm-list precedence parity), 'package epoch' command shape, trace-driven epoch increments on tm/auto_path changes, the epoch-index short-circuit (a .tm added to an already-scanned dir needs 'package epoch incr'), and the pkgIndex.tcl sourcing-scope contract (source_pkgindex, fixed 2026-07-11 - formerly a GAP pin of the global-'dir' clobber): user global 'dir' survives pkg-unknown fallthrough, index scripts see $dir and reach the real ::auto_path (tcllib extension pattern), and their stray unqualified sets no longer leak to ::. Suite conventions learned the hard way: child probes source the SOURCE-TREE libunknown directly by path — 'package require punk::libunknown' tie-breaks the same-version copies (src/modules vs bootsupport) by tm path order, which favours bootsupport in the testinterp and machine env paths in children; and probe scripts must avoid global variable names the handlers use (notably 'dir') — that clobbering misdirected a fixture write into the real Tcl install during test development