aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/tests/util/process_executor_test.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-07-12 01:28:17 +0900
committernsfisis <nsfisis@gmail.com>2026-07-16 01:02:47 +0900
commit4d9e3dd6176a0cd2cc5e158b044beeb7b3de21be (patch)
treeed19d9660f40a1bc93c5629c7a6c7bf41cf884e8 /crates/shirabe/tests/util/process_executor_test.rs
parent4e1170c2328dd8007a5d737a759cd18030b1200b (diff)
downloadphp-shirabe-4d9e3dd6176a0cd2cc5e158b044beeb7b3de21be.tar.gz
php-shirabe-4d9e3dd6176a0cd2cc5e158b044beeb7b3de21be.tar.zst
php-shirabe-4d9e3dd6176a0cd2cc5e158b044beeb7b3de21be.zip
test(util): port remaining todo!() tests in util test suite
Implement previously-todo!() tests in auth_helper_test.rs, process_executor_test.rs, remote_filesystem_test.rs, and stream_context_factory_test.rs by porting the corresponding PHPUnit test methods. Extend IOStub with writeRaw/setAuthentication call tracking and askAndValidate/getAuthentication overrides to model the PHPUnit mocks these tests rely on, deduping the resulting call-recording fields into a small generic CallRecorder<T> helper instead of repeating the same RefCell<Vec<T>> push/borrow().clone() boilerplate five times. testStoreAuthWithPromptInvalidAnswer and testPromptAuthIfNeededMultipleBitbucketDownloads had initially lost the ported PHPUnit mock's argument/call-count assertions (askAndValidate's exact prompt string, and hasAuthentication/getAuthentication's exactly(2) call counts), silently narrowing what the tests verify; IOStub now records these calls and the tests assert on them, matching upstream. Tests left unportable (PHP set_error_handler machinery, closures in data providers, network/subclass-mock dependencies, etc.) keep #[ignore] with a single // TODO(phase-d) reason recorded in the function body. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/tests/util/process_executor_test.rs')
-rw-r--r--crates/shirabe/tests/util/process_executor_test.rs41
1 files changed, 36 insertions, 5 deletions
diff --git a/crates/shirabe/tests/util/process_executor_test.rs b/crates/shirabe/tests/util/process_executor_test.rs
index e093a801..2ce43f3c 100644
--- a/crates/shirabe/tests/util/process_executor_test.rs
+++ b/crates/shirabe/tests/util/process_executor_test.rs
@@ -1,8 +1,8 @@
//! ref: composer/tests/Composer/Test/Util/ProcessExecutorTest.php
// These run real subprocesses (capturing output/stderr/timeout) and assert ProcessExecutor's
-// password hiding, line splitting and argument escaping; the subprocess execution and mocked
-// IO are not ported.
+// password hiding, line splitting and argument escaping. A few data points remain unportable —
+// see the individual `// TODO(phase-d)` comments below.
use shirabe::io::ConsoleIO;
use shirabe::io::IOInterface;
@@ -28,16 +28,34 @@ fn test_execute_captures_output() {
#[ignore = "requires PHP output buffering (ob_start/ob_get_clean) to capture stdout; no equivalent symbol"]
#[test]
fn test_execute_outputs_if_not_captured() {
+ // TODO(phase-d): requires PHP output buffering (ob_start/ob_get_clean) to capture
+ // stdout; no equivalent symbol. ProcessExecutor::execute with
+ // ProcessExecutor::FORWARD_OUTPUT and io=None writes straight to the real process
+ // stdout (see output_handler's `print!`), and there is no safe way to capture that
+ // from within a parallel cargo test process without redirecting the real stdout file
+ // descriptor, which is unsafe under `cargo test`'s default multi-threaded runner.
todo!()
}
-#[ignore = "requires getMockBuilder('IOInterface') with expects()->once()->method('writeRaw')->with() expectation verification; no mocking framework"]
#[test]
fn test_use_io_is_not_null_and_if_not_captured() {
- todo!()
+ use crate::io_stub::IOStub;
+
+ let io = std::rc::Rc::new(std::cell::RefCell::new(IOStub::new()));
+ let mut process = ProcessExecutor::new(Some(
+ io.clone() as std::rc::Rc<std::cell::RefCell<dyn IOInterface>>
+ ));
+
+ process
+ .execute("echo foo", ProcessExecutor::FORWARD_OUTPUT, None)
+ .unwrap();
+
+ assert_eq!(
+ vec![(format!("foo{}", PHP_EOL), false)],
+ io.borrow().write_raw_calls()
+ );
}
-#[ignore = "stderr capture works, but the test cwd (crates/shirabe) contains a `foo/` fixture dir, so `cat foo` reports \"Is a directory\" instead of \"No such file or directory\""]
#[test]
fn test_execute_captures_stderr() {
let mut process = ProcessExecutor::new(None);
@@ -124,6 +142,14 @@ fn test_doesnt_hide_ports() {
#[ignore = "splitLines is called with null in the PHP test, but split_lines accepts only &str (no ?string/Option overload)"]
#[test]
fn test_split_lines() {
+ // TODO(phase-d): splitLines is called with null in the PHP test
+ // ($process->splitLines(null)), but ProcessExecutor::split_lines here takes `&str`, not
+ // `Option<&str>` (PHP's `?string`). Porting this data point faithfully means widening
+ // split_lines's signature to Option<&str>, which touches every call site
+ // (package/version/version_guesser.rs, util/git.rs,
+ // repository/vcs/{hg,fossil,git,svn}_driver.rs — 13 call sites in total, all currently
+ // passing `&str`). That is a production API change beyond this test file; flagged for
+ // a design decision rather than made unilaterally.
todo!()
}
@@ -162,6 +188,11 @@ fn test_console_io_does_not_format_symfony_console_style() {
#[ignore = "executeAsync returns a Process, not a cancelable promise; no promise/cancel symbol exists"]
#[test]
fn test_execute_async_cancel() {
+ // TODO(phase-d): PHP's executeAsync returns a React\Promise\PromiseInterface with
+ // cancel(); Rust's execute_async returns anyhow::Result<Process> directly (see the
+ // comment on ProcessExecutor::execute_async: "no test seam in the external-packages
+ // crate"), so there is no promise/cancel symbol to drive this test's
+ // `$promise->cancel()` step.
todo!()
}