DRAFT (do not merge): Phase 1 — plugin test harness in src/Testing/ - #2
Draft
detain wants to merge 6 commits into
Draft
DRAFT (do not merge): Phase 1 — plugin test harness in src/Testing/#2detain wants to merge 6 commits into
detain wants to merge 6 commits into
Conversation
Bootstrap::init() + fakes + ConstantStub so plugin handlers can actually execute under test. Never shipped to master (D6): 69 repos track dev-master. Key design point, verified by spike rather than assumed: the installer's autoload.files already defines get_module_db/get_service_define/ function_requirements/get_module_settings into production, so a function_exists-guarded stub of those names is dead code. Three of the four are pure delegations to \MyAdmin\App, so aliasing FakeApp into that name makes the real, unmodified installer functions work against the fakes. The fourth reads $GLOBALS['modules'], which register_module() populates. D2 tripwire test included and mutation-verified: adding a src/Testing/ path to autoload.files turns the suite red.
Implicitly nullable parameter types are deprecated in PHP 8.4; 12 fake constructors used 'CallLog $log = null'. Explicit '?CallLog' is valid from 7.1 so the >=7.4 floor is unaffected.
Brings the two pre-existing CI failures' fixes onto the harness branch so PR #2's matrix reflects the harness alone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <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.
Opened solely to run the 8.2 / 8.3 / 8.4 CI matrix. Per decision D6 of
plugin_plan.md, merge tomasteris gated on the Phase 4 pilot gate, not thisphase. 69 repos track
detain/myadmin-plugin-installer: dev-master, so a merge herebreaks their CI instantly and can break a production
composer update.What this is
Phase 1 of the MyAdmin plugin test-harness buildout:
src/Testing/, a shared harnessthat lets a plugin's handlers actually execute under test instead of being described
by reflection.
Full design write-up:
docs/testing-harness.md.Additive only. No diff to
src/Plugin.php,src/Installer.php,src/PluginScanner.php,src/VendorGuard.php,src/Loader.php,src/modules.php,src/function_requirements.php,src/Command/, orcomposer.json— verified per file.Results
Fleet state re-measured independently before any change: 66 pass / 3 fail of 69. The
three red are exactly the repos blocked on this phase.
myadmin-virtuozzo-vpsmyadmin-mail-modulemyadmin-vps-modulemyadmin-kvm-vps(control)Both blocked repos went green with no change to their
src/. vps-module's failing setis byte-identical before and after. Fleet-wide: 66 of 66 loadable plugins execute
getSettings()(337 settings registered, zero throws); 40 executegetMenu().Installer suite: 329 tests / 727 assertions, OK, ~0.9 s (was 189 tests / 0.65 s).
How it works
The installer's
autoload.filesalready definesget_module_db(),get_module_settings(),get_service_define()andfunction_requirements()into everyproduction install, so a
function_exists-guarded stub of those names is dead code.Three of the four are pure delegations to
\MyAdmin\App, so aliasingFakeAppintothat name makes the real, unmodified installer functions work against the fakes. The
fourth reads
$GLOBALS['modules'], whichBootstrappopulates via the installer's ownregister_module(). Verified by spike, not assumed.Review focus
src/Testing/stubs.phpdefinesmyadmin_log(),has_acl()anddialog(). If it ever reachedautoload.filesit would shadow the realones in every production install: logging stops,
has_acl()returns a fixed answer.AutoloadTripwireTestenforces this and was observed failing when the path is added(mutation M1) and when a stub loses its guard (M9).
composer dump-autoload -oconfirmsautoload_files.phpholds only the two known entries and zeroTestingpaths.SignaturePinTestpins everyFakeSettings/FakeMenusignature as data. Five entries in the plan's original list disagreed withcore; the harness follows core.
ConstantStubover-capture / risk R3. 20 adversarial cases.Mutation testing: 14 killed, 1 equivalent (documented).
✅ CI matrix — all four legs green
The two pre-existing failures that made
masterred since at least 2026-04-19 are nowfixed on master (
4e8943c,db0d18d) and merged in here, so this branch's matrixreflects the harness alone.
symfony/console v8.1.2, so the typed parent is genuinely exercisedBoth fixes are recorded in detail in
plugin_plan.md. In short:It was never a PHP 8.4 language bug — it is a symfony/console 8.0
incompatibility. Symfony 8 added a native
: voidtoCommand::configure()and allthree commands overrode it untyped, a load-time fatal. It surfaced only on 8.4 because
symfony/console 8 requires PHP >= 8.4; the other legs resolve 7.4.x, whose parent is
untyped. Fixed by declaring
: void, which is correct against both majors, and pinnedby a reflection test so the contract is checked on every leg rather than only where a
resolver happens to pick Symfony 8.
The Windows failures were not path-separator bugs — that was the symptom. Both
VendorGuard::statusLines()and the test fixture shelled out with2>/dev/null, whichcmd.exe cannot resolve; the redirection failed and killed the command line before git
ran. Every invocation returned non-zero, which
statusLines()reads as "clean" — sothe guard that exists to stop Composer silently stashing developer work was itself
silently inert on Windows. (The earlier note in this PR attributing the 5 failures to
PluginScannerTestwas wrong; they wereVendorGuardTest.)Unix behaviour is unchanged by either fix.
Open decision for the owner
The namespace-scoped stub mechanism (amends D2/§629). It works, but Phase 1 measurement
shows it is not required for the four contested functions —
FakeAppcovers them all.Recommendation is a hybrid: nothing by default, a generated committed forwarder file where
a plugin-specific helper genuinely needs one. Reasoning in
docs/testing-harness.md§8.🤖 Generated with Claude Code