aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/tests/util
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-06-25 15:24:55 +0900
committernsfisis <nsfisis@gmail.com>2026-06-26 00:20:05 +0900
commitd4cdccb8de8758bd46a12283f8df90e020327b99 (patch)
treecd7c928cff2615a0bd599cf1f9e09c9852c399d7 /crates/shirabe/tests/util
parent8117e5450693d19726da877bce8aacf5c7aa53af (diff)
downloadphp-shirabe-d4cdccb8de8758bd46a12283f8df90e020327b99.tar.gz
php-shirabe-d4cdccb8de8758bd46a12283f8df90e020327b99.tar.zst
php-shirabe-d4cdccb8de8758bd46a12283f8df90e020327b99.zip
test: port 70 perforce/repository/downloader/installer/dispatcher tests
Port perforce (36), locker (10), composer_repository (7), installation_manager (6), file_downloader (5), and event_dispatcher (6) tests via the mock infra. Fix production porting bugs surfaced en route: BufferIO::get_output look-behind regex, ComposerRepository list-form package iteration and initialize dispatch, gethostname and spl_autoload_functions shims; add EventDispatcher get_listeners test seam. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/tests/util')
-rw-r--r--crates/shirabe/tests/util/perforce_test.rs671
1 files changed, 589 insertions, 82 deletions
diff --git a/crates/shirabe/tests/util/perforce_test.rs b/crates/shirabe/tests/util/perforce_test.rs
index 0a62ebb..4f3cb58 100644
--- a/crates/shirabe/tests/util/perforce_test.rs
+++ b/crates/shirabe/tests/util/perforce_test.rs
@@ -1,16 +1,19 @@
//! ref: composer/tests/Composer/Test/Util/PerforceTest.php
-// These mock IO and a ProcessExecutor to drive Perforce client/stream/command behaviour;
-// mocking is not available here.
-
use std::cell::RefCell;
use std::rc::Rc;
use indexmap::IndexMap;
+use serial_test::serial;
use shirabe::io::{IOInterface, NullIO};
-use shirabe::util::{Perforce, ProcessExecutor};
+use shirabe::util::Perforce;
+use shirabe::util::filesystem::Filesystem;
+use shirabe::util::process_executor::{MockExpectation, MockHandler, ProcessExecutor};
use shirabe_php_shim::PhpMixed;
+use crate::io_stub::IOStub;
+use crate::process_executor_mock::{cmd, cmd_full, get_process_executor_mock};
+
const TEST_DEPOT: &str = "depot";
const TEST_BRANCH: &str = "branch";
const TEST_P4USER: &str = "user";
@@ -52,14 +55,51 @@ fn create_new_perforce_with_windows_flag(flag: bool) -> Perforce {
)
}
-#[allow(dead_code)]
-fn set_up() {
- // Builds mocked ProcessExecutor/IO, the test repo config, and a Windows-flagged Perforce;
- // mocking is not available.
- todo!()
+// Mirrors PHP `createNewPerforceWithWindowsFlag` but lets each test inject the mocked
+// ProcessExecutor and IO it configured, matching the PHP `setUp` wiring.
+fn create_perforce(
+ flag: bool,
+ process: Rc<RefCell<ProcessExecutor>>,
+ io: Rc<RefCell<dyn IOInterface>>,
+) -> Perforce {
+ Perforce::new(
+ get_test_repo_config(),
+ TEST_PORT.to_string(),
+ TEST_PATH.to_string(),
+ process,
+ flag,
+ io,
+ )
+}
+
+// The expected decoded composer.json, equivalent to PerforceTest::getComposerJson()
+// after json_decode($json, true): an empty `psr-0` object decodes to an empty array.
+fn expected_composer_information() -> IndexMap<String, PhpMixed> {
+ let mut autoload = IndexMap::new();
+ autoload.insert("psr-0".to_string(), PhpMixed::Array(IndexMap::new()));
+
+ let mut expected = IndexMap::new();
+ expected.insert(
+ "name".to_string(),
+ PhpMixed::String("test/perforce".to_string()),
+ );
+ expected.insert(
+ "description".to_string(),
+ PhpMixed::String("Basic project for testing".to_string()),
+ );
+ expected.insert(
+ "minimum-stability".to_string(),
+ PhpMixed::String("dev".to_string()),
+ );
+ expected.insert("autoload".to_string(), PhpMixed::Array(autoload));
+ expected
}
-#[ignore]
+// Valid composer.json content fed as p4 print stdout. Equivalent to
+// PerforceTest::getComposerJson(): the exact formatting is irrelevant because the
+// production code json_decodes it.
+const COMPOSER_JSON: &str = r#"{"name":"test/perforce","description":"Basic project for testing","minimum-stability":"dev","autoload":{"psr-0":{}}}"#;
+
#[test]
fn test_get_client_without_stream() {
let mut perforce = create_new_perforce_with_windows_flag(true);
@@ -70,7 +110,6 @@ fn test_get_client_without_stream() {
assert_eq!(expected, client);
}
-#[ignore]
#[test]
fn test_get_client_from_stream() {
let mut perforce = create_new_perforce_with_windows_flag(true);
@@ -82,7 +121,6 @@ fn test_get_client_from_stream() {
assert_eq!(expected, client);
}
-#[ignore]
#[test]
fn test_get_stream_without_stream() {
let mut perforce = create_new_perforce_with_windows_flag(true);
@@ -91,7 +129,6 @@ fn test_get_stream_without_stream() {
assert_eq!("//depot", stream);
}
-#[ignore]
#[test]
fn test_get_stream_with_stream() {
let mut perforce = create_new_perforce_with_windows_flag(true);
@@ -101,7 +138,6 @@ fn test_get_stream_with_stream() {
assert_eq!("//depot/branch", stream);
}
-#[ignore]
#[test]
fn test_get_stream_without_label_with_stream_without_label() {
let perforce = create_new_perforce_with_windows_flag(true);
@@ -110,7 +146,6 @@ fn test_get_stream_without_label_with_stream_without_label() {
assert_eq!("//depot/branch", stream);
}
-#[ignore]
#[test]
fn test_get_stream_without_label_with_stream_with_label() {
let perforce = create_new_perforce_with_windows_flag(true);
@@ -119,7 +154,6 @@ fn test_get_stream_without_label_with_stream_with_label() {
assert_eq!("//depot/branching", stream);
}
-#[ignore]
#[test]
fn test_get_client_spec() {
let mut perforce = create_new_perforce_with_windows_flag(true);
@@ -129,7 +163,6 @@ fn test_get_client_spec() {
assert_eq!(expected, client_spec);
}
-#[ignore]
#[test]
fn test_generate_p4_command() {
let mut perforce = create_new_perforce_with_windows_flag(true);
@@ -150,7 +183,6 @@ fn test_generate_p4_command() {
assert_eq!(expected, p4_command);
}
-#[ignore]
#[test]
fn test_query_p4_user_with_user_already_set() {
let mut perforce = create_new_perforce_with_windows_flag(true);
@@ -160,48 +192,149 @@ fn test_query_p4_user_with_user_already_set() {
}
#[test]
-#[ignore = "requires getProcessExecutorMock with expects() command stdout stubbing (p4 set => P4USER=...); no mocking infrastructure exists"]
fn test_query_p4_user_with_user_set_in_p4_variables_with_windows_os() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd_full(
+ vec!["p4 set"],
+ 0,
+ format!("P4USER=TEST_P4VARIABLE_USER{}", shirabe_php_shim::PHP_EOL),
+ "",
+ )],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process, io);
+ perforce.set_user(None);
+
+ perforce.query_p4_user();
+ assert_eq!(
+ Some("TEST_P4VARIABLE_USER".to_string()),
+ perforce.get_user()
+ );
}
#[test]
-#[ignore = "requires getProcessExecutorMock with expects() command stdout stubbing (echo $P4USER => ...); no mocking infrastructure exists"]
fn test_query_p4_user_with_user_set_in_p4_variables_not_windows_os() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd_full(
+ vec!["echo $P4USER"],
+ 0,
+ format!("TEST_P4VARIABLE_USER{}", shirabe_php_shim::PHP_EOL),
+ "",
+ )],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(false, process, io);
+ perforce.set_user(None);
+
+ perforce.query_p4_user();
+ assert_eq!(
+ Some("TEST_P4VARIABLE_USER".to_string()),
+ perforce.get_user()
+ );
}
#[test]
-#[ignore = "requires mocked IOInterface ask()->willReturn and getProcessExecutorMock; no mocking infrastructure exists"]
fn test_query_p4_user_queries_for_user() {
- todo!()
+ // Non-strict empty process mock: the p4-variable lookup returns empty so the
+ // code falls through to io->ask().
+ let (process, _guard) = get_process_executor_mock(vec![], false, MockHandler::default());
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(
+ IOStub::new().with_ask(PhpMixed::String("TEST_QUERY_USER".to_string())),
+ ));
+ let mut perforce = create_perforce(true, process, io);
+ perforce.set_user(None);
+
+ perforce.query_p4_user();
+ assert_eq!(Some("TEST_QUERY_USER".to_string()), perforce.get_user());
}
#[test]
-#[ignore = "requires mocked IOInterface ask()->willReturn and getProcessExecutorMock expects() command verification; no mocking infrastructure exists"]
fn test_query_p4_user_stores_response_to_query_for_user_with_windows() {
- todo!()
+ let expected_command = format!(
+ "p4 set P4USER={}",
+ ProcessExecutor::escape("TEST_QUERY_USER")
+ );
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd(vec!["p4 set"]), cmd(vec![expected_command.as_str()])],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(
+ IOStub::new().with_ask(PhpMixed::String("TEST_QUERY_USER".to_string())),
+ ));
+ let mut perforce = create_perforce(true, process, io);
+ perforce.set_user(None);
+
+ perforce.query_p4_user();
}
#[test]
-#[ignore = "requires mocked IOInterface ask()->willReturn and getProcessExecutorMock expects() command verification; no mocking infrastructure exists"]
fn test_query_p4_user_stores_response_to_query_for_user_without_windows() {
- todo!()
+ let expected_command = format!(
+ "export P4USER={}",
+ ProcessExecutor::escape("TEST_QUERY_USER")
+ );
+ let (process, _guard) = get_process_executor_mock(
+ vec![
+ cmd(vec!["echo $P4USER"]),
+ cmd(vec![expected_command.as_str()]),
+ ],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(
+ IOStub::new().with_ask(PhpMixed::String("TEST_QUERY_USER".to_string())),
+ ));
+ let mut perforce = create_perforce(false, process, io);
+ perforce.set_user(None);
+
+ perforce.query_p4_user();
}
#[test]
-#[ignore = "requires mocked IOInterface ask()->willReturn and getProcessExecutorMock expects() command verification; no mocking infrastructure exists"]
fn test_query_p4_user_escapes_injection_on_windows() {
- todo!()
+ let expected_command = format!(
+ "p4 set P4USER={}",
+ ProcessExecutor::escape("foo && calc.exe")
+ );
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd(vec!["p4 set"]), cmd(vec![expected_command.as_str()])],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(
+ IOStub::new().with_ask(PhpMixed::String("foo && calc.exe".to_string())),
+ ));
+ let mut perforce = create_perforce(true, process, io);
+ perforce.set_user(None);
+
+ perforce.query_p4_user();
}
#[test]
-#[ignore = "requires mocked IOInterface ask()->willReturn and getProcessExecutorMock expects() command verification; no mocking infrastructure exists"]
fn test_query_p4_user_escapes_injection_on_unix() {
- todo!()
+ let expected_command = format!("export P4USER={}", ProcessExecutor::escape("foo; id"));
+ let (process, _guard) = get_process_executor_mock(
+ vec![
+ cmd(vec!["echo $P4USER"]),
+ cmd(vec![expected_command.as_str()]),
+ ],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(
+ IOStub::new().with_ask(PhpMixed::String("foo; id".to_string())),
+ ));
+ let mut perforce = create_perforce(false, process, io);
+ perforce.set_user(None);
+
+ perforce.query_p4_user();
}
-#[ignore]
#[test]
fn test_query_p4_password_with_password_already_set() {
let mut repo_config = IndexMap::new();
@@ -228,127 +361,501 @@ fn test_query_p4_password_with_password_already_set() {
}
#[test]
-#[ignore = "requires getProcessExecutorMock with expects() command stdout stubbing (p4 set => P4PASSWD=...); no mocking infrastructure exists"]
fn test_query_p4_password_with_password_set_in_p4_variables_with_windows_os() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd_full(
+ vec!["p4 set"],
+ 0,
+ format!(
+ "P4PASSWD=TEST_P4VARIABLE_PASSWORD{}",
+ shirabe_php_shim::PHP_EOL
+ ),
+ "",
+ )],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process, io);
+
+ let password = perforce.query_p4_password();
+ assert_eq!(Some("TEST_P4VARIABLE_PASSWORD".to_string()), password);
}
#[test]
-#[ignore = "requires getProcessExecutorMock with expects() command stdout stubbing (echo $P4PASSWD => ...); no mocking infrastructure exists"]
fn test_query_p4_password_with_password_set_in_p4_variables_not_windows_os() {
- todo!()
-}
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd_full(
+ vec!["echo $P4PASSWD"],
+ 0,
+ format!("TEST_P4VARIABLE_PASSWORD{}", shirabe_php_shim::PHP_EOL),
+ "",
+ )],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(false, process, io);
-#[test]
-#[ignore = "requires mocked IOInterface askAndHideAnswer()->willReturn; no mocking infrastructure exists"]
-fn test_query_p4_password_queries_for_password() {
- todo!()
+ let password = perforce.query_p4_password();
+ assert_eq!(Some("TEST_P4VARIABLE_PASSWORD".to_string()), password);
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command verification for the p4 client spec write; no mocking infrastructure exists"]
-fn test_write_p4_client_spec_without_stream() {
- todo!()
-}
+fn test_query_p4_password_queries_for_password() {
+ // Non-strict empty process mock: the p4-variable lookup returns empty so the
+ // code falls through to io->askAndHideAnswer().
+ let (process, _guard) = get_process_executor_mock(vec![], false, MockHandler::default());
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(
+ IOStub::new().with_ask_and_hide_answer(Some("TEST_QUERY_PASSWORD".to_string())),
+ ));
+ let mut perforce = create_perforce(true, process, io);
-#[test]
-#[ignore = "requires getProcessExecutorMock expects() command verification for the p4 client spec write; no mocking infrastructure exists"]
-fn test_write_p4_client_spec_with_stream() {
- todo!()
+ let password = perforce.query_p4_password();
+ assert_eq!(Some("TEST_QUERY_PASSWORD".to_string()), password);
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command stdout stubbing for p4 login -s; no mocking infrastructure exists"]
fn test_is_logged_in() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd(vec!["p4", "-u", "user", "-p", "port", "login", "-s"])],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process, io);
+
+ perforce.is_logged_in().unwrap();
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command stdout stubbing for p4 streams; no mocking infrastructure exists"]
fn test_get_branches_with_stream() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![
+ cmd_full(
+ vec![
+ "p4",
+ "-u",
+ "user",
+ "-c",
+ "composer_perforce_TEST_depot_branch",
+ "-p",
+ "port",
+ "streams",
+ "//depot/...",
+ ],
+ 0,
+ format!(
+ "Stream //depot/branch mainline none 'branch'{}",
+ shirabe_php_shim::PHP_EOL
+ ),
+ "",
+ ),
+ cmd_full(
+ vec![
+ "p4",
+ "-u",
+ "user",
+ "-p",
+ "port",
+ "changes",
+ "//depot/branch/...",
+ ],
+ 0,
+ "Change 1234 on 2014/03/19 by Clark.Stuth@Clark.Stuth_test_client 'test changelist'",
+ "",
+ ),
+ ],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process, io);
+ perforce.set_stream("//depot/branch");
+
+ let branches = perforce.get_branches();
+ assert_eq!("//depot/branch@1234", branches["master"]);
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command stdout stubbing for p4 changes; no mocking infrastructure exists"]
fn test_get_branches_without_stream() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd_full(
+ vec!["p4", "-u", "user", "-p", "port", "changes", "//depot/..."],
+ 0,
+ "Change 5678 on 2014/03/19 by Clark.Stuth@Clark.Stuth_test_client 'test changelist'",
+ "",
+ )],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process, io);
+
+ let branches = perforce.get_branches();
+ assert_eq!("//depot@5678", branches["master"]);
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command stdout stubbing for p4 changes; no mocking infrastructure exists"]
fn test_get_tags_without_stream() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd_full(
+ vec![
+ "p4",
+ "-u",
+ "user",
+ "-c",
+ "composer_perforce_TEST_depot",
+ "-p",
+ "port",
+ "labels",
+ ],
+ 0,
+ format!(
+ "Label 0.0.1 2013/07/31 'First Label!'{}Label 0.0.2 2013/08/01 'Second Label!'{}",
+ shirabe_php_shim::PHP_EOL,
+ shirabe_php_shim::PHP_EOL
+ ),
+ "",
+ )],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process, io);
+
+ let tags = perforce.get_tags();
+ assert_eq!("//depot@0.0.1", tags["0.0.1"]);
+ assert_eq!("//depot@0.0.2", tags["0.0.2"]);
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command stdout stubbing for p4 changes; no mocking infrastructure exists"]
fn test_get_tags_with_stream() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd_full(
+ vec![
+ "p4",
+ "-u",
+ "user",
+ "-c",
+ "composer_perforce_TEST_depot_branch",
+ "-p",
+ "port",
+ "labels",
+ ],
+ 0,
+ format!(
+ "Label 0.0.1 2013/07/31 'First Label!'{}Label 0.0.2 2013/08/01 'Second Label!'{}",
+ shirabe_php_shim::PHP_EOL,
+ shirabe_php_shim::PHP_EOL
+ ),
+ "",
+ )],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process, io);
+ perforce.set_stream("//depot/branch");
+
+ let tags = perforce.get_tags();
+ assert_eq!("//depot/branch@0.0.1", tags["0.0.1"]);
+ assert_eq!("//depot/branch@0.0.2", tags["0.0.2"]);
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command stdout stubbing for p4 streams; no mocking infrastructure exists"]
fn test_check_stream_without_stream() {
- todo!()
+ let mut perforce = create_new_perforce_with_windows_flag(true);
+
+ let result = perforce.check_stream();
+ assert!(!result);
+ assert!(!perforce.is_stream());
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command stdout stubbing for p4 streams; no mocking infrastructure exists"]
fn test_check_stream_with_stream() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd_full(
+ vec!["p4", "-u", "user", "-p", "port", "depots"],
+ 0,
+ "Depot depot 2013/06/25 stream /p4/1/depots/depot/... 'Created by Me'",
+ "",
+ )],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process, io);
+
+ let result = perforce.check_stream();
+ assert!(result);
+ assert!(perforce.is_stream());
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command stdout stubbing for p4 print composer.json; no mocking infrastructure exists"]
fn test_get_composer_information_without_label_without_stream() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd_full(
+ vec![
+ "p4",
+ "-u",
+ "user",
+ "-c",
+ "composer_perforce_TEST_depot",
+ "-p",
+ "port",
+ "print",
+ "//depot/composer.json",
+ ],
+ 0,
+ COMPOSER_JSON,
+ "",
+ )],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process, io);
+
+ let result = perforce.get_composer_information("//depot").unwrap();
+ assert_eq!(Some(expected_composer_information()), result);
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command stdout stubbing for p4 print composer.json; no mocking infrastructure exists"]
fn test_get_composer_information_with_label_without_stream() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![
+ cmd_full(
+ vec![
+ "p4",
+ "-u",
+ "user",
+ "-p",
+ "port",
+ "files",
+ "//depot/composer.json@0.0.1",
+ ],
+ 0,
+ "//depot/composer.json#1 - branch change 10001 (text)",
+ "",
+ ),
+ cmd_full(
+ vec![
+ "p4",
+ "-u",
+ "user",
+ "-c",
+ "composer_perforce_TEST_depot",
+ "-p",
+ "port",
+ "print",
+ "//depot/composer.json@10001",
+ ],
+ 0,
+ COMPOSER_JSON,
+ "",
+ ),
+ ],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process, io);
+
+ let result = perforce.get_composer_information("//depot@0.0.1").unwrap();
+ assert_eq!(Some(expected_composer_information()), result);
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command stdout stubbing for p4 print composer.json; no mocking infrastructure exists"]
fn test_get_composer_information_without_label_with_stream() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd_full(
+ vec![
+ "p4",
+ "-u",
+ "user",
+ "-c",
+ "composer_perforce_TEST_depot_branch",
+ "-p",
+ "port",
+ "print",
+ "//depot/branch/composer.json",
+ ],
+ 0,
+ COMPOSER_JSON,
+ "",
+ )],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process, io);
+ perforce.set_stream("//depot/branch");
+
+ let result = perforce.get_composer_information("//depot/branch").unwrap();
+ assert_eq!(Some(expected_composer_information()), result);
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command stdout stubbing for p4 print composer.json; no mocking infrastructure exists"]
fn test_get_composer_information_with_label_with_stream() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![
+ cmd_full(
+ vec![
+ "p4",
+ "-u",
+ "user",
+ "-p",
+ "port",
+ "files",
+ "//depot/branch/composer.json@0.0.1",
+ ],
+ 0,
+ "//depot/composer.json#1 - branch change 10001 (text)",
+ "",
+ ),
+ cmd_full(
+ vec![
+ "p4",
+ "-u",
+ "user",
+ "-c",
+ "composer_perforce_TEST_depot_branch",
+ "-p",
+ "port",
+ "print",
+ "//depot/branch/composer.json@10001",
+ ],
+ 0,
+ COMPOSER_JSON,
+ "",
+ ),
+ ],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process, io);
+ perforce.set_stream("//depot/branch");
+
+ let result = perforce
+ .get_composer_information("//depot/branch@0.0.1")
+ .unwrap();
+ assert_eq!(Some(expected_composer_information()), result);
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command verification for p4 sync; no mocking infrastructure exists"]
+#[serial]
fn test_sync_code_base_without_stream() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd(vec![
+ "p4",
+ "-u",
+ "user",
+ "-c",
+ "composer_perforce_TEST_depot",
+ "-p",
+ "port",
+ "sync",
+ "-f",
+ "@label",
+ ])],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process, io);
+
+ perforce.sync_code_base(Some("label")).unwrap();
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command verification for p4 sync; no mocking infrastructure exists"]
+#[serial]
fn test_sync_code_base_with_stream() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd(vec![
+ "p4",
+ "-u",
+ "user",
+ "-c",
+ "composer_perforce_TEST_depot_branch",
+ "-p",
+ "port",
+ "sync",
+ "-f",
+ "@label",
+ ])],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process, io);
+ perforce.set_stream("//depot/branch");
+
+ perforce.sync_code_base(Some("label")).unwrap();
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command stdout stubbing for p4 info -s; no mocking infrastructure exists"]
fn test_check_server_exists() {
- todo!()
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd(vec![
+ "p4",
+ "-p",
+ "perforce.does.exist:port",
+ "info",
+ "-s",
+ ])],
+ true,
+ MockHandler::default(),
+ );
+
+ let result =
+ Perforce::check_server_exists("perforce.does.exist:port", &mut process.borrow_mut());
+ assert!(result);
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command stdout stubbing for p4 info -s; no mocking infrastructure exists"]
fn test_check_server_client_error() {
- todo!()
+ // PHP mocks ProcessExecutor::execute -> 127. The mock harness returns the
+ // configured return code for the matched command.
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd_full(
+ vec!["p4", "-p", "perforce.does.exist:port", "info", "-s"],
+ 127,
+ "",
+ "",
+ )],
+ true,
+ MockHandler::default(),
+ );
+
+ let result =
+ Perforce::check_server_exists("perforce.does.exist:port", &mut process.borrow_mut());
+ assert!(!result);
}
#[test]
-#[ignore = "requires getProcessExecutorMock expects() command verification for p4 client -d; no mocking infrastructure exists"]
fn test_cleanup_client_spec_should_delete_client() {
- todo!()
+ let test_client = "composer_perforce_TEST_depot";
+ let (process, _guard) = get_process_executor_mock(
+ vec![cmd(vec![
+ "p4",
+ "-u",
+ TEST_P4USER,
+ "-p",
+ TEST_PORT,
+ "client",
+ "-d",
+ test_client,
+ ])],
+ true,
+ MockHandler::default(),
+ );
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+ let mut perforce = create_perforce(true, process.clone(), io);
+
+ let fs = Rc::new(RefCell::new(Filesystem::new(Some(process))));
+ perforce.set_filesystem(fs);
+
+ perforce.cleanup_client_spec();
}