aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/tests/command
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-03 01:30:26 +0900
committernsfisis <nsfisis@gmail.com>2026-08-03 01:30:26 +0900
commit20f7a7826ae048d249e0d837ca6393a5f09c9ba6 (patch)
treee35b541857c47543b54afcacf58b82ef3a7cce70 /crates/shirabe/tests/command
parentbf7ec47524a068c7fa7658f03f4dd44957f492a6 (diff)
downloadphp-shirabe-20f7a7826ae048d249e0d837ca6393a5f09c9ba6.tar.gz
php-shirabe-20f7a7826ae048d249e0d837ca6393a5f09c9ba6.tar.zst
php-shirabe-20f7a7826ae048d249e0d837ca6393a5f09c9ba6.zip
feat(event-dispatcher): run composer.json PHP scripts through the RPC worker
Implement the two script execution paths that previously stopped at todo!(): a Class::method listener is invoked as CallStaticMethod with the event crossing the boundary as a proxy-stub handle, and a Command-class listener runs inside a throwaway bare Symfony Application hosted by the worker via a generated snippet, its BufferedOutput written back through the dispatcher's IO. makeAutoloader is ported for real (canonical-package hash, setDevMode, buildPackageMap/parseAutoloads/createLoader), and the class_exists/is_callable/is_a/defined guards now query the worker, whose script autoloader resolves classes by asking the Rust-side ClassLoader over the reverse channel. EventInterface gains as_any (the IOInterface downcast pattern) so the concrete event type is reachable behind the trait object. Application::do_run now registers ScriptAliasCommand entries as typed commands, unblocking the run-script --list/alias tests; the dev-mode-to-generator test is ported with local mockall mocks. The remaining ignored tests carry re-verified reasons: the listener methods live on the PHPUnit test class itself (unloadable in the worker), or the test needs live import of a user PHP Command class into the Application. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/tests/command')
-rw-r--r--crates/shirabe/tests/command/run_script_command_test.rs49
1 files changed, 20 insertions, 29 deletions
diff --git a/crates/shirabe/tests/command/run_script_command_test.rs b/crates/shirabe/tests/command/run_script_command_test.rs
index 6e40bde0..74d05758 100644
--- a/crates/shirabe/tests/command/run_script_command_test.rs
+++ b/crates/shirabe/tests/command/run_script_command_test.rs
@@ -10,33 +10,25 @@ use shirabe_php_shim::PhpMixed;
/// `ScriptEvent` passed to `hasEventListeners` matches the script name AND its `isDevMode()` equals
/// the computed dev mode (`dev || !noDev`) -- the latter being the whole point of the test.
#[test]
-#[ignore = "PHP asserts (a) via mocked hasEventListeners that the ScriptEvent has isDevMode() == \
- (dev || !no_dev) and (b) via mocked dispatchScript that it is called once with \
- ($script, $expectedDevMode, []). Neither expectation is expressible: (a) the \
- __set_get_listeners_override callback only sees &dyn EventInterface \
- (src/event_dispatcher/event.rs:49), which has no as_any/downcast seam to reach the \
- concrete ScriptEvent::is_dev_mode (src/script/event.rs:51) -- adding one is a \
- cross-cutting trait change over every event type, not a small test seam; (b) \
- dispatch_script is a concrete method with no call-recording seam, and letting the \
- real one run would execute listeners for real. The faithful body is therefore \
- inexpressible and is left as todo!()."]
+#[ignore = "PHP mocks RunScriptCommand itself (onlyMethods incl. requireComposer -> a composer \
+ whose EventDispatcher is a hasEventListeners/dispatchScript recording mock) and \
+ drives run() with mocked Input/Output. The Rust RunScriptCommand has no \
+ requireComposer override seam and Input/Output are concrete types, so the mocked \
+ harness is inexpressible; the event-side isDevMode downcast now exists \
+ (EventInterface::as_any), but that alone does not unblock the test."]
fn test_detect_and_pass_dev_mode_to_event_and_to_dispatching() {
- // TODO(phase-d): PHP asserts (a) via mocked hasEventListeners that the ScriptEvent has
- // isDevMode() == (dev || !no_dev) and (b) via mocked dispatchScript that it is called once
- // with ($script, $expectedDevMode, []). Neither expectation is expressible: (a) the
- // __set_get_listeners_override callback only sees &dyn EventInterface
- // (src/event_dispatcher/event.rs:49), which has no as_any/downcast seam to reach the concrete
- // ScriptEvent::is_dev_mode (src/script/event.rs:51) -- adding one is a cross-cutting trait
- // change over every event type, not a small test seam; (b) dispatch_script is a concrete
- // method with no call-recording seam, and letting the real one run would execute listeners
- // for real. The faithful body is therefore inexpressible and is left as todo!().
+ // TODO(phase-d): PHP mocks RunScriptCommand itself (onlyMethods incl. requireComposer -> a
+ // composer whose EventDispatcher is a hasEventListeners/dispatchScript recording mock) and
+ // drives run() with mocked Input/Output. The Rust RunScriptCommand has no requireComposer
+ // override seam and Input/Output are concrete types, so the mocked harness is
+ // inexpressible; the event-side isDevMode downcast now exists (EventInterface::as_any), but
+ // that alone does not unblock the test.
todo!()
}
/// ref: RunScriptCommandTest::testCanListScripts
#[test]
#[serial]
-#[ignore = "Application::do_run registers composer.json scripts as commands; that path calls loader.register (class_loader.rs:288 -> spl_autoload_register at runtime.rs:231) which is a todo!() stub. With a 'scripts' key present, app_tester.run() panics there before the command executes"]
fn test_can_list_scripts() {
let tear_down = init_temp_composer(
Some(&serde_json::json!({
@@ -82,7 +74,6 @@ fn test_can_list_scripts() {
/// ref: RunScriptCommandTest::testCanDefineAliases
#[test]
#[serial]
-#[ignore = "Application::do_run registers composer.json scripts as commands; that path calls loader.register (class_loader.rs:288 -> spl_autoload_register at runtime.rs:231) which is a todo!() stub. With a 'scripts' key present, app_tester.run() panics there before the command executes"]
fn test_can_define_aliases() {
let expected_aliases = vec!["one", "two", "three"];
@@ -131,19 +122,19 @@ fn test_can_define_aliases() {
}
#[test]
-#[ignore = "requires writing and executing a PHP-generated Symfony Command class (file_put_contents MyCommand.php) loaded via composer autoload; fundamentally unportable, no PHP runtime command loading in shirabe"]
+#[ignore = "the test invokes the script name as a top-level composer command, which requires Application::do_run to import the user's PHP Command class (MyCommand.php) as a live application command (todo!() in application.rs; PHP-side Application milestone). The EventDispatcher-side Command-class path alone cannot satisfy the direct invocation and its argument definitions"]
fn test_execution_of_simple_symfony_command() {
- // TODO(phase-d): requires writing and executing a PHP-generated Symfony Command class
- // (file_put_contents MyCommand.php) loaded via composer autoload; fundamentally unportable, no
- // PHP runtime command loading in shirabe.
+ // TODO(phase-d): the test invokes the script name as a top-level composer command, which
+ // requires Application::do_run to import the user's PHP Command class (MyCommand.php) as a
+ // live application command (todo!() in application.rs; PHP-side Application milestone).
todo!()
}
#[test]
-#[ignore = "requires writing and executing a PHP-generated Symfony Command class (file_put_contents MyCommandWithDefinitions.php) loaded via composer autoload; fundamentally unportable, no PHP runtime command loading in shirabe"]
+#[ignore = "the test invokes the script name as a top-level composer command, which requires Application::do_run to import the user's PHP Command class (MyCommandWithDefinitions.php) as a live application command (todo!() in application.rs; PHP-side Application milestone). The EventDispatcher-side Command-class path alone cannot satisfy the direct invocation and its argument definitions"]
fn test_execution_of_symfony_command_with_configuration() {
- // TODO(phase-d): requires writing and executing a PHP-generated Symfony Command class
- // (file_put_contents MyCommandWithDefinitions.php) loaded via composer autoload; fundamentally
- // unportable, no PHP runtime command loading in shirabe.
+ // TODO(phase-d): the test invokes the script name as a top-level composer command, which
+ // requires Application::do_run to import the user's PHP Command class (MyCommandWithDefinitions.php)
+ // as a live application command (todo!() in application.rs; PHP-side Application milestone).
todo!()
}