Browse Source
Two wiring-order holes surfaced during the G-007 interactive verification: 1. Calling ensure_object_integration before opunk::console is loaded errored into the nonexistent namespace (can't set "::opunk::console:: waiting_chunks_arrayvar": parent namespace doesn't exist). It now returns 0 as a graceful no-op without latching object_integration_done, so a later call after opunk::console loads still performs the wiring; the wired/latched path returns 1. 2. 'package require opunk::console; opunk::console::create ...' with no intervening punk::console object operation left the created console without a registered owner: the lifecycle callback that records ownership is only installed by ensure_object_integration, which is wired lazily from punk::console's object-spec paths. Behaviour was unaffected for the owning thread (share qualifiers fall back to the calling thread) but other threads could not address that console's facts. On wiring the callback, ensure_object_integration now retro-registers ownership for anchors already present in the interp - anchors are per-interp/per-thread so the anchoring context is the calling thread. Only empty registry entries are filled; existing live registrations are preserved (and the default console keeps first-registration-wins semantics). Tests: new objectintegration.test covers the no-op return (unlatched), retro-registration of a pre-wiring anchor with lifecycle forget clearing the entry, idempotency of the latched path, and normal post-wiring registration - passing under Tcl 9.0.3 and 8.6. Full suite at baseline (exec-14.3 only). Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.commaster
3 changed files with 125 additions and 1 deletions
@ -0,0 +1,97 @@
|
||||
package require tcltest |
||||
tcltest::configure {*}$::argv |
||||
|
||||
#min-version bound documents that these tests target the dev module's API and protects |
||||
#against stable bootsupport copies shadowing the alpha dev version if this file is sourced outside |
||||
#runtests.tcl (whose testinterp runs 'package prefer latest' making the bound redundant there). |
||||
package require punk::console 999999.0a1.0- |
||||
|
||||
#Tests for punk::console::ensure_object_integration wiring-order behaviour: the graceful no-op |
||||
#when opunk::console is not loaded, and catch-up ownership registration for anchors created |
||||
#before the lifecycle callback was wired. |
||||
#ORDER MATTERS within this file: the first test relies on opunk::console not yet being loaded |
||||
#in this interp (runtests gives each test file a fresh testinterp), and the retro-registration |
||||
#test relies on creating its anchor before the first successful ensure_object_integration. |
||||
|
||||
namespace eval ::testspace { |
||||
namespace import ::tcltest::* |
||||
|
||||
variable common { |
||||
set result "" |
||||
} |
||||
|
||||
tcltest::testConstraint opunk_not_loaded [expr {[catch {package present opunk::console}]}] |
||||
|
||||
test ensure_object_integration_no_opunk {graceful no-op (0, no error, no latch) when opunk::console is not loaded}\ |
||||
-constraints opunk_not_loaded\ |
||||
-setup $common -body { |
||||
lappend result [punk::console::ensure_object_integration] |
||||
#must not have latched - a later call after opunk::console loads must still wire |
||||
lappend result [set ::punk::console::object_integration_done] |
||||
}\ |
||||
-cleanup {}\ |
||||
-result [list\ |
||||
0\ |
||||
0\ |
||||
] |
||||
|
||||
test ensure_object_integration_retro_registration {anchor created before wiring gains a registered owner when ensure_object_integration wires the callback}\ |
||||
-setup $common -body { |
||||
package require opunk::console |
||||
lassign [chan pipe] rd wr |
||||
#create BEFORE integration wiring - lifecycle callback is empty so no 'created' |
||||
#event fires and no owner is registered (the wiring-order hole) |
||||
opunk::console::create preintegration $rd $wr |
||||
lappend result [punk::console::console_owner_get [list $rd $wr]] |
||||
#wiring performs the catch-up registration for the pre-existing anchor |
||||
lappend result [punk::console::ensure_object_integration] |
||||
lappend result [expr {[punk::console::console_owner_get [list $rd $wr]] eq [thread::id]}] |
||||
#lifecycle callback is now wired - forget clears the entry as usual |
||||
opunk::console::forget preintegration |
||||
lappend result [punk::console::console_owner_get [list $rd $wr]] |
||||
}\ |
||||
-cleanup { |
||||
catch {opunk::console::forget preintegration} |
||||
catch {punk::console::console_owner_forget [list $rd $wr]} |
||||
catch {chan close $rd} |
||||
catch {chan close $wr} |
||||
}\ |
||||
-result [list\ |
||||
{}\ |
||||
1\ |
||||
1\ |
||||
{}\ |
||||
] |
||||
|
||||
test ensure_object_integration_idempotent {second call is a latched no-op returning 1}\ |
||||
-setup $common -body { |
||||
lappend result [punk::console::ensure_object_integration] |
||||
lappend result [set ::punk::console::object_integration_done] |
||||
}\ |
||||
-cleanup {}\ |
||||
-result [list\ |
||||
1\ |
||||
1\ |
||||
] |
||||
|
||||
test ensure_object_integration_create_after_wiring {anchor created after wiring registers via the lifecycle callback (no retro path involved)}\ |
||||
-setup $common -body { |
||||
lassign [chan pipe] rd wr |
||||
opunk::console::create postintegration $rd $wr |
||||
lappend result [expr {[punk::console::console_owner_get [list $rd $wr]] eq [thread::id]}] |
||||
opunk::console::forget postintegration |
||||
lappend result [punk::console::console_owner_get [list $rd $wr]] |
||||
}\ |
||||
-cleanup { |
||||
catch {opunk::console::forget postintegration} |
||||
catch {punk::console::console_owner_forget [list $rd $wr]} |
||||
catch {chan close $rd} |
||||
catch {chan close $wr} |
||||
}\ |
||||
-result [list\ |
||||
1\ |
||||
{}\ |
||||
] |
||||
|
||||
} |
||||
tcltest::cleanupTests ;#needed to produce test summary. |
||||
Loading…
Reference in new issue