diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-25 15:24:55 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-26 00:20:05 +0900 |
| commit | d4cdccb8de8758bd46a12283f8df90e020327b99 (patch) | |
| tree | cd7c928cff2615a0bd599cf1f9e09c9852c399d7 /crates/shirabe/tests/util/perforce_test.rs | |
| parent | 8117e5450693d19726da877bce8aacf5c7aa53af (diff) | |
| download | php-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/perforce_test.rs')
| -rw-r--r-- | crates/shirabe/tests/util/perforce_test.rs | 671 |
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(); } |
