ctest reports zero skips: delete the Docker-based SSH integration test, bind term_mapping to product code (vms-97d) - #9
Merged
Merged
Conversation
The Docker-based SSH integration test (test_vmsssh.sh, vmsssh_integration
ctest target, test_ssh_client.c) tested only the dead Docker runtime
(CLAUDE.md Rule 9) for a server ruled a show horse and cancelled (vms-02d,
2026-07-30). It was also a local-only phantom: CI never installs libssh, so
it never even registered there. Locally it registered and skipped
(SKIP_RETURN_CODE 77), and a skip reads as coverage it does not provide
(CLAUDE.md Rule 10).
Deleted:
- tests/vmsssh/test_vmsssh.sh (Docker-based integration script)
- tests/vmsssh/test_ssh_client.c (libssh test client, only a harness for
the deleted integration test)
- the vmsssh_integration ctest registration and its libssh gating in
tests/vmsssh/CMakeLists.txt
Kept:
- tests/vmsssh/test_term_mapping.c / term_mapping ctest target — a
genuine unit test of TERM -> VMS device type mapping with no libssh
dependency, unrelated to the deleted integration test; terminal
fidelity remains a live Phase 3 concern. tests/vmsssh is now added
unconditionally under BUILD_TESTS in the root CMakeLists.txt so this
test always builds and runs, never gated on libssh.
- src/vmsssh/vmssshd.c (the daemon source) — retained per item scope for
a possible future revival. Its libssh gate in the root CMakeLists.txt
is unchanged (the daemon itself genuinely needs libssh to link); only
its test surface is removed.
Verified both configurations: with libssh installed, ctest goes from 40
tests/1 skip to 39 tests/0 skipped/0 failed. With LIBSSH_INCLUDE_DIR and
LIBSSH_LIBRARY forced to -NOTFOUND (simulating libssh absent without
touching the shared host package), src/vmsssh is correctly skipped
("libssh not found — vmssshd will not be built") while tests/vmsssh still
configures and term_mapping still builds and passes.
Co-Authored-By: Claude Sonnet 5 (implementer) <noreply@anthropic.com>
Veracity re-dispatch on vms-97d found two defects in the kept unit test:
1. tests/vmsssh/test_term_mapping.c #included a hand-maintained COPY of
map_term_to_vms_device_type() instead of the real vmssshd.c function
-- the classic mock-away-the-thing-under-test bug. Any future edit to
the product function left the test green.
2. The kept device-type strings ("VT100"/"VT200"/"VT300"/"VT400") and the
TERM->family mapping were asserted with no oracle citation, in
violation of Rule 10 (self-certified VMS-facing values are illegal;
green CI is not evidence of VMS correctness).
Fix, per the orchestrator ruling's option (a):
- Extracted the mapping into src/vmsssh/term_map.c + term_map.h, a
dependency-free translation unit outside the libssh gate. vmssshd.c
now calls the shared vmsssh_map_term_to_device_type() instead of
defining its own static copy.
- tests/vmsssh/test_term_mapping.c now compiles and links
src/vmsssh/term_map.c directly -- it exercises the real product code,
and a drift in term_map.c now fails the test.
- term_map.h/.c and the test file carry an explicit Rule 8/Rule 10
label: the mapping is an OVMX design choice, NOT a reproduction of
documented OpenVMS behavior. OpenVMS sets terminal device type via SET
TERMINAL/DEVICE_TYPE and renders $TTDEF values as e.g.
"VT400_Series" via SHOW TERMINAL; it has no mechanism that infers a
device type from a Unix TERM string. No VMS-fidelity claim is made or
tested -- only internal consistency of the OVMX heuristic.
Verified both configurations from a clean build:
- WITH libssh (host has libssh-dev): ctest = 39/39 passed, 0 skipped.
VMSSSHD.EXE links term_map.c.o; test_term_mapping links the same TU.
- WITHOUT libssh (cache-forced -DLIBSSH_INCLUDE_DIR/-DLIBSSH_LIBRARY
=-NOTFOUND, no host mutation): "libssh not found -- vmssshd will not
be built" fires, no VMSSSHD.EXE is produced, and ctest still reports
39/39 passed, 0 skipped -- term_mapping builds and runs unconditionally.
Does not reopen the settled deletion of test_vmsssh.sh /
vmsssh_integration / test_ssh_client.c from the prior commit on this
branch (cc88896) -- that result was accepted by the orchestrator ruling
and is untouched here.
vms-97d
baron-3dl
added a commit
that referenced
this pull request
Aug 13, 2026
…ee head must be pointer-width (#463) MMK.EXE SIGSEGV'd in the guest before sp_open (post-parse/pre-drive), nondeterministically and only with a real executive. Prior work (vms-b23 #462) characterized it via a SIGSEGV handler but lacked a real backtrace. Root cause (real backtrace, this commit): a 64-bit pointer-width bug. objects.c declares the LIB$*_TREE root cell as `static unsigned int objtree` — 4 bytes. On the VAX a longword IS a pointer so stock MMK is correct; on a 64-bit OVMX target that cell is too small. lib$insert_tree / lib$lookup_tree take the head by reference and dereference it as a full 8-byte pointer, so they: - over-READ 8 bytes of a 4-byte global (the adjacent global's 4 bytes become the high half of a bogus root pointer), and - on insert, over-WRITE, truncating the stored root node address. The reconstructed garbage pointer is later dereferenced -> SIGSEGV. Whether it faults depends on address-space layout, which is exactly why it was nondeterministic and "executive-dependent" (the executive changes the heap layout); on the host the reconstructed pointer happened not to fault, so MMK reached sp_open cleanly. Pinned with a real backtrace via ASan on the host mmk_native ELF, run with the identical input the guest capstone uses (VMS_FOREIGN_CMD="/DESCRIPTION=OVMXB23.MMS OVMXB23.OUT"): ERROR: AddressSanitizer: global-buffer-overflow ... READ of size 8 #0 lib$lookup_tree src/libvms/rtl/lib_tree.c:108 #1 Find_Object tests/corpus/tier3-mmk/objects.c:102 #2 make_objrefs tests/corpus/tier3-mmk/parse_descrip.c:1135 #3 parse_store tests/corpus/tier3-mmk/parse_descrip.c:1051 #4 act_prs tests/libvms/mmk_parse_tables.c:85 ... lib$table_parse -> parse_descrip -> Read_Description #9 main tests/corpus/tier3-mmk/mmk.c:705 0 bytes after global variable 'objtree' (size 4) Fix: declare objtree pointer-width (`void *`), matching symbols.c's apply_sort() `void *tree` and the LIB$ manual's quadword tree head on 64-bit architectures. After the fix ASan is clean on the same input and MMK proceeds through the object tree to the drive (sp_open). Clean-room (Rule 8): objects.c is stock MadGoat freeware; the one-line width change is an OVMX portability fix, tagged inline. Proof: - ASan before: global-buffer-overflow at lib_tree.c:108 (above). - ASan after: clean; MMK reaches the drive (same as host baseline). - toolchain-mmk-parse ctest: PASS (no host regression). - build-static (musl) mmk_native: builds clean. Co-authored-by: alice <alice@workspace.local> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
baron-3dl
added a commit
that referenced
this pull request
Aug 17, 2026
The zero-match-glob hard-fail added to overlay-ovmx-drivers.sh (previous commit) correctly aborts when a sources.conf glob stages nothing -- but it exposed a STALE scaffold in tests/integration/test_ovmx_module_home.sh. The demonstrator sub-test builds a scratch repo ($WORK/repo) that copies distro/kernel/drivers- ovmx (so vmsfs's sources.conf now carries the src/vmsfs/ods2/*.c codec glob) plus src/kernel + src/kernel-core, but NOT src/vmsfs. The codec glob then matched nothing and the new guard aborted the overlay, cascading the demonstrator's ovmxdemo-wiring assertions (ovmx_module_home_gate, Build & Test #9). Fix mirrors the real distro/Dockerfile.bootable change: the scratch repo now also stages src/vmsfs (carrying src/vmsfs/ods2/ + src/vmsfs/include/vmsfs/ods2.h), the same tree the kernel-build stage COPYs into its overlay context. vmsfs's codec glob matches, the overlay runs clean, and the demonstrator tests its actual concern (a new drivers-ovmx/<mod>/ subdir wires itself in) without tripping the guard. The guard is NOT weakened and vmsfs is NOT special-cased -- the test's scaffold was simply stale relative to the Dockerfile change. Verified via the ctest wrapper this time (not just the script): ctest -R ovmx_module_home_gate -> 1/1 Passed module-home gate: 29 passed, 0 failed (demonstrator + ovmxdemo assertions all green) Rung of epic vms-208 (Files-11 ODS-2 ACP in the executive). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
baron-3dl
added a commit
that referenced
this pull request
Aug 17, 2026
…c (unblocks ACP boot) (#645) * vms-4a8: bootable-image vms.ko carries the kernel-resident ODS-2 codec The bootable vmsfs.ko is built by the in-tree drivers/ovmx/ overlay, which FLATTENS all module sources to basenames. The genuine ODS-2 codec was absent there: its sources #include the public header by a SUBDIR path ("vmsfs/ods2.h"), which the basename-flatten model could not resolve, so the overlay Kbuild left -DOVMX_ODS2_KERNEL undefined and dropped the codec objects (vms-dcd's tracked follow-up). The shipped module therefore could not read a genuine ODS-2 volume. Make the flatten subdir-safe, additively: - overlay-ovmx-drivers.sh: a sources.conf line may now use `<glob> -> <subdir>/` to stage matched files UNDER the module dir's <subdir>/ instead of at the flat root. Lines without `->` flatten to basenames exactly as before -- the convention is purely additive and touches no other module. - vmsfs/sources.conf: stage the codec (src/vmsfs/ods2/*.c,*.h) and stage the public header preserving its path: `src/vmsfs/include/vmsfs/ods2.h -> vmsfs/`, so #include "vmsfs/ods2.h" resolves via -I$(src) in the flat dir. - vmsfs/Kbuild: add the codec objects (ods2_reader/writer/bdev/path/block_kern + vmsfs_ods2ro) and define -DOVMX_ODS2_KERNEL, so the OVMX_ODS2_KERNEL gate in vmsfs_super.c (vmsfs_ods2ro_register) now resolves -- no dangling symbol. - Dockerfile.bootable: add binutils and an nm proof that the shipped vmsfs.ko carries vmsfs_ods2ro_register + ods2_* (codec-compiled-in gate). ADDITIVE: this makes the shipping module CARRY the codec; it does NOT flip the boot default or mount SYS$DISK via the ACP (the atomic-flip / boot rung). Codec source and Kbuild object list are untouched, so the out-of-tree (src/kernel/vmsfs/Makefile), userspace, Alpha (build-vmsko-alpha.sh) and VAX (build-vms-module-vax.sh) builds keep their include paths. Alpha/VAX peers should re-run their cross-builds as a heads-up. Proof: staged the overlay into a fabricated kernel tree and built the FLAT layout against real kernel headers with the real Kbuild + -DOVMX_ODS2_KERNEL -- modpost clean (no undefined ods2_/vmsfs_ods2ro symbols) and nm shows vmsfs_ods2ro_register + ods2_bdev_finish_open + ods2_wvolume_append_file in the produced vmsfs.ko. Module-home gate 29/29; out-of-tree vms.ko + vmsfs.ko green. Rung of epic vms-208 (Files-11 ODS-2 ACP in the executive). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * vms-4a8: stage codec into the REAL Dockerfile kernel-build context + fail-loud on empty glob The prior commit made the OVERLAY stage the ODS-2 codec, and proved it against a fabricated kernel tree fed the FULL repo as REPO. But the real bootable build (distro/Dockerfile.bootable, `kernel-build` stage) hands the overlay a REPO -- /tmp/ovmx-src -- assembled from only two COPYs: src/kernel and src/kernel-core. src/vmsfs was never copied, so the codec globs (src/vmsfs/ods2/*.c and the public header src/vmsfs/include/vmsfs/ods2.h) matched NOTHING in the real build. The overlay merely WARNed (n stayed >0 from the src/kernel globs), the codec .c files never staged, and the in-tree kernel build died with make: *** No rule to make target 'drivers/ovmx/vmsfs/ods2_reader.o' -> no bootable image -> every boot/e2e gate red. The fabricated-tree modpost proof could not see this because it was given the whole repo, not the Dockerfile build context (the #623-class in-tree blind spot). Two fixes: - Dockerfile.bootable (kernel-build stage): COPY src/vmsfs into /tmp/ovmx-src before the overlay runs, so the codec sources + the subdir'd public header are present in the exact REPO the overlay flattens from. - overlay-ovmx-drivers.sh: a sources.conf glob that matches ZERO files is now a hard FAIL, not a WARN. A glob naming files that aren't in the build context silently drops objects the Kbuild requires; failing loudly at overlay time -- with the offending glob and REPO named -- turns a cryptic downstream "No rule to make target" into an immediate, legible error. This is the guard that would have caught the miss above at CI overlay time. Verified: overlay against a REPO lacking src/vmsfs now FAILs with "sources.conf glob 'src/vmsfs/ods2/*.c' ... matched no files"; against the full repo it stages all 6 codec objects and the vmsfs/ods2.h header and completes. Real `docker build --target kernel-build` proof appended below. Rung of epic vms-208 (Files-11 ODS-2 ACP in the executive). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * vms-4a8: kernel-resident codec — cut ods2_wvolume_dir_insert stack frame under 2KB The real Dockerfile kernel-build (previous commit unblocked staging) then surfaced a genuine in-kernel error the userspace/fabricated builds never see: ods2_writer.c: In function 'ods2_wvolume_dir_insert': error: the frame size of 3288 bytes is larger than 2048 bytes [-Werror=frame-larger-than=] The function put ~2.6KB of scratch on the stack -- hdr[512] + hdr_parsed(512) + newrec[512] + lbns[256]*4(1024) -- fine in userspace, but over the kernel's 2048-byte per-frame limit (the kernel stack is a few pages, and this is a leaf of the ACP call chain). An -O2 userspace sweep with -Wframe-larger-than=2048 confirmed this is the ONLY codec function over the limit. Fix (behaviour-identical): bundle those four buffers into ONE heap block, struct di_scratch, allocated through the codec's existing allocator seam (ods2_kzalloc -> kvmalloc in-kernel, malloc in userspace -- the same seam `flat` already uses), and free it once at a new single `done:` exit. Every post-allocation return became `goto done`; `flat`'s own frees fold into the same label (guarded + NULLed so the free is idempotent, no double-free on the success path). The four pre-allocation argument-check returns keep returning directly (nothing to free yet). No on-disk bytes or control decisions change -- only where the scratch lives. Verified: gcc -O2 -Wall -Wextra -Wframe-larger-than=2048 on ods2_writer.c is now clean (no frame warning, no warnings). Host ods2 ctest + real docker kernel-build proof below. Rung of epic vms-208 (Files-11 ODS-2 ACP in the executive). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * vms-4a8: kernel-resident codec — fix bd_inode removal for kernel 6.12 (bdev_nr_bytes) With the frame-size fix in, the real Dockerfile kernel-build (6.12.103) advanced past the codec objects to vmsfs_ods2ro.c and hit the next genuine in-kernel break: vmsfs_ods2ro.c:387: error: 'struct block_device' has no member named 'bd_inode' The 6.x block layer removed 'bd_inode' from the public struct block_device (the bdev inode moved out of the struct). ods2ro_fill_super() used i_size_read(sb->s_bdev->bd_inode) purely to read the backing device's size in bytes. Replace it with bdev_nr_bytes(sb->s_bdev) -- the supported device-size accessor (linux/blkdev.h, present since 5.16), same byte count -- and include <linux/blkdev.h> explicitly rather than lean on a transitive include. More portable than before, not less: bdev_nr_bytes() spans 5.16..6.12+, so this also builds under the out-of-tree QEMU harness (src/kernel/vmsfs/Makefile) and the Alpha/VAX cross-builds, which compile the same file. A scan of the rest of vmsfs_ods2ro.c (mount_bdev / iget_locked / sb_set_blocksize / kill_block_super / register_filesystem) shows every other API unchanged in 6.12; the codec .c objects already compiled clean in the prior build. Real kernel-build proof to follow. Rung of epic vms-208 (Files-11 ODS-2 ACP in the executive). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * vms-4a8: stage src/vmsfs in the module-home gate demonstrator scaffold The zero-match-glob hard-fail added to overlay-ovmx-drivers.sh (previous commit) correctly aborts when a sources.conf glob stages nothing -- but it exposed a STALE scaffold in tests/integration/test_ovmx_module_home.sh. The demonstrator sub-test builds a scratch repo ($WORK/repo) that copies distro/kernel/drivers- ovmx (so vmsfs's sources.conf now carries the src/vmsfs/ods2/*.c codec glob) plus src/kernel + src/kernel-core, but NOT src/vmsfs. The codec glob then matched nothing and the new guard aborted the overlay, cascading the demonstrator's ovmxdemo-wiring assertions (ovmx_module_home_gate, Build & Test #9). Fix mirrors the real distro/Dockerfile.bootable change: the scratch repo now also stages src/vmsfs (carrying src/vmsfs/ods2/ + src/vmsfs/include/vmsfs/ods2.h), the same tree the kernel-build stage COPYs into its overlay context. vmsfs's codec glob matches, the overlay runs clean, and the demonstrator tests its actual concern (a new drivers-ovmx/<mod>/ subdir wires itself in) without tripping the guard. The guard is NOT weakened and vmsfs is NOT special-cased -- the test's scaffold was simply stale relative to the Dockerfile change. Verified via the ctest wrapper this time (not just the script): ctest -R ovmx_module_home_gate -> 1/1 Passed module-home gate: 29 passed, 0 failed (demonstrator + ovmxdemo assertions all green) Rung of epic vms-208 (Files-11 ODS-2 ACP in the executive). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the phantom-skip defect in
vms-97d, first item of thevms-14fswarm to clear veracity.What changed
tests/vmsssh/test_vmsssh.sh(it randocker info, built the ROOT Dockerfile and SSHed into the container — i.e. it tested the dead Docker runtime, forbidden as a runtime by Rule 9) and itsvmsssh_integrationregistration, plustest_ssh_client.cwhich was only that script's harness.test_term_mapping. It was a copy ofmap_term_to_vms_device_type()pasted into the test file — nothing bound the two, so any edit tovmssshd.cwould have left it green. The function is now extracted tosrc/vmsssh/term_map.{c,h}and both the product daemon and the test use it.Verification
ctestwith libssh headers present (the configuration that previously skipped): 39/39 passed, 0 failed, 0 skipped. Baseline was 40 tests / 1 skip; the delta is exactly the removedvmsssh_integration.git archive.Notes
src/vmsssh/vmssshd.cis retained — only the Docker-runtime test surface was removed. Un-oracled VMS device-type assertions (VT100/VT400, and the xterm→VT inference, which has no OpenVMS analogue) were not promoted into CI; real terminal device types are owned byvms-d0b.🤖 Generated with Claude Code