From 01d947899787bf52df50ff791755888856981382 Mon Sep 17 00:00:00 2001 From: krishnakumar4a4 Date: Wed, 24 Jun 2026 19:13:58 +0530 Subject: [PATCH 1/2] refactor: build tests by extracting common functions --- crates/cargo-wdk/src/actions/build/tests.rs | 1941 ++++++++----------- 1 file changed, 842 insertions(+), 1099 deletions(-) diff --git a/crates/cargo-wdk/src/actions/build/tests.rs b/crates/cargo-wdk/src/actions/build/tests.rs index cb6aad715..7ca54cbba 100644 --- a/crates/cargo-wdk/src/actions/build/tests.rs +++ b/crates/cargo-wdk/src/actions/build/tests.rs @@ -44,243 +44,161 @@ use crate::{ // Then: It builds successfully #[test] pub fn given_a_driver_project_when_default_values_are_provided_then_it_builds_successfully() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = false; - let sample_class = false; - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); - - let cargo_build_output = - create_cargo_build_output_json(driver_name, driver_version, &cwd, None, profile); - - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_default_package_task_steps(driver_name, "KMDF", target_arch, verify_signature); - - assert_build_action_run_with_env_is_success( - &cwd, - profile, - None, - verify_signature, - sample_class, - test_build_action, + let test_context = BuildTestContext::default(); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); + let cargo_build_output = default_standalone_build_output(&test_context); + + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) + .expect_default_package_task_steps( + DEFAULT_DRIVER_NAME, + DEFAULT_DRIVER_TYPE, + target_arch, + false, + ) + }, + assert_build_action_success, ); } #[test] pub fn given_a_driver_project_when_profile_is_release_then_it_builds_successfully() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = Some(Profile::Release); - let target_arch = CpuArchitecture::Amd64; - let verify_signature = false; - let sample_class = false; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); - - let cargo_build_output = - create_cargo_build_output_json(driver_name, driver_version, &cwd, None, profile); - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_default_package_task_steps(driver_name, "KMDF", target_arch, verify_signature); - - assert_build_action_run_with_env_is_success( - &cwd, - profile, - None, - verify_signature, - sample_class, - test_build_action, + let test_context = BuildTestContext::default().with_profile(Profile::Release); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); + let cargo_build_output = default_standalone_build_output(&test_context); + + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) + .expect_default_package_task_steps( + DEFAULT_DRIVER_NAME, + DEFAULT_DRIVER_TYPE, + target_arch, + false, + ) + }, + assert_build_action_success, ); } #[test] pub fn given_a_driver_project_when_target_arch_is_arm64_then_it_builds_successfully() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Arm64; - let verify_signature = false; - let sample_class = false; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); - - let cargo_build_output = create_cargo_build_output_json( - driver_name, - driver_version, - &cwd, - Some(&to_target_triple(target_arch)), - profile, - ); - let test_build_action = - &TestBuildAction::new(cwd.clone(), profile, Some(target_arch), sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_default_package_task_steps(driver_name, "KMDF", target_arch, verify_signature); - - assert_build_action_run_with_env_is_success( - &cwd, - profile, - Some(target_arch), - verify_signature, - sample_class, - test_build_action, + let test_context = BuildTestContext::default().with_target_arch(CpuArchitecture::Arm64); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.target_arch.expect("missing target arch"); + let cargo_build_output = default_standalone_build_output(&test_context); + + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_default_package_task_steps( + DEFAULT_DRIVER_NAME, + DEFAULT_DRIVER_TYPE, + target_arch, + false, + ) + }, + assert_build_action_success, ); } #[test] pub fn given_a_driver_project_when_profile_is_release_and_target_arch_is_arm64_then_it_builds_successfully() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = Some(Profile::Release); - let target_arch = CpuArchitecture::Arm64; - let verify_signature = false; - let sample_class = false; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); - - let cargo_build_output = create_cargo_build_output_json( - driver_name, - driver_version, - &cwd, - Some(&to_target_triple(target_arch)), - profile, - ); - - let test_build_action = - &TestBuildAction::new(cwd.clone(), profile, Some(target_arch), sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_default_package_task_steps(driver_name, "KMDF", target_arch, verify_signature); - - assert_build_action_run_with_env_is_success( - &cwd, - profile, - Some(target_arch), - verify_signature, - sample_class, - test_build_action, + let test_context = BuildTestContext::default() + .with_profile(Profile::Release) + .with_target_arch(CpuArchitecture::Arm64); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.target_arch.expect("missing target arch"); + let cargo_build_output = default_standalone_build_output(&test_context); + + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_default_package_task_steps( + DEFAULT_DRIVER_NAME, + DEFAULT_DRIVER_TYPE, + target_arch, + false, + ) + }, + assert_build_action_success, ); } #[test] pub fn given_a_driver_project_when_sample_class_is_true_then_it_builds_successfully() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = false; - let sample_class = true; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); - - let cargo_build_output = - create_cargo_build_output_json(driver_name, driver_version, &cwd, None, profile); - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_default_package_task_steps(driver_name, driver_type, target_arch, verify_signature) - .expect_detect_wdk_build_number(25100u32); - - assert_build_action_run_with_env_is_success( - &cwd, - profile, - None, - verify_signature, - sample_class, - test_build_action, + let test_context = BuildTestContext::default().with_sample_class(true); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); + let cargo_build_output = default_standalone_build_output(&test_context); + + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) + .expect_default_package_task_steps( + DEFAULT_DRIVER_NAME, + DEFAULT_DRIVER_TYPE, + target_arch, + false, + ) + .expect_detect_wdk_build_number(25100u32) + }, + assert_build_action_success, ); } #[test] pub fn given_a_driver_project_when_verify_signature_is_true_then_it_builds_successfully() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = true; - let sample_class = false; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); - - let cargo_build_output = - create_cargo_build_output_json(driver_name, driver_version, &cwd, None, profile); - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_default_package_task_steps(driver_name, driver_type, target_arch, verify_signature); - - assert_build_action_run_with_env_is_success( - &cwd, - profile, - None, - verify_signature, - sample_class, - test_build_action, + let test_context = BuildTestContext::default().with_verify_signature(true); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); + let cargo_build_output = default_standalone_build_output(&test_context); + + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) + .expect_default_package_task_steps( + DEFAULT_DRIVER_NAME, + DEFAULT_DRIVER_TYPE, + target_arch, + true, + ) + }, + assert_build_action_success, ); } #[test] pub fn given_a_driver_project_when_self_signed_exists_then_it_should_skip_calling_makecert() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = true; - let sample_class = false; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); + let test_context = BuildTestContext::default().with_verify_signature(true); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); let expected_certmgr_output = Output { status: ExitStatus::default(), stdout: r"==============Certificate # 1 ========== @@ -312,205 +230,135 @@ pub fn given_a_driver_project_when_self_signed_exists_then_it_should_skip_callin stderr: vec![], }; - let cargo_build_output = - create_cargo_build_output_json(driver_name, driver_version, &cwd, None, profile); - - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(driver_name, &cwd, true) - .expect_inx_file_exists(driver_name, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(driver_name, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(driver_name, &cwd, true) - .expect_copy_pdb_file_to_package_folder(driver_name, &cwd, true) - .expect_copy_inx_file_to_package_folder(driver_name, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(driver_name, &cwd, true) - .expect_stampinf(driver_name, &cwd, target_arch, None) - .expect_inf2cat(driver_name, &cwd, target_arch, None) - .expect_self_signed_cert_file_exists(&cwd, false) - .expect_certmgr_exists_check(Some(expected_certmgr_output)) - .expect_certmgr_create_cert_from_store(&cwd, Some(expected_create_cert_output)) - .expect_copy_self_signed_cert_file_to_package_folder(driver_name, &cwd, true) - .expect_signtool_sign_driver_binary_sys_file(driver_name, &cwd, None) - .expect_signtool_sign_cat_file(driver_name, &cwd, None) - .expect_infverif(driver_name, &cwd, "KMDF", None) - .expect_signtool_verify_driver_binary_sys_file(driver_name, &cwd, None) - .expect_signtool_verify_cat_file(driver_name, &cwd, None); - - assert_build_action_run_with_env_is_success( - &cwd, - profile, - None, - verify_signature, - sample_class, - test_build_action, + let cargo_build_output = default_standalone_build_output(&test_context); + + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) + .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) + .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) + .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_stampinf(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) + .expect_inf2cat(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) + .expect_self_signed_cert_file_exists(&cwd, false) + .expect_certmgr_exists_check(Some(expected_certmgr_output)) + .expect_certmgr_create_cert_from_store(&cwd, Some(expected_create_cert_output)) + .expect_copy_self_signed_cert_file_to_package_folder( + DEFAULT_DRIVER_NAME, + &cwd, + true, + ) + .expect_signtool_sign_driver_binary_sys_file(DEFAULT_DRIVER_NAME, &cwd, None) + .expect_signtool_sign_cat_file(DEFAULT_DRIVER_NAME, &cwd, None) + .expect_infverif(DEFAULT_DRIVER_NAME, &cwd, DEFAULT_DRIVER_TYPE, None) + .expect_signtool_verify_driver_binary_sys_file(DEFAULT_DRIVER_NAME, &cwd, None) + .expect_signtool_verify_cat_file(DEFAULT_DRIVER_NAME, &cwd, None) + }, + assert_build_action_success, ); } #[test] pub fn given_a_driver_project_when_final_package_dir_exists_then_it_should_skip_creating_it() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = false; - let sample_class = false; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); + let test_context = BuildTestContext::default(); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); let expected_certmgr_output = get_certmgr_success_output(); - - let cargo_build_output = - create_cargo_build_output_json(driver_name, driver_version, &cwd, None, profile); - - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(driver_name, &cwd, false) - .expect_dir_created(driver_name, &cwd, true) - .expect_inx_file_exists(driver_name, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(driver_name, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(driver_name, &cwd, true) - .expect_copy_pdb_file_to_package_folder(driver_name, &cwd, true) - .expect_copy_inx_file_to_package_folder(driver_name, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(driver_name, &cwd, true) - .expect_stampinf(driver_name, &cwd, target_arch, None) - .expect_inf2cat(driver_name, &cwd, target_arch, None) - .expect_self_signed_cert_file_exists(&cwd, false) - .expect_certmgr_exists_check(Some(expected_certmgr_output)) - .expect_makecert(&cwd, None) - .expect_copy_self_signed_cert_file_to_package_folder(driver_name, &cwd, true) - .expect_signtool_sign_driver_binary_sys_file(driver_name, &cwd, None) - .expect_signtool_sign_cat_file(driver_name, &cwd, None) - .expect_infverif(driver_name, &cwd, "KMDF", None); - - assert_build_action_run_with_env_is_success( - &cwd, - profile, - None, - verify_signature, - sample_class, - test_build_action, + let cargo_build_output = default_standalone_build_output(&test_context); + + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) + .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, false) + .expect_dir_created(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) + .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) + .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_stampinf(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) + .expect_inf2cat(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) + .expect_self_signed_cert_file_exists(&cwd, false) + .expect_certmgr_exists_check(Some(expected_certmgr_output)) + .expect_makecert(&cwd, None) + .expect_copy_self_signed_cert_file_to_package_folder( + DEFAULT_DRIVER_NAME, + &cwd, + true, + ) + .expect_signtool_sign_driver_binary_sys_file(DEFAULT_DRIVER_NAME, &cwd, None) + .expect_signtool_sign_cat_file(DEFAULT_DRIVER_NAME, &cwd, None) + .expect_infverif(DEFAULT_DRIVER_NAME, &cwd, DEFAULT_DRIVER_TYPE, None) + }, + assert_build_action_success, ); } #[test] pub fn given_a_driver_project_when_inx_file_do_not_exist_then_package_should_fail() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = true; - let sample_class = false; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); - - let cargo_build_output = - create_cargo_build_output_json(driver_name, driver_version, &cwd, None, profile); - - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_inx_file_exists(driver_name, &cwd, false); - - let build_action = initialize_build_action( - &cwd, - profile.as_ref(), - None, - verify_signature, - sample_class, - test_build_action, + let test_context = BuildTestContext::default().with_verify_signature(true); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); + let cargo_build_output = default_standalone_build_output(&test_context); + + set_up_and_assert( + test_context, + BuildActionRunMode::Direct, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) + .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, false) + }, + assert_workspace_member_build_failed, ); - assert!(build_action.is_ok()); - let run_result = build_action.expect("Failed to init build action").run(); - - assert!(matches!( - run_result.as_ref().expect_err("expected error"), - BuildActionError::OneOrMoreWorkspaceMembersFailedToBuild(_) - )); } #[test] pub fn given_a_driver_project_when_copy_of_an_artifact_fails_then_the_package_should_fail() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = true; - let sample_class = false; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); - - let cargo_build_output = create_cargo_build_output_json( - driver_name, - driver_version, - &cwd, - Some(&to_target_triple(target_arch)), - profile, - ); - - let test_build_action = - &TestBuildAction::new(cwd.clone(), profile, Some(target_arch), sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_final_package_dir_exists(driver_name, &cwd, true) - .expect_inx_file_exists(driver_name, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(driver_name, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(driver_name, &cwd, false); - - let build_action = initialize_build_action( - &cwd, - profile.as_ref(), - Some(target_arch), - verify_signature, - sample_class, - test_build_action, + let test_context = BuildTestContext::default() + .with_target_arch(DEFAULT_TARGET_ARCH) + .with_verify_signature(true); + let cwd = test_context.cwd.clone(); + let cargo_build_output = default_standalone_build_output(&test_context); + + set_up_and_assert( + test_context, + BuildActionRunMode::Direct, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) + .expect_copy_driver_binary_sys_to_package_folder( + DEFAULT_DRIVER_NAME, + &cwd, + false, + ) + }, + assert_workspace_member_build_failed, ); - assert!(build_action.is_ok()); - let run_result = build_action.expect("Failed to init build action").run(); - - assert!(matches!( - run_result.as_ref().expect_err("expected error"), - BuildActionError::OneOrMoreWorkspaceMembersFailedToBuild(_) - )); } #[test] pub fn given_a_driver_project_when_stampinf_command_execution_fails_then_package_should_fail() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = true; - let sample_class = false; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); + let test_context = BuildTestContext::default().with_verify_signature(true); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); let expected_stampinf_output = Output { status: ExitStatus::from_raw(1), @@ -518,60 +366,38 @@ pub fn given_a_driver_project_when_stampinf_command_execution_fails_then_package stderr: vec![], }; - let cargo_build_output = - create_cargo_build_output_json(driver_name, driver_version, &cwd, None, profile); - - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(driver_name, &cwd, true) - .expect_inx_file_exists(driver_name, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(driver_name, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(driver_name, &cwd, true) - .expect_copy_pdb_file_to_package_folder(driver_name, &cwd, true) - .expect_copy_inx_file_to_package_folder(driver_name, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(driver_name, &cwd, true) - .expect_stampinf( - driver_name, - &cwd, - target_arch, - Some(expected_stampinf_output), - ); - - let build_action = initialize_build_action( - &cwd, - profile.as_ref(), - None, - verify_signature, - sample_class, - test_build_action, + let cargo_build_output = default_standalone_build_output(&test_context); + + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) + .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) + .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) + .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_stampinf( + DEFAULT_DRIVER_NAME, + &cwd, + target_arch, + Some(expected_stampinf_output), + ) + }, + assert_workspace_member_build_failed, ); - assert!(build_action.is_ok()); - let run_result = run_build_action(build_action); - - assert!(matches!( - run_result.as_ref().expect_err("expected error"), - BuildActionError::OneOrMoreWorkspaceMembersFailedToBuild(_) - )); } #[test] pub fn given_a_driver_project_when_inf2cat_command_execution_fails_then_package_should_fail() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = true; - let sample_class = false; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); + let test_context = BuildTestContext::default().with_verify_signature(true); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); let expected_inf2cat_output = Output { status: ExitStatus::from_raw(1), @@ -579,61 +405,39 @@ pub fn given_a_driver_project_when_inf2cat_command_execution_fails_then_package_ stderr: vec![], }; - let cargo_build_output = - create_cargo_build_output_json(driver_name, driver_version, &cwd, None, profile); - - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(driver_name, &cwd, true) - .expect_inx_file_exists(driver_name, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(driver_name, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(driver_name, &cwd, true) - .expect_copy_pdb_file_to_package_folder(driver_name, &cwd, true) - .expect_copy_inx_file_to_package_folder(driver_name, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(driver_name, &cwd, true) - .expect_stampinf(driver_name, &cwd, target_arch, None) - .expect_inf2cat( - driver_name, - &cwd, - target_arch, - Some(expected_inf2cat_output), - ); - - let build_action = initialize_build_action( - &cwd, - profile.as_ref(), - None, - verify_signature, - sample_class, - test_build_action, + let cargo_build_output = default_standalone_build_output(&test_context); + + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) + .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) + .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) + .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_stampinf(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) + .expect_inf2cat( + DEFAULT_DRIVER_NAME, + &cwd, + target_arch, + Some(expected_inf2cat_output), + ) + }, + assert_workspace_member_build_failed, ); - assert!(build_action.is_ok()); - let run_result = run_build_action(build_action); - - assert!(matches!( - run_result.as_ref().expect_err("expected error"), - BuildActionError::OneOrMoreWorkspaceMembersFailedToBuild(_) - )); } #[test] pub fn given_a_driver_project_when_certmgr_command_execution_fails_then_package_should_fail() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = true; - let sample_class = false; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); + let test_context = BuildTestContext::default().with_verify_signature(true); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); let expected_output = Output { status: ExitStatus::from_raw(1), @@ -641,58 +445,36 @@ pub fn given_a_driver_project_when_certmgr_command_execution_fails_then_package_ stderr: vec![], }; - let cargo_build_output = - create_cargo_build_output_json(driver_name, driver_version, &cwd, None, profile); - - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(driver_name, &cwd, true) - .expect_inx_file_exists(driver_name, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(driver_name, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(driver_name, &cwd, true) - .expect_copy_pdb_file_to_package_folder(driver_name, &cwd, true) - .expect_copy_inx_file_to_package_folder(driver_name, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(driver_name, &cwd, true) - .expect_stampinf(driver_name, &cwd, target_arch, None) - .expect_inf2cat(driver_name, &cwd, target_arch, None) - .expect_self_signed_cert_file_exists(&cwd, false) - .expect_certmgr_exists_check(Some(expected_output)); - - let build_action = initialize_build_action( - &cwd, - profile.as_ref(), - None, - verify_signature, - sample_class, - test_build_action, + let cargo_build_output = default_standalone_build_output(&test_context); + + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) + .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) + .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) + .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_stampinf(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) + .expect_inf2cat(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) + .expect_self_signed_cert_file_exists(&cwd, false) + .expect_certmgr_exists_check(Some(expected_output)) + }, + assert_workspace_member_build_failed, ); - assert!(build_action.is_ok()); - let run_result = run_build_action(build_action); - - assert!(matches!( - run_result.as_ref().expect_err("expected error"), - BuildActionError::OneOrMoreWorkspaceMembersFailedToBuild(_) - )); } #[test] pub fn given_a_driver_project_when_makecert_command_execution_fails_then_package_should_fail() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = true; - let sample_class = false; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); + let test_context = BuildTestContext::default().with_verify_signature(true); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); let expected_output = Output { status: ExitStatus::from_raw(1), @@ -700,62 +482,39 @@ pub fn given_a_driver_project_when_makecert_command_execution_fails_then_package stderr: vec![], }; - let cargo_build_output = - create_cargo_build_output_json(driver_name, driver_version, &cwd, None, profile); - - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(driver_name, &cwd, true) - .expect_inx_file_exists(driver_name, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(driver_name, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(driver_name, &cwd, true) - .expect_copy_pdb_file_to_package_folder(driver_name, &cwd, true) - .expect_copy_inx_file_to_package_folder(driver_name, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(driver_name, &cwd, true) - .expect_stampinf(driver_name, &cwd, target_arch, None) - .expect_inf2cat(driver_name, &cwd, target_arch, None) - .expect_self_signed_cert_file_exists(&cwd, false) - .expect_certmgr_exists_check(None) - .expect_makecert(&cwd, Some(expected_output)); - - let build_action = initialize_build_action( - &cwd, - profile.as_ref(), - None, - verify_signature, - sample_class, - test_build_action, + let cargo_build_output = default_standalone_build_output(&test_context); + + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) + .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) + .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) + .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_stampinf(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) + .expect_inf2cat(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) + .expect_self_signed_cert_file_exists(&cwd, false) + .expect_certmgr_exists_check(None) + .expect_makecert(&cwd, Some(expected_output)) + }, + assert_workspace_member_build_failed, ); - assert!(build_action.is_ok()); - let run_result = run_build_action(build_action); - - assert!(matches!( - run_result.as_ref().expect_err("expected error"), - BuildActionError::OneOrMoreWorkspaceMembersFailedToBuild(_) - )); } #[test] pub fn given_a_driver_project_when_signtool_command_execution_fails_then_package_should_fail() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = true; - let sample_class = false; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); + let test_context = BuildTestContext::default().with_verify_signature(true); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); - let cargo_build_output = - create_cargo_build_output_json(driver_name, driver_version, &cwd, None, profile); + let cargo_build_output = default_standalone_build_output(&test_context); let expected_output = Output { status: ExitStatus::from_raw(1), @@ -763,61 +522,47 @@ pub fn given_a_driver_project_when_signtool_command_execution_fails_then_package stderr: vec![], }; - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(driver_name, &cwd, true) - .expect_inx_file_exists(driver_name, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(driver_name, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(driver_name, &cwd, true) - .expect_copy_pdb_file_to_package_folder(driver_name, &cwd, true) - .expect_copy_inx_file_to_package_folder(driver_name, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(driver_name, &cwd, true) - .expect_stampinf(driver_name, &cwd, target_arch, None) - .expect_inf2cat(driver_name, &cwd, target_arch, None) - .expect_self_signed_cert_file_exists(&cwd, false) - .expect_certmgr_exists_check(None) - .expect_makecert(&cwd, None) - .expect_copy_self_signed_cert_file_to_package_folder(driver_name, &cwd, true) - .expect_signtool_sign_driver_binary_sys_file(driver_name, &cwd, Some(expected_output)); - - let build_action = initialize_build_action( - &cwd, - profile.as_ref(), - None, - verify_signature, - sample_class, - test_build_action, + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) + .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) + .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) + .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_stampinf(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) + .expect_inf2cat(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) + .expect_self_signed_cert_file_exists(&cwd, false) + .expect_certmgr_exists_check(None) + .expect_makecert(&cwd, None) + .expect_copy_self_signed_cert_file_to_package_folder( + DEFAULT_DRIVER_NAME, + &cwd, + true, + ) + .expect_signtool_sign_driver_binary_sys_file( + DEFAULT_DRIVER_NAME, + &cwd, + Some(expected_output), + ) + }, + assert_workspace_member_build_failed, ); - assert!(build_action.is_ok()); - let run_result = run_build_action(build_action); - - assert!(matches!( - run_result.as_ref().expect_err("expected error"), - BuildActionError::OneOrMoreWorkspaceMembersFailedToBuild(_) - )); } #[test] pub fn given_a_driver_project_when_infverif_command_execution_fails_then_package_should_fail() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = true; - let sample_class = false; - - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); + let test_context = BuildTestContext::default().with_verify_signature(true); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); - let cargo_build_output = - create_cargo_build_output_json(driver_name, driver_version, &cwd, None, profile); + let cargo_build_output = default_standalone_build_output(&test_context); let expected_output = Output { status: ExitStatus::from_raw(1), @@ -825,127 +570,86 @@ pub fn given_a_driver_project_when_infverif_command_execution_fails_then_package stderr: vec![], }; - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(driver_name, &cwd, true) - .expect_inx_file_exists(driver_name, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(driver_name, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(driver_name, &cwd, true) - .expect_copy_pdb_file_to_package_folder(driver_name, &cwd, true) - .expect_copy_inx_file_to_package_folder(driver_name, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(driver_name, &cwd, true) - .expect_stampinf(driver_name, &cwd, target_arch, None) - .expect_inf2cat(driver_name, &cwd, target_arch, None) - .expect_self_signed_cert_file_exists(&cwd, false) - .expect_certmgr_exists_check(None) - .expect_makecert(&cwd, None) - .expect_copy_self_signed_cert_file_to_package_folder(driver_name, &cwd, true) - .expect_signtool_sign_driver_binary_sys_file(driver_name, &cwd, None) - .expect_signtool_sign_cat_file(driver_name, &cwd, None) - .expect_infverif(driver_name, &cwd, "KMDF", Some(expected_output)); - - let build_action = initialize_build_action( - &cwd, - profile.as_ref(), - None, - verify_signature, - sample_class, - test_build_action, + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) + .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) + .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) + .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) + .expect_stampinf(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) + .expect_inf2cat(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) + .expect_self_signed_cert_file_exists(&cwd, false) + .expect_certmgr_exists_check(None) + .expect_makecert(&cwd, None) + .expect_copy_self_signed_cert_file_to_package_folder( + DEFAULT_DRIVER_NAME, + &cwd, + true, + ) + .expect_signtool_sign_driver_binary_sys_file(DEFAULT_DRIVER_NAME, &cwd, None) + .expect_signtool_sign_cat_file(DEFAULT_DRIVER_NAME, &cwd, None) + .expect_infverif(DEFAULT_DRIVER_NAME, &cwd, DEFAULT_DRIVER_TYPE, Some(expected_output)) + }, + assert_workspace_member_build_failed, ); - assert!(build_action.is_ok()); - let run_result = run_build_action(build_action); - - assert!(matches!( - run_result.as_ref().expect_err("expected error"), - BuildActionError::OneOrMoreWorkspaceMembersFailedToBuild(_) - )); } #[test] pub fn given_a_non_driver_project_when_default_values_are_provided_with_no_wdk_metadata_are_provided_then_build_should_be_successful() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let verify_signature = true; - let sample_class = false; - - // Driver project data + let test_context = BuildTestContext::default().with_verify_signature(true); + let cwd = test_context.cwd.clone(); let driver_name = "non-driver"; let driver_version = "0.0.1"; let (workspace_member, package) = get_cargo_metadata_package(&cwd, driver_name, driver_version, None); - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, None); - - assert_build_action_run_is_success( - &cwd, - profile, - None, - verify_signature, - sample_class, - test_build_action, + set_up_and_assert( + test_context, + BuildActionRunMode::Direct, + |test_build_action| { + test_build_action + .set_up_standalone_driver_project((workspace_member, package)) + .expect_default_build_task_steps(driver_name, None) + }, + assert_build_action_success, ); } #[test] pub fn given_a_invalid_driver_project_with_partial_wdk_metadata_when_valid_default_values_are_provided_then_wdk_metadata_parse_should_fail() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp\\sample-driver"); - let profile = None; - let verify_signature = true; - let sample_class = false; - - // Driver project data + let test_context = + BuildTestContext::default().with_cwd("C:\\tmp\\sample-driver").with_verify_signature(true); let driver_name = "sample-driver"; let cargo_toml_metadata = invalid_driver_cargo_toml(); - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_with_custom_toml(&cargo_toml_metadata) - .expect_default_build_task_steps(driver_name, None); - - let build_action = initialize_build_action( - &cwd, - profile.as_ref(), - None, - verify_signature, - sample_class, - test_build_action, + set_up_and_assert( + test_context, + BuildActionRunMode::Direct, + |test_build_action| { + test_build_action + .set_up_with_custom_toml(&cargo_toml_metadata) + .expect_default_build_task_steps(driver_name, None) + }, + assert_wdk_metadata_deserialization_failed, ); - assert!(build_action.is_ok()); - let run_result = build_action.expect("Failed to init build action").run(); - assert!(matches!( - run_result.as_ref().expect_err("expected error"), - BuildActionError::WdkMetadataParse(TryFromCargoMetadataError::WdkMetadataDeserialization { - metadata_source: _, - error_source: _ - }) - )); } #[test] pub fn given_a_driver_project_when_target_arch_is_not_provided_and_probing_cargo_rustc_fails_then_packaging_should_fail() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let verify_signature = false; - let sample_class = false; - // Driver project data - let driver_type = "KMDF"; - let driver_name = "sample-kmdf"; - let driver_version = "0.0.1"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, Some(&wdk_metadata)); - - let cargo_build_output = - create_cargo_build_output_json(driver_name, driver_version, &cwd, None, profile); + let test_context = BuildTestContext::default(); + let cwd = test_context.cwd.clone(); + let cargo_build_output = default_standalone_build_output(&test_context); let cargo_rustc_output = Output { status: ExitStatus::from_raw(1), @@ -953,29 +657,20 @@ pub fn given_a_driver_project_when_target_arch_is_not_provided_and_probing_cargo stderr: vec![], }; - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc( - &cwd, - CpuArchitecture::Amd64, - Some(cargo_rustc_output), - ); - - let build_action = initialize_build_action( - &cwd, - profile.as_ref(), - None, - verify_signature, - sample_class, - test_build_action, + set_up_and_assert( + test_context, + BuildActionRunMode::Direct, + |test_build_action| { + set_up_default_standalone_driver_project(test_build_action, &cwd) + .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc( + &cwd, + DEFAULT_TARGET_ARCH, + Some(cargo_rustc_output), + ) + }, + assert_workspace_member_build_failed, ); - assert!(build_action.is_ok()); - let run_result = build_action.expect("Failed to init build action").run(); - assert!(matches!( - run_result.as_ref().expect_err("expected error"), - BuildActionError::OneOrMoreWorkspaceMembersFailedToBuild(_) - )); } //////////////////////////////////////////////////////////////////////////////// @@ -984,14 +679,9 @@ pub fn given_a_driver_project_when_target_arch_is_not_provided_and_probing_cargo #[test] pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_default_values_are_provided_then_it_packages_successfully() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = true; - let sample_class = false; - - // Driver project data + let test_context = BuildTestContext::default().with_verify_signature(true); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); let driver_type = "KMDF"; let driver_name_1 = "sample-kmdf-1"; let driver_version_1 = "0.0.1"; @@ -1007,7 +697,7 @@ pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_defau &cwd, &cwd.join(driver_name_1).join("Cargo.toml"), None, - profile, + test_context.profile, true, ); let artifact_2 = create_cargo_build_output_json_with_manifest( @@ -1016,7 +706,7 @@ pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_defau &cwd, &cwd.join(driver_name_2).join("Cargo.toml"), None, - profile, + test_context.profile, true, ); let artifact_non_driver = create_cargo_build_output_json_with_manifest( @@ -1025,7 +715,7 @@ pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_defau &cwd, &cwd.join(non_driver).join("Cargo.toml"), None, - profile, + test_context.profile, false, ); let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); @@ -1044,60 +734,61 @@ pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_defau let (workspace_member_3, package_3) = get_cargo_metadata_package(&cwd.join(non_driver), non_driver, non_driver_version, None); - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_workspace_with_multiple_driver_projects( - &cwd, - Some(wdk_metadata), - vec![ - (workspace_member_1, package_1), - (workspace_member_2, package_2), - (workspace_member_3, package_3), - ], - ) - .expect_detect_wdk_build_number(25100u32) - .expect_root_manifest_exists(&cwd, true) - .expect_cargo_build(driver_name_1, &cwd.join(driver_name_1), Some(artifact_1)) - .expect_probe_target_arch_using_cargo_rustc(&cwd.join(driver_name_1), target_arch, None) - .expect_default_package_task_steps_for_workspace( - driver_name_1, - driver_type, - target_arch, - verify_signature, - ) - // Second driver project - .expect_cargo_build(driver_name_2, &cwd.join(driver_name_2), Some(artifact_2)) - .expect_probe_target_arch_using_cargo_rustc(&cwd.join(driver_name_2), target_arch, None) - .expect_default_package_task_steps_for_workspace( - driver_name_2, - driver_type, - target_arch, - verify_signature, - ) - // Non-driver project - .expect_cargo_build(non_driver, &cwd.join(non_driver), Some(artifact_non_driver)); - - assert_build_action_run_with_env_is_success( - &cwd, - profile, - None, - verify_signature, - sample_class, - test_build_action, + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + test_build_action + .set_up_workspace_with_multiple_driver_projects( + &cwd, + Some(wdk_metadata), + vec![ + (workspace_member_1, package_1), + (workspace_member_2, package_2), + (workspace_member_3, package_3), + ], + ) + .expect_detect_wdk_build_number(25100u32) + .expect_root_manifest_exists(&cwd, true) + .expect_cargo_build(driver_name_1, &cwd.join(driver_name_1), Some(artifact_1)) + .expect_probe_target_arch_using_cargo_rustc( + &cwd.join(driver_name_1), + target_arch, + None, + ) + .expect_default_package_task_steps_for_workspace( + driver_name_1, + driver_type, + target_arch, + true, + ) + .expect_cargo_build(driver_name_2, &cwd.join(driver_name_2), Some(artifact_2)) + .expect_probe_target_arch_using_cargo_rustc( + &cwd.join(driver_name_2), + target_arch, + None, + ) + .expect_default_package_task_steps_for_workspace( + driver_name_2, + driver_type, + target_arch, + true, + ) + .expect_cargo_build(non_driver, &cwd.join(non_driver), Some(artifact_non_driver)) + }, + assert_build_action_success, ); } #[test] pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_cwd_is_driver_project_then_it_packages_driver_project_successfully() { - // Input CLI args let workspace_root_dir = PathBuf::from("C:\\tmp"); - let cwd = workspace_root_dir.join("sample-kmdf-1"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = true; - let sample_class = false; - - // Driver project data + let test_context = BuildTestContext::default() + .with_cwd(workspace_root_dir.join("sample-kmdf-1")) + .with_verify_signature(true); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); let driver_type = "KMDF"; let driver_name_1 = "sample-kmdf-1"; let driver_version_1 = "0.0.1"; @@ -1133,69 +824,78 @@ pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_cwd_i &workspace_root_dir, &workspace_root_dir.join(driver_name_1).join("Cargo.toml"), None, - profile, + test_context.profile, true, ); - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) // Even when cwd is changed to driver project inside the workspace, cargo metadata read - // is going to be for the whole workspace - .set_up_workspace_with_multiple_driver_projects( - &workspace_root_dir, - Some(wdk_metadata), - vec![ - (workspace_member_1, package_1), - (workspace_member_2, package_2), - (workspace_member_3, package_3), - ], - ) - .expect_detect_wdk_build_number(25100u32) - .expect_root_manifest_exists(&cwd, true) - .expect_cargo_build(driver_name_1, &cwd, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(driver_name_1, &workspace_root_dir, true) - .expect_inx_file_exists(driver_name_1, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(driver_name_1, &workspace_root_dir) - .expect_copy_driver_binary_sys_to_package_folder(driver_name_1, &workspace_root_dir, true) - .expect_copy_pdb_file_to_package_folder(driver_name_1, &workspace_root_dir, true) - .expect_copy_inx_file_to_package_folder(driver_name_1, &cwd, true, &workspace_root_dir) - .expect_copy_map_file_to_package_folder(driver_name_1, &workspace_root_dir, true) - .expect_stampinf(driver_name_1, &workspace_root_dir, target_arch, None) - .expect_inf2cat(driver_name_1, &workspace_root_dir, target_arch, None) - .expect_self_signed_cert_file_exists(&workspace_root_dir, false) - .expect_certmgr_exists_check(Some(expected_certmgr_output)) - .expect_makecert(&workspace_root_dir, None) - .expect_copy_self_signed_cert_file_to_package_folder( - driver_name_1, - &workspace_root_dir, - true, - ) - .expect_signtool_sign_driver_binary_sys_file(driver_name_1, &workspace_root_dir, None) - .expect_signtool_sign_cat_file(driver_name_1, &workspace_root_dir, None) - .expect_signtool_verify_driver_binary_sys_file(driver_name_1, &workspace_root_dir, None) - .expect_signtool_verify_cat_file(driver_name_1, &workspace_root_dir, None) - .expect_infverif(driver_name_1, &workspace_root_dir, "KMDF", None); - - assert_build_action_run_with_env_is_success( - &cwd, - profile, - None, - verify_signature, - sample_class, - test_build_action, + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + test_build_action + .set_up_workspace_with_multiple_driver_projects( + &workspace_root_dir, + Some(wdk_metadata), + vec![ + (workspace_member_1, package_1), + (workspace_member_2, package_2), + (workspace_member_3, package_3), + ], + ) + .expect_detect_wdk_build_number(25100u32) + .expect_root_manifest_exists(&cwd, true) + .expect_cargo_build(driver_name_1, &cwd, Some(cargo_build_output)) + .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) + .expect_final_package_dir_exists(driver_name_1, &workspace_root_dir, true) + .expect_inx_file_exists(driver_name_1, &cwd, true) + .expect_rename_driver_binary_dll_to_sys(driver_name_1, &workspace_root_dir) + .expect_copy_driver_binary_sys_to_package_folder( + driver_name_1, + &workspace_root_dir, + true, + ) + .expect_copy_pdb_file_to_package_folder(driver_name_1, &workspace_root_dir, true) + .expect_copy_inx_file_to_package_folder( + driver_name_1, + &cwd, + true, + &workspace_root_dir, + ) + .expect_copy_map_file_to_package_folder(driver_name_1, &workspace_root_dir, true) + .expect_stampinf(driver_name_1, &workspace_root_dir, target_arch, None) + .expect_inf2cat(driver_name_1, &workspace_root_dir, target_arch, None) + .expect_self_signed_cert_file_exists(&workspace_root_dir, false) + .expect_certmgr_exists_check(Some(expected_certmgr_output)) + .expect_makecert(&workspace_root_dir, None) + .expect_copy_self_signed_cert_file_to_package_folder( + driver_name_1, + &workspace_root_dir, + true, + ) + .expect_signtool_sign_driver_binary_sys_file( + driver_name_1, + &workspace_root_dir, + None, + ) + .expect_signtool_sign_cat_file(driver_name_1, &workspace_root_dir, None) + .expect_signtool_verify_driver_binary_sys_file( + driver_name_1, + &workspace_root_dir, + None, + ) + .expect_signtool_verify_cat_file(driver_name_1, &workspace_root_dir, None) + .expect_infverif(driver_name_1, &workspace_root_dir, "KMDF", None) + }, + assert_build_action_success, ); } #[test] pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_verify_signature_is_false_then_it_skips_verify_tasks() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let target_arch = CpuArchitecture::Amd64; - let verify_signature = false; - let sample_class = false; - - // Driver project data + let test_context = BuildTestContext::default(); + let cwd = test_context.cwd.clone(); + let target_arch = test_context.default_target_arch(); let driver_type = "KMDF"; let driver_name_1 = "sample-kmdf-1"; let driver_version_1 = "0.0.1"; @@ -1211,7 +911,7 @@ pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_verif &cwd, &cwd.join(driver_name_1).join("Cargo.toml"), None, - profile, + test_context.profile, true, ); let artifact_2 = create_cargo_build_output_json_with_manifest( @@ -1220,7 +920,7 @@ pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_verif &cwd, &cwd.join(driver_name_2).join("Cargo.toml"), None, - profile, + test_context.profile, true, ); let artifact_non_driver = create_cargo_build_output_json_with_manifest( @@ -1229,7 +929,7 @@ pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_verif &cwd, &cwd.join(non_driver).join("Cargo.toml"), None, - profile, + test_context.profile, false, // NOT a driver - will use "lib" instead of "cdylib" ); let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); @@ -1248,59 +948,60 @@ pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_verif let (workspace_member_3, package_3) = get_cargo_metadata_package(&cwd.join(non_driver), non_driver, non_driver_version, None); - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_workspace_with_multiple_driver_projects( - &cwd, - Some(wdk_metadata), - vec![ - (workspace_member_1, package_1), - (workspace_member_2, package_2), - (workspace_member_3, package_3), - ], - ) - .expect_detect_wdk_build_number(25100u32) - .expect_root_manifest_exists(&cwd, true) - .expect_cargo_build(driver_name_1, &cwd.join(driver_name_1), Some(artifact_1)) - .expect_probe_target_arch_using_cargo_rustc(&cwd.join(driver_name_1), target_arch, None) - .expect_default_package_task_steps_for_workspace( - driver_name_1, - driver_type, - target_arch, - verify_signature, - ) - // Second driver project - .expect_cargo_build(driver_name_2, &cwd.join(driver_name_2), Some(artifact_2)) - .expect_probe_target_arch_using_cargo_rustc(&cwd.join(driver_name_2), target_arch, None) - .expect_default_package_task_steps_for_workspace( - driver_name_2, - driver_type, - target_arch, - verify_signature, - ) - // Non-driver project - .expect_cargo_build(non_driver, &cwd.join(non_driver), Some(artifact_non_driver)); - - assert_build_action_run_with_env_is_success( - &cwd, - profile, - None, - verify_signature, - sample_class, - test_build_action, + set_up_and_assert( + test_context, + BuildActionRunMode::WithEnv, + |test_build_action| { + test_build_action + .set_up_workspace_with_multiple_driver_projects( + &cwd, + Some(wdk_metadata), + vec![ + (workspace_member_1, package_1), + (workspace_member_2, package_2), + (workspace_member_3, package_3), + ], + ) + .expect_detect_wdk_build_number(25100u32) + .expect_root_manifest_exists(&cwd, true) + .expect_cargo_build(driver_name_1, &cwd.join(driver_name_1), Some(artifact_1)) + .expect_probe_target_arch_using_cargo_rustc( + &cwd.join(driver_name_1), + target_arch, + None, + ) + .expect_default_package_task_steps_for_workspace( + driver_name_1, + driver_type, + target_arch, + false, + ) + .expect_cargo_build(driver_name_2, &cwd.join(driver_name_2), Some(artifact_2)) + .expect_probe_target_arch_using_cargo_rustc( + &cwd.join(driver_name_2), + target_arch, + None, + ) + .expect_default_package_task_steps_for_workspace( + driver_name_2, + driver_type, + target_arch, + false, + ) + .expect_cargo_build(non_driver, &cwd.join(non_driver), Some(artifact_non_driver)) + }, + assert_build_action_success, ); } #[test] pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_cwd_is_non_driver_project_then_it_builds_but_skips_packaging() { - // Input CLI args let workspace_root_dir = PathBuf::from("C:\\tmp"); - let cwd = workspace_root_dir.join("non-driver"); - let profile = None; - let verify_signature = true; - let sample_class = false; - - // Driver project data + let test_context = BuildTestContext::default() + .with_cwd(workspace_root_dir.join("non-driver")) + .with_verify_signature(true); + let cwd = test_context.cwd.clone(); let driver_type = "KMDF"; let driver_name_1 = "sample-kmdf-1"; let driver_version_1 = "0.0.1"; @@ -1328,41 +1029,33 @@ pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_cwd_i None, ); - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) // Even when cwd is changed to driver project inside the workspace, cargo metadata read - // is going to be for the whole workspace - .set_up_workspace_with_multiple_driver_projects( - &workspace_root_dir, - Some(wdk_metadata), - vec![ - (workspace_member_1, package_1), - (workspace_member_2, package_2), - (workspace_member_3, package_3), - ], - ) - .expect_detect_wdk_build_number(25100u32) - .expect_root_manifest_exists(&cwd, true) - .expect_cargo_build(non_driver, &cwd, None); - - assert_build_action_run_is_success( - &cwd, - profile, - None, - verify_signature, - sample_class, - test_build_action, + set_up_and_assert( + test_context, + BuildActionRunMode::Direct, + |test_build_action| { + test_build_action + .set_up_workspace_with_multiple_driver_projects( + &workspace_root_dir, + Some(wdk_metadata), + vec![ + (workspace_member_1, package_1), + (workspace_member_2, package_2), + (workspace_member_3, package_3), + ], + ) + .expect_detect_wdk_build_number(25100u32) + .expect_root_manifest_exists(&cwd, true) + .expect_cargo_build(non_driver, &cwd, None) + }, + assert_build_action_success, ); } #[test] pub fn given_a_workspace_with_multiple_distinct_wdk_configurations_at_each_workspace_member_level_when_default_values_are_provided_then_wdk_metadata_parse_should_fail() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let verify_signature = true; - let sample_class = false; - - // Driver project data + let test_context = BuildTestContext::default().with_verify_signature(true); + let cwd = test_context.cwd.clone(); let driver_type_1 = "KMDF"; let driver_name_1 = "sample-kmdf-1"; let driver_type_2 = "UMDF"; @@ -1384,51 +1077,33 @@ pub fn given_a_workspace_with_multiple_distinct_wdk_configurations_at_each_works Some(&wdk_metadata_2), ); - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_workspace_with_multiple_driver_projects( - &cwd, - Some(wdk_metadata_1), - vec![ - (workspace_member_1, package_1), - (workspace_member_2, package_2), - ], - ) - .expect_detect_wdk_build_number(25100u32) - .expect_root_manifest_exists(&cwd, true) - .expect_cargo_build(driver_name_1, &cwd.join(driver_name_1), None) - .expect_cargo_build(driver_name_2, &cwd.join(driver_name_2), None); - - let build_action = initialize_build_action( - &cwd, - profile.as_ref(), - None, - verify_signature, - sample_class, - test_build_action, + set_up_and_assert( + test_context, + BuildActionRunMode::Direct, + |test_build_action| { + test_build_action + .set_up_workspace_with_multiple_driver_projects( + &cwd, + Some(wdk_metadata_1), + vec![ + (workspace_member_1, package_1), + (workspace_member_2, package_2), + ], + ) + .expect_detect_wdk_build_number(25100u32) + .expect_root_manifest_exists(&cwd, true) + .expect_cargo_build(driver_name_1, &cwd.join(driver_name_1), None) + .expect_cargo_build(driver_name_2, &cwd.join(driver_name_2), None) + }, + assert_multiple_wdk_configurations_detected, ); - assert!(build_action.is_ok()); - let run_result = build_action.expect("Failed to init build action").run(); - - assert!(matches!( - run_result.expect_err("run_result error in test: given_a_workspace_with_multiple_distinct_wdk_configurations_at_each_workspace_member_level_when_default_values_are_provided_then_wdk_metadata_parse_should_fail"), - BuildActionError::WdkMetadataParse( - TryFromCargoMetadataError::MultipleWdkConfigurationsDetected { - wdk_metadata_configurations: _ - } - ) - )); } #[test] pub fn given_a_workspace_with_multiple_distinct_wdk_configurations_at_root_and_workspace_member_level_when_default_values_are_provided_then_wdk_metadata_parse_should_fail() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let verify_signature = true; - let sample_class = false; - - // Driver project data + let test_context = BuildTestContext::default().with_verify_signature(true); + let cwd = test_context.cwd.clone(); let driver_type_1 = "KMDF"; let driver_name_1 = "sample-kmdf-1"; let driver_type_2 = "UMDF"; @@ -1450,88 +1125,64 @@ pub fn given_a_workspace_with_multiple_distinct_wdk_configurations_at_root_and_w Some(&wdk_metadata_1), ); - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) - .set_up_workspace_with_multiple_driver_projects( - &cwd, - Some(wdk_metadata_2), - vec![ - (workspace_member_1, package_1), - (workspace_member_2, package_2), - ], - ) - .expect_root_manifest_exists(&cwd, true) - .expect_detect_wdk_build_number(25100u32) - .expect_cargo_build(driver_name_1, &cwd.join(driver_name_1), None) - .expect_cargo_build(driver_name_2, &cwd.join(driver_name_2), None); - - let build_action = initialize_build_action( - &cwd, - profile.as_ref(), - None, - verify_signature, - sample_class, - test_build_action, + set_up_and_assert( + test_context, + BuildActionRunMode::Direct, + |test_build_action| { + test_build_action + .set_up_workspace_with_multiple_driver_projects( + &cwd, + Some(wdk_metadata_2), + vec![ + (workspace_member_1, package_1), + (workspace_member_2, package_2), + ], + ) + .expect_root_manifest_exists(&cwd, true) + .expect_detect_wdk_build_number(25100u32) + .expect_cargo_build(driver_name_1, &cwd.join(driver_name_1), None) + .expect_cargo_build(driver_name_2, &cwd.join(driver_name_2), None) + }, + assert_multiple_wdk_configurations_detected, ); - assert!(build_action.is_ok()); - let run_result = build_action.expect("Failed to init build action").run(); - - assert!(matches!( - run_result.expect_err("run_result error in test: given_a_workspace_with_multiple_distinct_wdk_configurations_at_root_and_workspace_member_level_when_default_values_are_provided_then_wdk_metadata_parse_should_fail"), - BuildActionError::WdkMetadataParse( - TryFromCargoMetadataError::MultipleWdkConfigurationsDetected { - wdk_metadata_configurations: _ - } - ) - )); } #[test] pub fn given_a_workspace_only_with_non_driver_projects_when_cwd_is_workspace_root_then_build_should_be_successful() { - // Input CLI args - let cwd = PathBuf::from("C:\\tmp"); - let profile = None; - let verify_signature = true; - let sample_class = false; - - // Driver project data + let test_context = BuildTestContext::default().with_verify_signature(true); + let cwd = test_context.cwd.clone(); let non_driver = "non-driver"; let non_driver_version = "0.0.3"; let (workspace_member_3, package_3) = get_cargo_metadata_package(&cwd.join(non_driver), non_driver, non_driver_version, None); - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) // Even when cwd is changed to driver project inside the workspace, cargo metadata read - // is going to be for the whole workspace - .set_up_workspace_with_multiple_driver_projects( - &cwd, - None, - vec![(workspace_member_3, package_3)], - ) - .expect_root_manifest_exists(&cwd, true) - .expect_detect_wdk_build_number(25100u32) - .expect_cargo_build(non_driver, &cwd.join(non_driver), None); - - assert_build_action_run_is_success( - &cwd, - profile, - None, - verify_signature, - sample_class, - test_build_action, + set_up_and_assert( + test_context, + BuildActionRunMode::Direct, + |test_build_action| { + test_build_action + .set_up_workspace_with_multiple_driver_projects( + &cwd, + None, + vec![(workspace_member_3, package_3)], + ) + .expect_root_manifest_exists(&cwd, true) + .expect_detect_wdk_build_number(25100u32) + .expect_cargo_build(non_driver, &cwd.join(non_driver), None) + }, + assert_build_action_success, ); } #[test] pub fn given_a_workspace_only_with_non_driver_projects_when_cwd_is_workspace_member_then_build_should_be_successful() { - // Input CLI args let workspace_root_dir = PathBuf::from("C:\\tmp"); - let cwd = workspace_root_dir.join("non-driver"); - let profile = None; - let verify_signature = true; - let sample_class = false; - - // Driver project data + let test_context = BuildTestContext::default() + .with_cwd(workspace_root_dir.join("non-driver")) + .with_verify_signature(true); + let cwd = test_context.cwd.clone(); let non_driver = "non-driver"; let non_driver_version = "0.0.3"; let (workspace_member_3, package_3) = get_cargo_metadata_package( @@ -1541,49 +1192,119 @@ pub fn given_a_workspace_only_with_non_driver_projects_when_cwd_is_workspace_mem None, ); - let test_build_action = &TestBuildAction::new(cwd.clone(), profile, None, sample_class) // Even when cwd is changed to driver project inside the workspace, cargo metadata read - // is going to be for the whole workspace - .set_up_workspace_with_multiple_driver_projects( - &workspace_root_dir, - None, - vec![(workspace_member_3, package_3)], - ) - .expect_root_manifest_exists(&cwd, true) - .expect_detect_wdk_build_number(25100u32) - .expect_cargo_build(non_driver, &cwd, None); - - assert_build_action_run_is_success( - &cwd, - profile, - None, - verify_signature, - sample_class, - test_build_action, + set_up_and_assert( + test_context, + BuildActionRunMode::Direct, + |test_build_action| { + test_build_action + .set_up_workspace_with_multiple_driver_projects( + &workspace_root_dir, + None, + vec![(workspace_member_3, package_3)], + ) + .expect_root_manifest_exists(&cwd, true) + .expect_detect_wdk_build_number(25100u32) + .expect_cargo_build(non_driver, &cwd, None) + }, + assert_build_action_success, ); } -fn assert_build_action_run_is_success( - cwd: &PathBuf, +const DEFAULT_DRIVER_TYPE: &str = "KMDF"; +const DEFAULT_DRIVER_NAME: &str = "sample-kmdf"; +const DEFAULT_DRIVER_VERSION: &str = "0.0.1"; +const DEFAULT_TARGET_ARCH: CpuArchitecture = CpuArchitecture::Amd64; + +#[derive(Clone, Copy)] +enum BuildActionRunMode { + Direct, + WithEnv, +} + +#[derive(Clone)] +struct BuildTestContext { + cwd: PathBuf, profile: Option, target_arch: Option, verify_signature: bool, sample_class: bool, - test_build_action: &TestBuildAction, -) { +} + +impl Default for BuildTestContext { + fn default() -> Self { + Self { + cwd: PathBuf::from("C:\\tmp"), + profile: None, + target_arch: None, + verify_signature: false, + sample_class: false, + } + } +} + +impl BuildTestContext { + fn with_cwd(mut self, cwd: impl Into) -> Self { + self.cwd = cwd.into(); + self + } + + fn with_profile(mut self, profile: Profile) -> Self { + self.profile = Some(profile); + self + } + + fn with_target_arch(mut self, target_arch: CpuArchitecture) -> Self { + self.target_arch = Some(target_arch); + self + } + + fn with_verify_signature(mut self, verify_signature: bool) -> Self { + self.verify_signature = verify_signature; + self + } + + fn with_sample_class(mut self, sample_class: bool) -> Self { + self.sample_class = sample_class; + self + } + + fn default_target_arch(&self) -> CpuArchitecture { + self.target_arch.unwrap_or(DEFAULT_TARGET_ARCH) + } +} + +fn set_up_and_assert( + test_context: BuildTestContext, + run_mode: BuildActionRunMode, + set_expectations_fn: SetupFn, + assert_fn: AssertFn, +) where + SetupFn: FnOnce(TestBuildAction) -> TestBuildAction, + AssertFn: FnOnce(Result<(), BuildActionError>), +{ + let test_build_action = set_expectations_fn(TestBuildAction::new( + test_context.cwd.clone(), + test_context.profile, + test_context.target_arch, + test_context.sample_class, + )); let build_action = initialize_build_action( - cwd, - profile.as_ref(), - target_arch, - verify_signature, - sample_class, - test_build_action, + &test_context.cwd, + test_context.profile.as_ref(), + test_context.target_arch, + test_context.verify_signature, + test_context.sample_class, + &test_build_action, ); assert!(build_action.is_ok()); - let run_result = build_action.expect("Failed to init build action").run(); - assert!( - run_result.is_ok(), - "build action failed unexpectedly: {run_result:?}" - ); + let build_action = build_action.expect("Failed to init build action"); + let run_result = match run_mode { + BuildActionRunMode::Direct => build_action.run(), + BuildActionRunMode::WithEnv => { + crate::test_utils::with_env::<&str, &str, _, _>(&[], || build_action.run()) + } + }; + assert_fn(run_result); } fn initialize_build_action<'a>( @@ -1624,35 +1345,57 @@ fn get_certmgr_success_output() -> Output { } } -fn assert_build_action_run_with_env_is_success( - cwd: &PathBuf, - profile: Option, - target_arch: Option, - verify_signature: bool, - sample_class: bool, - test_build_action: &TestBuildAction, -) { - let build_action = initialize_build_action( - cwd, - profile.as_ref(), - target_arch, - verify_signature, - sample_class, - test_build_action, - ); - assert!(build_action.is_ok()); - let run_result = run_build_action(build_action); - assert!( - run_result.is_ok(), - "build action with env failed unexpectedly: {run_result:?}" - ); +fn default_standalone_build_output(test_context: &BuildTestContext) -> Output { + let target_triple = test_context.target_arch.map(to_target_triple); + create_cargo_build_output_json( + DEFAULT_DRIVER_NAME, + DEFAULT_DRIVER_VERSION, + &test_context.cwd, + target_triple.as_deref(), + test_context.profile, + ) } -fn run_build_action( - build_action: Result, anyhow::Error>, -) -> Result<(), BuildActionError> { - let build_action = build_action.expect("Failed to init build action"); - crate::test_utils::with_env::<&str, &str, _, _>(&[], || build_action.run()) +fn set_up_default_standalone_driver_project( + test_build_action: TestBuildAction, + cwd: &Path, +) -> TestBuildAction { + let wdk_metadata = get_cargo_metadata_wdk_metadata(DEFAULT_DRIVER_TYPE, 1, 33); + let package_metadata = + get_cargo_metadata_package(cwd, DEFAULT_DRIVER_NAME, DEFAULT_DRIVER_VERSION, Some(&wdk_metadata)); + test_build_action.set_up_standalone_driver_project(package_metadata) +} + +fn assert_build_action_success(result: Result<(), BuildActionError>) { + assert!(result.is_ok(), "build action failed unexpectedly: {result:?}"); +} + +fn assert_workspace_member_build_failed(result: Result<(), BuildActionError>) { + assert!(matches!( + result.as_ref().expect_err("expected error"), + BuildActionError::OneOrMoreWorkspaceMembersFailedToBuild(_) + )); +} + +fn assert_wdk_metadata_deserialization_failed(result: Result<(), BuildActionError>) { + assert!(matches!( + result.as_ref().expect_err("expected error"), + BuildActionError::WdkMetadataParse(TryFromCargoMetadataError::WdkMetadataDeserialization { + metadata_source: _, + error_source: _ + }) + )); +} + +fn assert_multiple_wdk_configurations_detected(result: Result<(), BuildActionError>) { + assert!(matches!( + result.expect_err("expected error"), + BuildActionError::WdkMetadataParse( + TryFromCargoMetadataError::MultipleWdkConfigurationsDetected { + wdk_metadata_configurations: _ + } + ) + )); } /// Helper functions From 2e2b890f980acc4f575a96bf5897a832e87ceb91 Mon Sep 17 00:00:00 2001 From: krishnakumar4a4 Date: Thu, 25 Jun 2026 12:02:12 +0530 Subject: [PATCH 2/2] refactor: unit tests for actions module and tasks --- .../cargo-wdk/src/actions/build/build_task.rs | 36 + crates/cargo-wdk/src/actions/build/mod.rs | 76 +- .../src/actions/build/package_task.rs | 944 ++++- crates/cargo-wdk/src/actions/build/tests.rs | 3222 ++++------------- 4 files changed, 1711 insertions(+), 2567 deletions(-) diff --git a/crates/cargo-wdk/src/actions/build/build_task.rs b/crates/cargo-wdk/src/actions/build/build_task.rs index 83d741fc7..02b885b84 100644 --- a/crates/cargo-wdk/src/actions/build/build_task.rs +++ b/crates/cargo-wdk/src/actions/build/build_task.rs @@ -5,10 +5,14 @@ //! building a driver package with the provided options using the `cargo build` //! command. +#![allow(dead_code)] +#![allow(clippy::unused_self)] + use std::path::{Path, PathBuf}; use anyhow::Result; use cargo_metadata::Message; +use mockall::automock; use mockall_double::double; use tracing::debug; use wdk_build::CpuArchitecture; @@ -31,6 +35,38 @@ pub struct BuildTask<'a> { working_dir: &'a Path, } +#[derive(Debug)] +pub struct BuildTaskRunParams<'a> { + pub package_name: &'a str, + pub working_dir: &'a Path, + pub profile: Option<&'a Profile>, + pub target_arch: Option, + pub verbosity_level: clap_verbosity_flag::Verbosity, +} + +#[derive(Debug, Default)] +pub struct BuildTaskRunner {} + +#[automock] +impl BuildTaskRunner { + pub fn run<'a>( + &self, + params: &BuildTaskRunParams<'a>, + command_exec: &CommandExec, + ) -> Result>, BuildTaskError> { + BuildTask::new( + params.package_name, + params.working_dir, + params.profile, + params.target_arch, + params.verbosity_level, + command_exec, + ) + .run() + .map(Iterator::collect) + } +} + impl<'a> BuildTask<'a> { /// Creates a new instance of `BuildTask`. /// diff --git a/crates/cargo-wdk/src/actions/build/mod.rs b/crates/cargo-wdk/src/actions/build/mod.rs index ad1d9159c..18da4ab8e 100644 --- a/crates/cargo-wdk/src/actions/build/mod.rs +++ b/crates/cargo-wdk/src/actions/build/mod.rs @@ -18,11 +18,9 @@ use std::{ }; use anyhow::Result; -use build_task::BuildTask; use cargo_metadata::{CrateType, Message, Metadata as CargoMetadata, Package, TargetKind}; use error::BuildActionError; use mockall_double::double; -use package_task::{PackageTask, PackageTaskParams}; use tracing::{debug, error as err, info, trace, warn}; use wdk_build::{ CpuArchitecture, @@ -31,7 +29,13 @@ use wdk_build::{ use crate::actions::Profile; #[double] +use build_task::BuildTaskRunner; +use build_task::BuildTaskRunParams; +#[double] use crate::providers::{exec::CommandExec, fs::Fs, metadata::Metadata, wdk_build::WdkBuild}; +#[double] +use package_task::PackageTaskRunner; +use package_task::PackageTaskParams; pub struct BuildActionParams<'a> { pub working_dir: &'a Path, @@ -57,6 +61,8 @@ pub struct BuildAction<'a> { command_exec: &'a CommandExec, fs: &'a Fs, metadata: &'a Metadata, + build_task_runner: BuildTaskRunner, + package_task_runner: PackageTaskRunner, } impl<'a> BuildAction<'a> { @@ -83,6 +89,26 @@ impl<'a> BuildAction<'a> { command_exec: &'a CommandExec, fs: &'a Fs, metadata: &'a Metadata, + ) -> Result { + Self::new_with_runners( + params, + wdk_build, + command_exec, + fs, + metadata, + BuildTaskRunner::default(), + PackageTaskRunner::default(), + ) + } + + fn new_with_runners( + params: &BuildActionParams<'a>, + wdk_build: &'a WdkBuild, + command_exec: &'a CommandExec, + fs: &'a Fs, + metadata: &'a Metadata, + build_task_runner: BuildTaskRunner, + package_task_runner: PackageTaskRunner, ) -> Result { // TODO: validate params Ok(Self { @@ -96,6 +122,8 @@ impl<'a> BuildAction<'a> { command_exec, fs, metadata, + build_task_runner, + package_task_runner, }) } @@ -330,15 +358,16 @@ impl<'a> BuildAction<'a> { let package_name = package.name.as_str(); info!("Building package {package_name}"); - let build_task = BuildTask::new( - package_name, - working_dir, - self.profile, - self.target_arch, - self.verbosity_level, + let output_message_iter = self.build_task_runner.run( + &BuildTaskRunParams { + package_name, + working_dir, + profile: self.profile, + target_arch: self.target_arch, + verbosity_level: self.verbosity_level, + }, self.command_exec, - ); - let output_message_iter = build_task.run()?; + )?; let wdk_metadata = if let Ok(wdk_metadata) = wdk_metadata { debug!("Found wdk metadata in package: {}", package_name); @@ -372,28 +401,29 @@ impl<'a> BuildAction<'a> { self.get_target_arch_from_cargo_rustc(working_dir)? }; debug!("Target architecture for package: {package_name} is: {target_arch}"); - let target_dir = Self::get_target_dir_from_output(package, output_message_iter)?; + let target_dir = Self::get_target_dir_from_output(package, output_message_iter.into_iter())?; debug!( "Target directory for package: {} is: {}", package_name, target_dir.display() ); - PackageTask::new( - PackageTaskParams { - package_name, - working_dir, - target_dir: &target_dir, - target_arch: &target_arch, - verify_signature: self.verify_signature, - sample_class: self.is_sample_class, - driver_model, - }, + let package_task_params = PackageTaskParams { + package_name, + working_dir, + target_dir: &target_dir, + target_arch: &target_arch, + verify_signature: self.verify_signature, + sample_class: self.is_sample_class, + driver_model, + }; + + self.package_task_runner.run( + &package_task_params, self.wdk_build, self.command_exec, self.fs, - ) - .run()?; + )?; info!("Finished building {package_name}"); Ok(()) diff --git a/crates/cargo-wdk/src/actions/build/package_task.rs b/crates/cargo-wdk/src/actions/build/package_task.rs index 6162405aa..238e803db 100644 --- a/crates/cargo-wdk/src/actions/build/package_task.rs +++ b/crates/cargo-wdk/src/actions/build/package_task.rs @@ -7,6 +7,9 @@ //! includes functions that invoke various WDK Tools involved in signing, //! validating, verifying and generating artefacts for the driver package. +#![allow(dead_code)] +#![allow(clippy::unused_self)] + use std::{ ffi::{CStr, CString}, marker::PhantomData, @@ -15,6 +18,7 @@ use std::{ result::Result, }; +use mockall::automock; use mockall_double::double; use tracing::{debug, info, warn}; use wdk_build::{CpuArchitecture, DriverConfig}; @@ -48,6 +52,36 @@ pub struct PackageTaskParams<'a> { pub driver_model: DriverConfig, } +#[derive(Debug, Default)] +pub struct PackageTaskRunner {} + +#[automock] +impl PackageTaskRunner { + pub fn run<'a>( + &self, + params: &PackageTaskParams<'a>, + wdk_build: &WdkBuild, + command_exec: &CommandExec, + fs: &Fs, + ) -> Result<(), PackageTaskError> { + PackageTask::new( + PackageTaskParams { + package_name: params.package_name, + working_dir: params.working_dir, + target_dir: params.target_dir, + target_arch: params.target_arch, + verify_signature: params.verify_signature, + sample_class: params.sample_class, + driver_model: params.driver_model.clone(), + }, + wdk_build, + command_exec, + fs, + ) + .run() + } +} + /// Supports low level driver packaging operations pub struct PackageTask<'a> { package_name: String, @@ -613,13 +647,21 @@ impl Drop for NamedMutex { #[cfg(test)] mod tests { use std::{ + os::windows::process::ExitStatusExt, path::PathBuf, process::{ExitStatus, Output}, }; - use wdk_build::{CpuArchitecture, KmdfConfig}; + use mockall::predicate::eq; + use wdk_build::{CpuArchitecture, DriverConfig, KmdfConfig}; use super::*; + use crate::providers::{ + error::{CommandError, FileError}, + exec::MockCommandExec, + fs::MockFs, + wdk_build::MockWdkBuild, + }; #[test] fn new_succeeds_for_valid_args() { @@ -734,6 +776,403 @@ mod tests { PackageTask::new(package_task_params, &wdk_build, &command_exec, &fs); } + #[test] + fn run_packages_driver_with_expected_operations() { + let mut harness = PackageTaskHarness::new(); + let paths = harness.paths(); + + expect_exists(&mut harness.fs, paths.src_inx_file_path.clone(), true); + expect_exists(&mut harness.fs, paths.dest_root_package_folder.clone(), false); + harness + .fs + .expect_create_dir() + .with(eq(paths.dest_root_package_folder.clone())) + .once() + .return_once(|_| Ok(())); + expect_rename( + &mut harness.fs, + paths.src_driver_binary_file_path.clone(), + paths.src_renamed_driver_binary_file_path.clone(), + Ok(()), + ); + expect_copy( + &mut harness.fs, + paths.src_renamed_driver_binary_file_path.clone(), + paths.dest_driver_binary_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_pdb_file_path.clone(), + paths.dest_pdb_file_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_inx_file_path.clone(), + paths.dest_inf_file_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_map_file_path.clone(), + paths.dest_map_file_path.clone(), + Ok(1), + ); + expect_stampinf( + &mut harness.command_exec, + paths.dest_inf_file_path.clone(), + CpuArchitecture::Amd64, + Some(String::from("1.33")), + ); + expect_inf2cat( + &mut harness.command_exec, + paths.dest_root_package_folder.clone(), + "10_x64", + ); + expect_exists(&mut harness.fs, paths.src_cert_file_path.clone(), false); + expect_certmgr_exists_check(&mut harness.command_exec, false); + expect_certmgr_exists_check(&mut harness.command_exec, false); + expect_makecert(&mut harness.command_exec, paths.src_cert_file_path.clone()); + expect_copy( + &mut harness.fs, + paths.src_cert_file_path.clone(), + paths.dest_cert_file_path.clone(), + Ok(1), + ); + expect_signtool_sign(&mut harness.command_exec, paths.dest_driver_binary_path.clone()); + expect_signtool_sign(&mut harness.command_exec, paths.dest_cat_file_path.clone()); + expect_infverif( + &mut harness.command_exec, + paths.dest_inf_file_path.clone(), + "/w", + None, + ); + + let task = harness.task(); + let result = task.run(); + + assert!(result.is_ok(), "package task failed unexpectedly: {result:?}"); + } + + #[test] + fn run_verifies_signatures_when_enabled() { + let mut harness = PackageTaskHarness::new().with_verify_signature(true); + let paths = harness.paths(); + + expect_successful_packaging_without_verification_side_effects(&mut harness); + expect_signtool_verify(&mut harness.command_exec, paths.dest_driver_binary_path.clone()); + expect_signtool_verify(&mut harness.command_exec, paths.dest_cat_file_path.clone()); + + let task = harness.task(); + let result = task.run(); + + assert!(result.is_ok(), "package task failed unexpectedly: {result:?}"); + } + + #[test] + fn run_exports_certificate_from_store_when_it_already_exists() { + let mut harness = PackageTaskHarness::new(); + let paths = harness.paths(); + + expect_exists(&mut harness.fs, paths.src_inx_file_path.clone(), true); + expect_exists(&mut harness.fs, paths.dest_root_package_folder.clone(), true); + expect_rename( + &mut harness.fs, + paths.src_driver_binary_file_path.clone(), + paths.src_renamed_driver_binary_file_path.clone(), + Ok(()), + ); + expect_copy( + &mut harness.fs, + paths.src_renamed_driver_binary_file_path.clone(), + paths.dest_driver_binary_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_pdb_file_path.clone(), + paths.dest_pdb_file_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_inx_file_path.clone(), + paths.dest_inf_file_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_map_file_path.clone(), + paths.dest_map_file_path.clone(), + Ok(1), + ); + expect_stampinf( + &mut harness.command_exec, + paths.dest_inf_file_path.clone(), + CpuArchitecture::Amd64, + Some(String::from("1.33")), + ); + expect_inf2cat( + &mut harness.command_exec, + paths.dest_root_package_folder.clone(), + "10_x64", + ); + expect_exists(&mut harness.fs, paths.src_cert_file_path.clone(), false); + expect_certmgr_exists_check(&mut harness.command_exec, true); + expect_certmgr_create_cert_from_store( + &mut harness.command_exec, + paths.src_cert_file_path.clone(), + ); + expect_copy( + &mut harness.fs, + paths.src_cert_file_path.clone(), + paths.dest_cert_file_path.clone(), + Ok(1), + ); + expect_signtool_sign(&mut harness.command_exec, paths.dest_driver_binary_path.clone()); + expect_signtool_sign(&mut harness.command_exec, paths.dest_cat_file_path.clone()); + expect_infverif( + &mut harness.command_exec, + paths.dest_inf_file_path.clone(), + "/w", + None, + ); + + let task = harness.task(); + let result = task.run(); + + assert!(result.is_ok(), "package task failed unexpectedly: {result:?}"); + } + + #[test] + fn run_returns_error_when_inx_file_is_missing() { + let mut harness = PackageTaskHarness::new(); + let paths = harness.paths(); + expect_exists(&mut harness.fs, paths.src_inx_file_path.clone(), false); + + let task = harness.task(); + let result = task.run(); + + assert!(matches!( + result, + Err(PackageTaskError::MissingInxSrcFile(path)) + if path == paths.src_inx_file_path + )); + } + + #[test] + fn run_returns_error_when_copying_driver_binary_fails() { + let mut harness = PackageTaskHarness::new(); + let paths = harness.paths(); + + expect_exists(&mut harness.fs, paths.src_inx_file_path.clone(), true); + expect_exists(&mut harness.fs, paths.dest_root_package_folder.clone(), true); + expect_rename( + &mut harness.fs, + paths.src_driver_binary_file_path.clone(), + paths.src_renamed_driver_binary_file_path.clone(), + Ok(()), + ); + expect_copy( + &mut harness.fs, + paths.src_renamed_driver_binary_file_path.clone(), + paths.dest_driver_binary_path.clone(), + Err(FileError::CopyError( + paths.src_renamed_driver_binary_file_path.clone(), + paths.dest_driver_binary_path.clone(), + std::io::Error::new(std::io::ErrorKind::PermissionDenied, "copy failed"), + )), + ); + + let task = harness.task(); + let result = task.run(); + + assert!(matches!( + result, + Err(PackageTaskError::FileIo(FileError::CopyError(src, dest, _))) + if src == paths.src_renamed_driver_binary_file_path + && dest == paths.dest_driver_binary_path + )); + } + + #[test] + fn run_returns_error_when_stampinf_fails() { + let mut harness = PackageTaskHarness::new(); + let paths = harness.paths(); + + expect_exists(&mut harness.fs, paths.src_inx_file_path.clone(), true); + expect_exists(&mut harness.fs, paths.dest_root_package_folder.clone(), true); + expect_rename( + &mut harness.fs, + paths.src_driver_binary_file_path.clone(), + paths.src_renamed_driver_binary_file_path.clone(), + Ok(()), + ); + expect_copy( + &mut harness.fs, + paths.src_renamed_driver_binary_file_path.clone(), + paths.dest_driver_binary_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_pdb_file_path.clone(), + paths.dest_pdb_file_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_inx_file_path.clone(), + paths.dest_inf_file_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_map_file_path.clone(), + paths.dest_map_file_path.clone(), + Ok(1), + ); + expect_stampinf_error( + &mut harness.command_exec, + paths.dest_inf_file_path.clone(), + CpuArchitecture::Amd64, + Some(String::from("1.33")), + ); + + let task = harness.task(); + let result = task.run(); + + assert!(matches!(result, Err(PackageTaskError::StampinfCommand(_)))); + } + + #[test] + fn run_returns_error_when_inf2cat_fails() { + let mut harness = PackageTaskHarness::new(); + let paths = harness.paths(); + + expect_exists(&mut harness.fs, paths.src_inx_file_path.clone(), true); + expect_exists(&mut harness.fs, paths.dest_root_package_folder.clone(), true); + expect_rename( + &mut harness.fs, + paths.src_driver_binary_file_path.clone(), + paths.src_renamed_driver_binary_file_path.clone(), + Ok(()), + ); + expect_copy( + &mut harness.fs, + paths.src_renamed_driver_binary_file_path.clone(), + paths.dest_driver_binary_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_pdb_file_path.clone(), + paths.dest_pdb_file_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_inx_file_path.clone(), + paths.dest_inf_file_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_map_file_path.clone(), + paths.dest_map_file_path.clone(), + Ok(1), + ); + expect_stampinf( + &mut harness.command_exec, + paths.dest_inf_file_path.clone(), + CpuArchitecture::Amd64, + Some(String::from("1.33")), + ); + expect_inf2cat_error( + &mut harness.command_exec, + paths.dest_root_package_folder.clone(), + "10_x64", + ); + + let task = harness.task(); + let result = task.run(); + + assert!(matches!(result, Err(PackageTaskError::Inf2CatCommand(_)))); + } + + #[test] + fn run_skips_infverif_for_samples_when_wdk_build_is_in_bugged_range() { + let mut harness = PackageTaskHarness::new().with_sample_class(true); + let paths = harness.paths(); + + expect_exists(&mut harness.fs, paths.src_inx_file_path.clone(), true); + expect_exists(&mut harness.fs, paths.dest_root_package_folder.clone(), true); + expect_rename( + &mut harness.fs, + paths.src_driver_binary_file_path.clone(), + paths.src_renamed_driver_binary_file_path.clone(), + Ok(()), + ); + expect_copy( + &mut harness.fs, + paths.src_renamed_driver_binary_file_path.clone(), + paths.dest_driver_binary_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_pdb_file_path.clone(), + paths.dest_pdb_file_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_inx_file_path.clone(), + paths.dest_inf_file_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_map_file_path.clone(), + paths.dest_map_file_path.clone(), + Ok(1), + ); + expect_stampinf( + &mut harness.command_exec, + paths.dest_inf_file_path.clone(), + CpuArchitecture::Amd64, + Some(String::from("1.33")), + ); + expect_inf2cat( + &mut harness.command_exec, + paths.dest_root_package_folder.clone(), + "10_x64", + ); + expect_exists(&mut harness.fs, paths.src_cert_file_path.clone(), false); + expect_certmgr_exists_check(&mut harness.command_exec, false); + expect_certmgr_exists_check(&mut harness.command_exec, false); + expect_makecert(&mut harness.command_exec, paths.src_cert_file_path.clone()); + expect_copy( + &mut harness.fs, + paths.src_cert_file_path.clone(), + paths.dest_cert_file_path.clone(), + Ok(1), + ); + expect_signtool_sign(&mut harness.command_exec, paths.dest_driver_binary_path.clone()); + expect_signtool_sign(&mut harness.command_exec, paths.dest_cat_file_path.clone()); + harness + .wdk_build + .expect_detect_wdk_build_number() + .once() + .return_once(|| Ok(25798)); + + let task = harness.task(); + let result = task.run(); + + assert!(result.is_ok(), "package task failed unexpectedly: {result:?}"); + } + #[test] fn stampinf_version_overrides_with_env_var() { // verify both with and without the env var set scenarios @@ -799,6 +1238,509 @@ mod tests { } } + struct PackageTaskHarness { + package_name: &'static str, + working_dir: PathBuf, + target_dir: PathBuf, + arch: CpuArchitecture, + verify_signature: bool, + sample_class: bool, + driver_model: DriverConfig, + command_exec: MockCommandExec, + wdk_build: MockWdkBuild, + fs: MockFs, + } + + impl PackageTaskHarness { + fn new() -> Self { + Self { + package_name: "sample-driver", + working_dir: PathBuf::from(r"C:\abs\sample-driver"), + target_dir: PathBuf::from(r"C:\abs\sample-driver\target\debug"), + arch: CpuArchitecture::Amd64, + verify_signature: false, + sample_class: false, + driver_model: DriverConfig::Kmdf(KmdfConfig { + kmdf_version_major: 1, + target_kmdf_version_minor: 33, + minimum_kmdf_version_minor: Some(33), + }), + command_exec: MockCommandExec::new(), + wdk_build: MockWdkBuild::new(), + fs: MockFs::new(), + } + } + + fn with_verify_signature(mut self, verify_signature: bool) -> Self { + self.verify_signature = verify_signature; + self + } + + fn with_sample_class(mut self, sample_class: bool) -> Self { + self.sample_class = sample_class; + self + } + + fn paths(&self) -> PackageTaskPaths { + PackageTaskPaths { + src_inx_file_path: self.src_inx_file_path(), + src_driver_binary_file_path: self.src_driver_binary_file_path(), + src_renamed_driver_binary_file_path: self.src_renamed_driver_binary_file_path(), + src_pdb_file_path: self.src_pdb_file_path(), + src_map_file_path: self.src_map_file_path(), + src_cert_file_path: self.src_cert_file_path(), + dest_root_package_folder: self.dest_root_package_folder(), + dest_inf_file_path: self.dest_inf_file_path(), + dest_driver_binary_path: self.dest_driver_binary_path(), + dest_pdb_file_path: self.dest_pdb_file_path(), + dest_map_file_path: self.dest_map_file_path(), + dest_cert_file_path: self.dest_cert_file_path(), + dest_cat_file_path: self.dest_cat_file_path(), + } + } + + fn task(&self) -> PackageTask<'_> { + PackageTask::new( + PackageTaskParams { + package_name: self.package_name, + working_dir: &self.working_dir, + target_dir: &self.target_dir, + target_arch: &self.arch, + verify_signature: self.verify_signature, + sample_class: self.sample_class, + driver_model: self.driver_model.clone(), + }, + &self.wdk_build, + &self.command_exec, + &self.fs, + ) + } + + fn normalized_package_name(&self) -> String { + self.package_name.replace('-', "_") + } + + fn src_inx_file_path(&self) -> PathBuf { + self.working_dir + .join(format!("{}.inx", self.normalized_package_name())) + } + + fn src_driver_binary_file_path(&self) -> PathBuf { + self.target_dir + .join(format!("{}.dll", self.normalized_package_name())) + } + + fn src_renamed_driver_binary_file_path(&self) -> PathBuf { + self.target_dir + .join(format!("{}.sys", self.normalized_package_name())) + } + + fn src_pdb_file_path(&self) -> PathBuf { + self.target_dir + .join(format!("{}.pdb", self.normalized_package_name())) + } + + fn src_map_file_path(&self) -> PathBuf { + self.target_dir + .join("deps") + .join(format!("{}.map", self.normalized_package_name())) + } + + fn src_cert_file_path(&self) -> PathBuf { + self.target_dir.join(format!("{WDR_LOCAL_TEST_CERT}.cer")) + } + + fn dest_root_package_folder(&self) -> PathBuf { + self.target_dir + .join(format!("{}_package", self.normalized_package_name())) + } + + fn dest_inf_file_path(&self) -> PathBuf { + self.dest_root_package_folder() + .join(format!("{}.inf", self.normalized_package_name())) + } + + fn dest_driver_binary_path(&self) -> PathBuf { + self.dest_root_package_folder() + .join(format!("{}.sys", self.normalized_package_name())) + } + + fn dest_pdb_file_path(&self) -> PathBuf { + self.dest_root_package_folder() + .join(format!("{}.pdb", self.normalized_package_name())) + } + + fn dest_map_file_path(&self) -> PathBuf { + self.dest_root_package_folder() + .join(format!("{}.map", self.normalized_package_name())) + } + + fn dest_cert_file_path(&self) -> PathBuf { + self.dest_root_package_folder() + .join(format!("{WDR_LOCAL_TEST_CERT}.cer")) + } + + fn dest_cat_file_path(&self) -> PathBuf { + self.dest_root_package_folder() + .join(format!("{}.cat", self.normalized_package_name())) + } + } + + struct PackageTaskPaths { + src_inx_file_path: PathBuf, + src_driver_binary_file_path: PathBuf, + src_renamed_driver_binary_file_path: PathBuf, + src_pdb_file_path: PathBuf, + src_map_file_path: PathBuf, + src_cert_file_path: PathBuf, + dest_root_package_folder: PathBuf, + dest_inf_file_path: PathBuf, + dest_driver_binary_path: PathBuf, + dest_pdb_file_path: PathBuf, + dest_map_file_path: PathBuf, + dest_cert_file_path: PathBuf, + dest_cat_file_path: PathBuf, + } + + fn expect_successful_packaging_without_verification_side_effects( + harness: &mut PackageTaskHarness, + ) { + let paths = harness.paths(); + expect_exists(&mut harness.fs, paths.src_inx_file_path.clone(), true); + expect_exists(&mut harness.fs, paths.dest_root_package_folder.clone(), true); + expect_rename( + &mut harness.fs, + paths.src_driver_binary_file_path.clone(), + paths.src_renamed_driver_binary_file_path.clone(), + Ok(()), + ); + expect_copy( + &mut harness.fs, + paths.src_renamed_driver_binary_file_path.clone(), + paths.dest_driver_binary_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_pdb_file_path.clone(), + paths.dest_pdb_file_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_inx_file_path.clone(), + paths.dest_inf_file_path.clone(), + Ok(1), + ); + expect_copy( + &mut harness.fs, + paths.src_map_file_path.clone(), + paths.dest_map_file_path.clone(), + Ok(1), + ); + expect_stampinf( + &mut harness.command_exec, + paths.dest_inf_file_path.clone(), + CpuArchitecture::Amd64, + Some(String::from("1.33")), + ); + expect_inf2cat( + &mut harness.command_exec, + paths.dest_root_package_folder.clone(), + "10_x64", + ); + expect_exists(&mut harness.fs, paths.src_cert_file_path.clone(), true); + expect_copy( + &mut harness.fs, + paths.src_cert_file_path.clone(), + paths.dest_cert_file_path.clone(), + Ok(1), + ); + expect_signtool_sign(&mut harness.command_exec, paths.dest_driver_binary_path.clone()); + expect_signtool_sign(&mut harness.command_exec, paths.dest_cat_file_path.clone()); + expect_infverif( + &mut harness.command_exec, + paths.dest_inf_file_path.clone(), + "/w", + None, + ); + } + + fn expect_exists(fs: &mut MockFs, path: PathBuf, exists: bool) { + fs.expect_exists() + .with(eq(path)) + .once() + .return_once(move |_| exists); + } + + fn expect_rename( + fs: &mut MockFs, + src: PathBuf, + dest: PathBuf, + result: Result<(), FileError>, + ) { + fs.expect_rename() + .with(eq(src), eq(dest)) + .once() + .return_once(move |_, _| result); + } + + fn expect_copy( + fs: &mut MockFs, + src: PathBuf, + dest: PathBuf, + result: Result, + ) { + fs.expect_copy() + .with(eq(src), eq(dest)) + .once() + .return_once(move |_, _| result); + } + + fn expect_stampinf( + command_exec: &mut MockCommandExec, + dest_inf_file_path: PathBuf, + arch: CpuArchitecture, + wdf_version: Option, + ) { + command_exec + .expect_run() + .withf(move |command, args, _, _| { + let dest_inf = dest_inf_file_path.to_string_lossy().to_string(); + command == "stampinf" + && args.len() >= 8 + && args[0] == "-f" + && args[1] == dest_inf + && args[2] == "-d" + && args[3] == "*" + && args[4] == "-a" + && args[5] == arch.to_string() + && args[6] == "-c" + && args[7] == "sample_driver.cat" + && args.windows(2).any(|window| window == ["-v", "*"]) + && wdf_version + .as_deref() + .is_none_or(|version| args.windows(2).any(|window| window == ["-k", version])) + }) + .once() + .return_once(|_, _, _, _| Ok(success_output())); + } + + fn expect_stampinf_error( + command_exec: &mut MockCommandExec, + dest_inf_file_path: PathBuf, + arch: CpuArchitecture, + wdf_version: Option, + ) { + command_exec + .expect_run() + .withf(move |command, args, _, _| { + let dest_inf = dest_inf_file_path.to_string_lossy().to_string(); + command == "stampinf" + && args.len() >= 8 + && args[0] == "-f" + && args[1] == dest_inf + && args[4] == "-a" + && args[5] == arch.to_string() + && wdf_version + .as_deref() + .is_none_or(|version| args.windows(2).any(|window| window == ["-k", version])) + }) + .once() + .return_once(|_, _, _, _| Err(command_error("stampinf"))); + } + + fn expect_inf2cat(command_exec: &mut MockCommandExec, dest_root: PathBuf, os_mapping: &str) { + let trimmed_dest_root = dest_root.to_string_lossy().trim_start_matches("\\\\?\\").to_string(); + let expected_driver_arg = format!("/driver:{trimmed_dest_root}"); + let expected_os_arg = format!("/os:{os_mapping}"); + command_exec + .expect_run() + .withf(move |command, args, _, _| { + command == "inf2cat" + && args == [expected_driver_arg.as_str(), expected_os_arg.as_str(), "/uselocaltime"] + }) + .once() + .return_once(|_, _, _, _| Ok(success_output())); + } + + fn expect_inf2cat_error( + command_exec: &mut MockCommandExec, + dest_root: PathBuf, + os_mapping: &str, + ) { + let trimmed_dest_root = dest_root.to_string_lossy().trim_start_matches("\\\\?\\").to_string(); + let expected_driver_arg = format!("/driver:{trimmed_dest_root}"); + let expected_os_arg = format!("/os:{os_mapping}"); + command_exec + .expect_run() + .withf(move |command, args, _, _| { + command == "inf2cat" + && args == [expected_driver_arg.as_str(), expected_os_arg.as_str(), "/uselocaltime"] + }) + .once() + .return_once(|_, _, _, _| Err(command_error("inf2cat"))); + } + + fn expect_certmgr_exists_check(command_exec: &mut MockCommandExec, has_cert: bool) { + let stdout = if has_cert { + r"==============Certificate # 1 ========== + Subject:: + [0,0] 2.5.4.3 (CN) WDRLocalTestCert + CertMgr Succeeded" + .as_bytes() + .to_vec() + } else { + r"==============No Certificates ========== + CertMgr Succeeded" + .as_bytes() + .to_vec() + }; + command_exec + .expect_run() + .withf(|command, args, _, _| command == "certmgr.exe" && args == ["-s", WDR_TEST_CERT_STORE]) + .once() + .return_once(move |_, _, _, _| { + Ok(Output { + status: ExitStatus::default(), + stdout, + stderr: vec![], + }) + }); + } + + fn expect_certmgr_create_cert_from_store( + command_exec: &mut MockCommandExec, + cert_path: PathBuf, + ) { + let cert_path = cert_path.to_string_lossy().to_string(); + command_exec + .expect_run() + .withf(move |command, args, _, _| { + command == "certmgr.exe" + && args + == [ + "-put", + "-s", + WDR_TEST_CERT_STORE, + "-c", + "-n", + WDR_LOCAL_TEST_CERT, + cert_path.as_str(), + ] + }) + .once() + .return_once(|_, _, _, _| Ok(success_output())); + } + + fn expect_makecert(command_exec: &mut MockCommandExec, cert_path: PathBuf) { + let cert_path = cert_path.to_string_lossy().to_string(); + command_exec + .expect_run() + .withf(move |command, args, _, _| { + command == "makecert" + && args + == [ + "-r", + "-pe", + "-a", + "SHA256", + "-eku", + "1.3.6.1.5.5.7.3.3", + "-ss", + WDR_TEST_CERT_STORE, + "-n", + "CN=WDRLocalTestCert", + cert_path.as_str(), + ] + }) + .once() + .return_once(|_, _, _, _| Ok(success_output())); + } + + fn expect_signtool_sign(command_exec: &mut MockCommandExec, file_path: PathBuf) { + let file_path = file_path.to_string_lossy().to_string(); + command_exec + .expect_run() + .withf(move |command, args, _, _| { + command == "signtool" + && args + == [ + "sign", + "/v", + "/s", + WDR_TEST_CERT_STORE, + "/n", + WDR_LOCAL_TEST_CERT, + "/t", + "http://timestamp.digicert.com", + "/fd", + "SHA256", + file_path.as_str(), + ] + }) + .once() + .return_once(|_, _, _, _| Ok(success_output())); + } + + fn expect_signtool_verify(command_exec: &mut MockCommandExec, file_path: PathBuf) { + let file_path = file_path.to_string_lossy().to_string(); + command_exec + .expect_run() + .withf(move |command, args, _, _| { + command == "signtool" + && args == ["verify", "/v", "/pa", file_path.as_str()] + }) + .once() + .return_once(|_, _, _, _| Ok(success_output())); + } + + fn expect_infverif( + command_exec: &mut MockCommandExec, + inf_path: PathBuf, + driver_flag: &str, + sample_flag: Option<&'static str>, + ) { + let inf_path = inf_path.to_string_lossy().to_string(); + let expected_args = if let Some(sample_flag) = sample_flag { + vec!["/v".to_string(), driver_flag.to_string(), sample_flag.to_string(), inf_path] + } else { + vec!["/v".to_string(), driver_flag.to_string(), inf_path] + }; + command_exec + .expect_run() + .withf(move |command, args, _, _| { + command == "infverif" + && args.len() == expected_args.len() + && args + .iter() + .zip(expected_args.iter()) + .all(|(actual, expected)| actual == expected) + }) + .once() + .return_once(|_, _, _, _| Ok(success_output())); + } + + fn success_output() -> Output { + Output { + status: ExitStatus::default(), + stdout: vec![], + stderr: vec![], + } + } + + fn command_error(command: &'static str) -> CommandError { + CommandError::from_output( + command, + &[], + &Output { + status: ExitStatus::from_raw(1), + stdout: vec![], + stderr: b"command failed".to_vec(), + }, + ) + } + mod named_mutex { use std::{ ffi::CString, diff --git a/crates/cargo-wdk/src/actions/build/tests.rs b/crates/cargo-wdk/src/actions/build/tests.rs index 7ca54cbba..f8078258b 100644 --- a/crates/cargo-wdk/src/actions/build/tests.rs +++ b/crates/cargo-wdk/src/actions/build/tests.rs @@ -1,1417 +1,543 @@ // Copyright (c) Microsoft Corporation // License: MIT OR Apache-2.0 -#![allow(clippy::too_many_lines)] // Package tests are longer and splitting them into sub functions can make the code less readable -#![allow(clippy::ref_option_ref)] // This is suppressed for mockall as it generates mocks with env_vars: &Option +#![allow(clippy::too_many_lines)] +#![allow(clippy::ref_option_ref)] + use std::{ collections::HashMap, + fs, + io, os::windows::process::ExitStatusExt, path::{Path, PathBuf}, process::{ExitStatus, Output}, - result::Result::Ok, + sync::atomic::{AtomicU64, Ordering}, }; -use cargo_metadata::Metadata as CargoMetadata; +use cargo_metadata::{Message, Metadata as CargoMetadata}; use mockall::predicate::eq; use mockall_double::double; -use wdk_build::{ - CpuArchitecture, - DriverConfig, - metadata::{TryFromCargoMetadataError, Wdk}, -}; +use wdk_build::{CpuArchitecture, DriverConfig}; +use super::{BuildAction, BuildActionError, BuildActionParams, build_task::BuildTaskRunParams, package_task::PackageTaskParams}; #[double] -use crate::providers::{ - exec::CommandExec, - fs::Fs, - metadata::Metadata as MetadataProvider, - wdk_build::WdkBuild, -}; +use super::build_task::BuildTaskRunner; +#[double] +use super::package_task::PackageTaskRunner; use crate::{ - actions::{ - Profile, - build::{BuildAction, BuildActionParams, error::BuildActionError}, - to_target_triple, + actions::{Profile, to_target_triple}, + providers::{ + error::{CommandError, FileError}, + exec::MockCommandExec, + fs::MockFs, + metadata::MockMetadata, + wdk_build::MockWdkBuild, }, - providers::error::{CommandError, FileError}, }; -//////////////////////////////////////////////////////////////////////////////// -/// Standalone driver project tests -//////////////////////////////////////////////////////////////////////////////// -// Test name is of form Given When Then -// Given: A driver project -// When: Default values are provided -// Then: It builds successfully -#[test] -pub fn given_a_driver_project_when_default_values_are_provided_then_it_builds_successfully() { - let test_context = BuildTestContext::default(); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - let cargo_build_output = default_standalone_build_output(&test_context); - - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_default_package_task_steps( - DEFAULT_DRIVER_NAME, - DEFAULT_DRIVER_TYPE, - target_arch, - false, - ) - }, - assert_build_action_success, - ); -} - -#[test] -pub fn given_a_driver_project_when_profile_is_release_then_it_builds_successfully() { - let test_context = BuildTestContext::default().with_profile(Profile::Release); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - let cargo_build_output = default_standalone_build_output(&test_context); - - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_default_package_task_steps( - DEFAULT_DRIVER_NAME, - DEFAULT_DRIVER_TYPE, - target_arch, - false, - ) - }, - assert_build_action_success, - ); -} - -#[test] -pub fn given_a_driver_project_when_target_arch_is_arm64_then_it_builds_successfully() { - let test_context = BuildTestContext::default().with_target_arch(CpuArchitecture::Arm64); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.target_arch.expect("missing target arch"); - let cargo_build_output = default_standalone_build_output(&test_context); - - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_default_package_task_steps( - DEFAULT_DRIVER_NAME, - DEFAULT_DRIVER_TYPE, - target_arch, - false, - ) - }, - assert_build_action_success, - ); -} - +const DEFAULT_DRIVER_NAME: &str = "sample-driver"; +const DEFAULT_DRIVER_VERSION: &str = "0.0.1"; #[test] -pub fn given_a_driver_project_when_profile_is_release_and_target_arch_is_arm64_then_it_builds_successfully() +fn given_a_driver_project_when_target_arch_is_detected_then_build_action_orchestrates_build_and_package() { - let test_context = BuildTestContext::default() - .with_profile(Profile::Release) - .with_target_arch(CpuArchitecture::Arm64); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.target_arch.expect("missing target arch"); - let cargo_build_output = default_standalone_build_output(&test_context); - - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_default_package_task_steps( - DEFAULT_DRIVER_NAME, - DEFAULT_DRIVER_TYPE, - target_arch, - false, - ) - }, - assert_build_action_success, - ); -} - -#[test] -pub fn given_a_driver_project_when_sample_class_is_true_then_it_builds_successfully() { - let test_context = BuildTestContext::default().with_sample_class(true); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - let cargo_build_output = default_standalone_build_output(&test_context); - - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_default_package_task_steps( - DEFAULT_DRIVER_NAME, - DEFAULT_DRIVER_TYPE, - target_arch, - false, - ) - .expect_detect_wdk_build_number(25100u32) - }, - assert_build_action_success, - ); -} - -#[test] -pub fn given_a_driver_project_when_verify_signature_is_true_then_it_builds_successfully() { - let test_context = BuildTestContext::default().with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - let cargo_build_output = default_standalone_build_output(&test_context); - - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_default_package_task_steps( - DEFAULT_DRIVER_NAME, - DEFAULT_DRIVER_TYPE, - target_arch, - true, - ) - }, - assert_build_action_success, - ); -} - -#[test] -pub fn given_a_driver_project_when_self_signed_exists_then_it_should_skip_calling_makecert() { - let test_context = BuildTestContext::default().with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - let expected_certmgr_output = Output { - status: ExitStatus::default(), - stdout: r"==============Certificate # 1 ========== - Subject:: - [0,0] 2.5.4.3 (CN) WDRLocalTestCert - Issuer:: - [0,0] 2.5.4.3 (CN) WDRLocalTestCert - SerialNumber:: - 5E 04 0D 63 35 20 76 A5 4A E1 96 BF CF 01 0F 96 - SHA1 Thumbprint:: - FB972842 C63CD369 E07D0C71 88E17921 B5813C71 - MD5 Thumbprint:: - 832B3F18 707EA3F6 54465207 345A93F1 - Provider Type:: 1 Provider Name:: Microsoft Strong Cryptographic Provider Container: 68f79a6e-6afa-4ec7-be5b-16d6656edd3f KeySpec: 2 - NotBefore:: - Tue Jan 28 13:51:04 2025 - NotAfter:: - Sun Jan 01 05:29:59 2040 - ==============No CTLs ========== - ==============No CRLs ========== - ============================================== - CertMgr Succeeded".as_bytes().to_vec(), - stderr: vec![], - }; - - let expected_create_cert_output = Output { - status: ExitStatus::default(), - stdout: vec![], - stderr: vec![], - }; + let cwd = PathBuf::from(r"C:\tmp\sample-driver"); + let target_dir = expected_target_dir(&cwd, None, None); + let mut test_build_action = TestBuildAction::new(cwd.clone(), None, None, false, false) + .set_up_standalone_driver_project(DEFAULT_DRIVER_NAME, Some(default_wdk_metadata())); - let cargo_build_output = default_standalone_build_output(&test_context); - - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_stampinf(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) - .expect_inf2cat(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) - .expect_self_signed_cert_file_exists(&cwd, false) - .expect_certmgr_exists_check(Some(expected_certmgr_output)) - .expect_certmgr_create_cert_from_store(&cwd, Some(expected_create_cert_output)) - .expect_copy_self_signed_cert_file_to_package_folder( - DEFAULT_DRIVER_NAME, - &cwd, - true, - ) - .expect_signtool_sign_driver_binary_sys_file(DEFAULT_DRIVER_NAME, &cwd, None) - .expect_signtool_sign_cat_file(DEFAULT_DRIVER_NAME, &cwd, None) - .expect_infverif(DEFAULT_DRIVER_NAME, &cwd, DEFAULT_DRIVER_TYPE, None) - .expect_signtool_verify_driver_binary_sys_file(DEFAULT_DRIVER_NAME, &cwd, None) - .expect_signtool_verify_cat_file(DEFAULT_DRIVER_NAME, &cwd, None) - }, - assert_build_action_success, - ); -} - -#[test] -pub fn given_a_driver_project_when_final_package_dir_exists_then_it_should_skip_creating_it() { - let test_context = BuildTestContext::default(); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - let expected_certmgr_output = get_certmgr_success_output(); - let cargo_build_output = default_standalone_build_output(&test_context); - - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, false) - .expect_dir_created(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_stampinf(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) - .expect_inf2cat(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) - .expect_self_signed_cert_file_exists(&cwd, false) - .expect_certmgr_exists_check(Some(expected_certmgr_output)) - .expect_makecert(&cwd, None) - .expect_copy_self_signed_cert_file_to_package_folder( - DEFAULT_DRIVER_NAME, - &cwd, - true, - ) - .expect_signtool_sign_driver_binary_sys_file(DEFAULT_DRIVER_NAME, &cwd, None) - .expect_signtool_sign_cat_file(DEFAULT_DRIVER_NAME, &cwd, None) - .expect_infverif(DEFAULT_DRIVER_NAME, &cwd, DEFAULT_DRIVER_TYPE, None) - }, - assert_build_action_success, - ); -} - -#[test] -pub fn given_a_driver_project_when_inx_file_do_not_exist_then_package_should_fail() { - let test_context = BuildTestContext::default().with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - let cargo_build_output = default_standalone_build_output(&test_context); - - set_up_and_assert( - test_context, - BuildActionRunMode::Direct, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, false) - }, - assert_workspace_member_build_failed, + test_build_action.expect_build_runner( + DEFAULT_DRIVER_NAME, + &cwd, + None, + None, + Ok(cargo_build_messages( + DEFAULT_DRIVER_NAME, + DEFAULT_DRIVER_VERSION, + &cwd, + None, + None, + )), ); -} - -#[test] -pub fn given_a_driver_project_when_copy_of_an_artifact_fails_then_the_package_should_fail() { - let test_context = BuildTestContext::default() - .with_target_arch(DEFAULT_TARGET_ARCH) - .with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let cargo_build_output = default_standalone_build_output(&test_context); - - set_up_and_assert( - test_context, - BuildActionRunMode::Direct, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) - .expect_copy_driver_binary_sys_to_package_folder( - DEFAULT_DRIVER_NAME, - &cwd, - false, - ) - }, - assert_workspace_member_build_failed, + test_build_action.expect_probe_target_arch_using_cargo_rustc(&cwd, CpuArchitecture::Amd64); + test_build_action.expect_package_runner( + DEFAULT_DRIVER_NAME, + &cwd, + &target_dir, + CpuArchitecture::Amd64, + false, + false, ); -} -#[test] -pub fn given_a_driver_project_when_stampinf_command_execution_fails_then_package_should_fail() { - let test_context = BuildTestContext::default().with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - - let expected_stampinf_output = Output { - status: ExitStatus::from_raw(1), - stdout: vec![], - stderr: vec![], - }; + let build_action = initialize_build_action(&mut test_build_action); + let result = build_action.run_from_workspace_root(&cwd); - let cargo_build_output = default_standalone_build_output(&test_context); - - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_stampinf( - DEFAULT_DRIVER_NAME, - &cwd, - target_arch, - Some(expected_stampinf_output), - ) - }, - assert_workspace_member_build_failed, - ); + assert!(result.is_ok(), "build action failed unexpectedly: {result:?}"); } #[test] -pub fn given_a_driver_project_when_inf2cat_command_execution_fails_then_package_should_fail() { - let test_context = BuildTestContext::default().with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - - let expected_inf2cat_output = Output { - status: ExitStatus::from_raw(1), - stdout: vec![], - stderr: vec![], - }; - - let cargo_build_output = default_standalone_build_output(&test_context); - - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_stampinf(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) - .expect_inf2cat( - DEFAULT_DRIVER_NAME, - &cwd, - target_arch, - Some(expected_inf2cat_output), - ) - }, - assert_workspace_member_build_failed, +fn given_explicit_target_arch_when_building_then_probe_is_skipped_and_package_runner_uses_it() { + let cwd = PathBuf::from(r"C:\tmp\sample-driver"); + let profile = Some(Profile::Release); + let target_arch = CpuArchitecture::Arm64; + let target_dir = expected_target_dir(&cwd, Some(target_arch), profile); + let target_triple = to_target_triple(target_arch); + let mut test_build_action = + TestBuildAction::new(cwd.clone(), profile, Some(target_arch), true, true) + .set_up_standalone_driver_project(DEFAULT_DRIVER_NAME, Some(default_wdk_metadata())); + + test_build_action.expect_build_runner( + DEFAULT_DRIVER_NAME, + &cwd, + profile, + Some(target_arch), + Ok(cargo_build_messages( + DEFAULT_DRIVER_NAME, + DEFAULT_DRIVER_VERSION, + &cwd, + Some(target_triple.as_str()), + profile, + )), ); -} - -#[test] -pub fn given_a_driver_project_when_certmgr_command_execution_fails_then_package_should_fail() { - let test_context = BuildTestContext::default().with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - - let expected_output = Output { - status: ExitStatus::from_raw(1), - stdout: vec![], - stderr: vec![], - }; - - let cargo_build_output = default_standalone_build_output(&test_context); - - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_stampinf(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) - .expect_inf2cat(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) - .expect_self_signed_cert_file_exists(&cwd, false) - .expect_certmgr_exists_check(Some(expected_output)) - }, - assert_workspace_member_build_failed, + test_build_action.expect_package_runner( + DEFAULT_DRIVER_NAME, + &cwd, + &target_dir, + target_arch, + true, + true, ); -} -#[test] -pub fn given_a_driver_project_when_makecert_command_execution_fails_then_package_should_fail() { - let test_context = BuildTestContext::default().with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - - let expected_output = Output { - status: ExitStatus::from_raw(1), - stdout: vec![], - stderr: vec![], - }; + let build_action = initialize_build_action(&mut test_build_action); + let result = build_action.run_from_workspace_root(&cwd); - let cargo_build_output = default_standalone_build_output(&test_context); - - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_stampinf(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) - .expect_inf2cat(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) - .expect_self_signed_cert_file_exists(&cwd, false) - .expect_certmgr_exists_check(None) - .expect_makecert(&cwd, Some(expected_output)) - }, - assert_workspace_member_build_failed, - ); + assert!(result.is_ok(), "build action failed unexpectedly: {result:?}"); } #[test] -pub fn given_a_driver_project_when_signtool_command_execution_fails_then_package_should_fail() { - let test_context = BuildTestContext::default().with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - - let cargo_build_output = default_standalone_build_output(&test_context); - - let expected_output = Output { - status: ExitStatus::from_raw(1), - stdout: vec![], - stderr: vec![], - }; +fn given_a_non_driver_package_when_building_then_package_runner_is_skipped() { + let cwd = PathBuf::from(r"C:\tmp\non-driver"); + let mut test_build_action = TestBuildAction::new(cwd.clone(), None, None, false, false) + .set_up_standalone_driver_project(DEFAULT_DRIVER_NAME, None); - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_stampinf(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) - .expect_inf2cat(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) - .expect_self_signed_cert_file_exists(&cwd, false) - .expect_certmgr_exists_check(None) - .expect_makecert(&cwd, None) - .expect_copy_self_signed_cert_file_to_package_folder( - DEFAULT_DRIVER_NAME, - &cwd, - true, - ) - .expect_signtool_sign_driver_binary_sys_file( - DEFAULT_DRIVER_NAME, - &cwd, - Some(expected_output), - ) - }, - assert_workspace_member_build_failed, + test_build_action.expect_build_runner( + DEFAULT_DRIVER_NAME, + &cwd, + None, + None, + Ok(cargo_build_messages( + DEFAULT_DRIVER_NAME, + DEFAULT_DRIVER_VERSION, + &cwd, + None, + None, + )), ); -} + test_build_action.mock_package_task_runner.expect_run().never(); -#[test] -pub fn given_a_driver_project_when_infverif_command_execution_fails_then_package_should_fail() { - let test_context = BuildTestContext::default().with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - - let cargo_build_output = default_standalone_build_output(&test_context); - - let expected_output = Output { - status: ExitStatus::from_raw(1), - stdout: vec![], - stderr: vec![], - }; + let build_action = initialize_build_action(&mut test_build_action); + let result = build_action.run_from_workspace_root(&cwd); - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_inx_file_exists(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(DEFAULT_DRIVER_NAME, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_pdb_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_copy_inx_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(DEFAULT_DRIVER_NAME, &cwd, true) - .expect_stampinf(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) - .expect_inf2cat(DEFAULT_DRIVER_NAME, &cwd, target_arch, None) - .expect_self_signed_cert_file_exists(&cwd, false) - .expect_certmgr_exists_check(None) - .expect_makecert(&cwd, None) - .expect_copy_self_signed_cert_file_to_package_folder( - DEFAULT_DRIVER_NAME, - &cwd, - true, - ) - .expect_signtool_sign_driver_binary_sys_file(DEFAULT_DRIVER_NAME, &cwd, None) - .expect_signtool_sign_cat_file(DEFAULT_DRIVER_NAME, &cwd, None) - .expect_infverif(DEFAULT_DRIVER_NAME, &cwd, DEFAULT_DRIVER_TYPE, Some(expected_output)) - }, - assert_workspace_member_build_failed, - ); + assert!(result.is_ok(), "build action failed unexpectedly: {result:?}"); } #[test] -pub fn given_a_non_driver_project_when_default_values_are_provided_with_no_wdk_metadata_are_provided_then_build_should_be_successful() - { - let test_context = BuildTestContext::default().with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let driver_name = "non-driver"; - let driver_version = "0.0.1"; - let (workspace_member, package) = - get_cargo_metadata_package(&cwd, driver_name, driver_version, None); - - set_up_and_assert( - test_context, - BuildActionRunMode::Direct, - |test_build_action| { - test_build_action - .set_up_standalone_driver_project((workspace_member, package)) - .expect_default_build_task_steps(driver_name, None) - }, - assert_build_action_success, - ); -} +fn given_a_driver_package_without_cdylib_when_building_then_package_runner_is_skipped() { + let cwd = PathBuf::from(r"C:\tmp\driver-lib"); + let mut test_build_action = TestBuildAction::new(cwd.clone(), None, None, false, false) + .set_up_with_custom_toml(&get_cargo_metadata( + &cwd, + vec![get_cargo_metadata_package_with_target( + &cwd, + DEFAULT_DRIVER_NAME, + DEFAULT_DRIVER_VERSION, + Some(default_wdk_metadata()), + "lib", + "lib", + "lib.rs", + ) + .1], + &[get_cargo_metadata_package_with_target( + &cwd, + DEFAULT_DRIVER_NAME, + DEFAULT_DRIVER_VERSION, + Some(default_wdk_metadata()), + "lib", + "lib", + "lib.rs", + ) + .0], + None, + )); -#[test] -pub fn given_a_invalid_driver_project_with_partial_wdk_metadata_when_valid_default_values_are_provided_then_wdk_metadata_parse_should_fail() - { - let test_context = - BuildTestContext::default().with_cwd("C:\\tmp\\sample-driver").with_verify_signature(true); - let driver_name = "sample-driver"; - let cargo_toml_metadata = invalid_driver_cargo_toml(); - - set_up_and_assert( - test_context, - BuildActionRunMode::Direct, - |test_build_action| { - test_build_action - .set_up_with_custom_toml(&cargo_toml_metadata) - .expect_default_build_task_steps(driver_name, None) - }, - assert_wdk_metadata_deserialization_failed, + test_build_action.expect_build_runner( + DEFAULT_DRIVER_NAME, + &cwd, + None, + None, + Ok(Vec::new()), ); -} - -#[test] -pub fn given_a_driver_project_when_target_arch_is_not_provided_and_probing_cargo_rustc_fails_then_packaging_should_fail() - { - let test_context = BuildTestContext::default(); - let cwd = test_context.cwd.clone(); - let cargo_build_output = default_standalone_build_output(&test_context); + test_build_action.mock_package_task_runner.expect_run().never(); - let cargo_rustc_output = Output { - status: ExitStatus::from_raw(1), - stdout: vec![], - stderr: vec![], - }; + let build_action = initialize_build_action(&mut test_build_action); + let result = build_action.run_from_workspace_root(&cwd); - set_up_and_assert( - test_context, - BuildActionRunMode::Direct, - |test_build_action| { - set_up_default_standalone_driver_project(test_build_action, &cwd) - .expect_default_build_task_steps(DEFAULT_DRIVER_NAME, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc( - &cwd, - DEFAULT_TARGET_ARCH, - Some(cargo_rustc_output), - ) - }, - assert_workspace_member_build_failed, - ); + assert!(result.is_ok(), "build action failed unexpectedly: {result:?}"); } -//////////////////////////////////////////////////////////////////////////////// -/// Workspace tests -//////////////////////////////////////////////////////////////////////////////// #[test] -pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_default_values_are_provided_then_it_packages_successfully() - { - let test_context = BuildTestContext::default().with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - let driver_type = "KMDF"; +fn given_a_workspace_root_when_one_member_fails_then_workspace_error_is_returned() { + let workspace_root = PathBuf::from(r"C:\tmp\workspace"); let driver_name_1 = "sample-kmdf-1"; - let driver_version_1 = "0.0.1"; let driver_name_2 = "sample-kmdf-2"; - let driver_version_2 = "0.0.2"; - let non_driver = "non-driver"; - let non_driver_version = "0.0.3"; - - // Create artifact outputs for workspace packages - let artifact_1 = create_cargo_build_output_json_with_manifest( + let driver_dir_1 = workspace_root.join(driver_name_1); + let driver_dir_2 = workspace_root.join(driver_name_2); + let target_arch = CpuArchitecture::Amd64; + let target_dir_1 = expected_target_dir(&driver_dir_1, Some(target_arch), None); + let target_triple = to_target_triple(target_arch); + let mut test_build_action = + TestBuildAction::new(workspace_root.clone(), None, Some(target_arch), false, false) + .set_up_workspace_with_multiple_driver_projects( + &workspace_root, + vec![ + ( + driver_name_1, + driver_dir_1.clone(), + Some(default_wdk_metadata()), + "cdylib", + "cdylib", + "main.rs", + ), + ( + driver_name_2, + driver_dir_2.clone(), + Some(default_wdk_metadata()), + "cdylib", + "cdylib", + "main.rs", + ), + ], + ); + + test_build_action.expect_build_runner( driver_name_1, - driver_version_1, - &cwd, - &cwd.join(driver_name_1).join("Cargo.toml"), + &driver_dir_1, None, - test_context.profile, - true, + Some(target_arch), + Ok(cargo_build_messages( + driver_name_1, + DEFAULT_DRIVER_VERSION, + &driver_dir_1, + Some(target_triple.as_str()), + None, + )), ); - let artifact_2 = create_cargo_build_output_json_with_manifest( + test_build_action.expect_build_runner( driver_name_2, - driver_version_2, - &cwd, - &cwd.join(driver_name_2).join("Cargo.toml"), + &driver_dir_2, None, - test_context.profile, - true, - ); - let artifact_non_driver = create_cargo_build_output_json_with_manifest( - non_driver, - non_driver_version, - &cwd, - &cwd.join(non_driver).join("Cargo.toml"), - None, - test_context.profile, - false, + Some(target_arch), + Err(build_task_error()), ); - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member_1, package_1) = get_cargo_metadata_package( - &cwd.join(driver_name_1), + test_build_action.expect_package_runner( driver_name_1, - driver_version_1, - Some(&wdk_metadata), - ); - let (workspace_member_2, package_2) = get_cargo_metadata_package( - &cwd.join(driver_name_2), - driver_name_2, - driver_version_2, - Some(&wdk_metadata), - ); - let (workspace_member_3, package_3) = - get_cargo_metadata_package(&cwd.join(non_driver), non_driver, non_driver_version, None); - - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - test_build_action - .set_up_workspace_with_multiple_driver_projects( - &cwd, - Some(wdk_metadata), - vec![ - (workspace_member_1, package_1), - (workspace_member_2, package_2), - (workspace_member_3, package_3), - ], - ) - .expect_detect_wdk_build_number(25100u32) - .expect_root_manifest_exists(&cwd, true) - .expect_cargo_build(driver_name_1, &cwd.join(driver_name_1), Some(artifact_1)) - .expect_probe_target_arch_using_cargo_rustc( - &cwd.join(driver_name_1), - target_arch, - None, - ) - .expect_default_package_task_steps_for_workspace( - driver_name_1, - driver_type, - target_arch, - true, - ) - .expect_cargo_build(driver_name_2, &cwd.join(driver_name_2), Some(artifact_2)) - .expect_probe_target_arch_using_cargo_rustc( - &cwd.join(driver_name_2), - target_arch, - None, - ) - .expect_default_package_task_steps_for_workspace( - driver_name_2, - driver_type, - target_arch, - true, - ) - .expect_cargo_build(non_driver, &cwd.join(non_driver), Some(artifact_non_driver)) - }, - assert_build_action_success, + &driver_dir_1, + &target_dir_1, + target_arch, + false, + false, ); + + let build_action = initialize_build_action(&mut test_build_action); + let result = build_action.run_from_workspace_root(&workspace_root); + + assert!(matches!( + result, + Err(BuildActionError::OneOrMoreWorkspaceMembersFailedToBuild(path)) + if path == workspace_root + )); } #[test] -pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_cwd_is_driver_project_then_it_packages_driver_project_successfully() - { - let workspace_root_dir = PathBuf::from("C:\\tmp"); - let test_context = BuildTestContext::default() - .with_cwd(workspace_root_dir.join("sample-kmdf-1")) - .with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - let driver_type = "KMDF"; +fn given_a_workspace_member_directory_when_building_then_only_that_member_is_orchestrated() { + let workspace_root = PathBuf::from(r"C:\tmp\workspace"); let driver_name_1 = "sample-kmdf-1"; - let driver_version_1 = "0.0.1"; let driver_name_2 = "sample-kmdf-2"; - let driver_version_2 = "0.0.2"; - let non_driver = "non-driver"; - let non_driver_version = "0.0.3"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member_1, package_1) = get_cargo_metadata_package( - &workspace_root_dir.join(driver_name_1), - driver_name_1, - driver_version_1, - Some(&wdk_metadata), - ); - let (workspace_member_2, package_2) = get_cargo_metadata_package( - &workspace_root_dir.join(driver_name_2), + let driver_dir_1 = workspace_root.join(driver_name_1); + let driver_dir_2 = workspace_root.join(driver_name_2); + let target_arch = CpuArchitecture::Amd64; + let target_dir_2 = expected_target_dir(&driver_dir_2, Some(target_arch), None); + let target_triple = to_target_triple(target_arch); + let mut test_build_action = + TestBuildAction::new(driver_dir_2.clone(), None, Some(target_arch), false, false) + .set_up_workspace_with_multiple_driver_projects( + &workspace_root, + vec![ + ( + driver_name_1, + driver_dir_1.clone(), + Some(default_wdk_metadata()), + "cdylib", + "cdylib", + "main.rs", + ), + ( + driver_name_2, + driver_dir_2.clone(), + Some(default_wdk_metadata()), + "cdylib", + "cdylib", + "main.rs", + ), + ], + ); + + test_build_action.expect_build_runner( driver_name_2, - driver_version_2, - Some(&wdk_metadata), - ); - let (workspace_member_3, package_3) = get_cargo_metadata_package( - &workspace_root_dir.join(non_driver), - non_driver, - non_driver_version, + &driver_dir_2, None, + Some(target_arch), + Ok(cargo_build_messages( + driver_name_2, + DEFAULT_DRIVER_VERSION, + &driver_dir_2, + Some(target_triple.as_str()), + None, + )), ); - - let expected_certmgr_output = get_certmgr_success_output(); - - let cargo_build_output = create_cargo_build_output_json_with_manifest( - driver_name_1, - driver_version_1, - &workspace_root_dir, - &workspace_root_dir.join(driver_name_1).join("Cargo.toml"), - None, - test_context.profile, - true, + test_build_action.expect_package_runner( + driver_name_2, + &driver_dir_2, + &target_dir_2, + target_arch, + false, + false, ); - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - test_build_action - .set_up_workspace_with_multiple_driver_projects( - &workspace_root_dir, - Some(wdk_metadata), - vec![ - (workspace_member_1, package_1), - (workspace_member_2, package_2), - (workspace_member_3, package_3), - ], - ) - .expect_detect_wdk_build_number(25100u32) - .expect_root_manifest_exists(&cwd, true) - .expect_cargo_build(driver_name_1, &cwd, Some(cargo_build_output)) - .expect_probe_target_arch_using_cargo_rustc(&cwd, target_arch, None) - .expect_final_package_dir_exists(driver_name_1, &workspace_root_dir, true) - .expect_inx_file_exists(driver_name_1, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(driver_name_1, &workspace_root_dir) - .expect_copy_driver_binary_sys_to_package_folder( - driver_name_1, - &workspace_root_dir, - true, - ) - .expect_copy_pdb_file_to_package_folder(driver_name_1, &workspace_root_dir, true) - .expect_copy_inx_file_to_package_folder( - driver_name_1, - &cwd, - true, - &workspace_root_dir, - ) - .expect_copy_map_file_to_package_folder(driver_name_1, &workspace_root_dir, true) - .expect_stampinf(driver_name_1, &workspace_root_dir, target_arch, None) - .expect_inf2cat(driver_name_1, &workspace_root_dir, target_arch, None) - .expect_self_signed_cert_file_exists(&workspace_root_dir, false) - .expect_certmgr_exists_check(Some(expected_certmgr_output)) - .expect_makecert(&workspace_root_dir, None) - .expect_copy_self_signed_cert_file_to_package_folder( - driver_name_1, - &workspace_root_dir, - true, - ) - .expect_signtool_sign_driver_binary_sys_file( - driver_name_1, - &workspace_root_dir, - None, - ) - .expect_signtool_sign_cat_file(driver_name_1, &workspace_root_dir, None) - .expect_signtool_verify_driver_binary_sys_file( - driver_name_1, - &workspace_root_dir, - None, - ) - .expect_signtool_verify_cat_file(driver_name_1, &workspace_root_dir, None) - .expect_infverif(driver_name_1, &workspace_root_dir, "KMDF", None) - }, - assert_build_action_success, - ); + let build_action = initialize_build_action(&mut test_build_action); + let result = build_action.run_from_workspace_root(&driver_dir_2); + + assert!(result.is_ok(), "build action failed unexpectedly: {result:?}"); } #[test] -pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_verify_signature_is_false_then_it_skips_verify_tasks() - { - let test_context = BuildTestContext::default(); - let cwd = test_context.cwd.clone(); - let target_arch = test_context.default_target_arch(); - let driver_type = "KMDF"; - let driver_name_1 = "sample-kmdf-1"; - let driver_version_1 = "0.0.1"; - let driver_name_2 = "sample-kmdf-2"; - let driver_version_2 = "0.0.2"; - let non_driver = "non-driver"; - let non_driver_version = "0.0.3"; +fn given_an_emulated_workspace_when_running_then_each_valid_project_is_built() { + let emulated_workspace = TestWorkspaceRoot::new("build-action-emulated-workspace"); + let driver_name_1 = "driver-a"; + let driver_name_2 = "driver-b"; + let ignored_dir = "docs"; + let driver_dir_1 = emulated_workspace.root.join(driver_name_1); + let driver_dir_2 = emulated_workspace.root.join(driver_name_2); + let ignored_dir_path = emulated_workspace.root.join(ignored_dir); + fs::create_dir_all(&driver_dir_1).expect("failed to create driver-a directory"); + fs::create_dir_all(&driver_dir_2).expect("failed to create driver-b directory"); + fs::create_dir_all(&ignored_dir_path).expect("failed to create docs directory"); + + let target_arch = CpuArchitecture::Amd64; + let target_dir_1 = expected_target_dir(&driver_dir_1, Some(target_arch), None); + let target_dir_2 = expected_target_dir(&driver_dir_2, Some(target_arch), None); + let target_triple = to_target_triple(target_arch); + let mut test_build_action = TestBuildAction::new( + emulated_workspace.root.clone(), + None, + Some(target_arch), + false, + false, + ); - // Create artifact outputs for workspace packages - let artifact_1 = create_cargo_build_output_json_with_manifest( + test_build_action.expect_detect_wdk_build_number(25100); + test_build_action.expect_root_manifest_exists(&emulated_workspace.root, false); + test_build_action.expect_read_dir_entries(&emulated_workspace.root); + test_build_action.expect_dir_file_types(); + test_build_action.expect_dir_cargo_toml_exists(&driver_dir_1, true); + test_build_action.expect_dir_cargo_toml_exists(&driver_dir_1, true); + test_build_action.expect_dir_cargo_toml_exists(&driver_dir_2, true); + test_build_action.expect_dir_cargo_toml_exists(&ignored_dir_path, false); + test_build_action.expect_dir_cargo_toml_exists(&ignored_dir_path, false); + test_build_action.expect_metadata_for_paths(vec![ + ( + driver_dir_1.clone(), + metadata_from_packages( + &driver_dir_1, + vec![( + driver_name_1, + driver_dir_1.clone(), + Some(default_wdk_metadata()), + "cdylib", + "cdylib", + "main.rs", + )], + ), + ), + ( + driver_dir_2.clone(), + metadata_from_packages( + &driver_dir_2, + vec![( + driver_name_2, + driver_dir_2.clone(), + Some(default_wdk_metadata()), + "cdylib", + "cdylib", + "main.rs", + )], + ), + ), + ]); + test_build_action.expect_build_runner( driver_name_1, - driver_version_1, - &cwd, - &cwd.join(driver_name_1).join("Cargo.toml"), + &driver_dir_1, None, - test_context.profile, - true, + Some(target_arch), + Ok(cargo_build_messages( + driver_name_1, + DEFAULT_DRIVER_VERSION, + &driver_dir_1, + Some(target_triple.as_str()), + None, + )), ); - let artifact_2 = create_cargo_build_output_json_with_manifest( + test_build_action.expect_build_runner( driver_name_2, - driver_version_2, - &cwd, - &cwd.join(driver_name_2).join("Cargo.toml"), - None, - test_context.profile, - true, - ); - let artifact_non_driver = create_cargo_build_output_json_with_manifest( - non_driver, - non_driver_version, - &cwd, - &cwd.join(non_driver).join("Cargo.toml"), + &driver_dir_2, None, - test_context.profile, - false, // NOT a driver - will use "lib" instead of "cdylib" + Some(target_arch), + Ok(cargo_build_messages( + driver_name_2, + DEFAULT_DRIVER_VERSION, + &driver_dir_2, + Some(target_triple.as_str()), + None, + )), ); - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member_1, package_1) = get_cargo_metadata_package( - &cwd.join(driver_name_1), + test_build_action.expect_package_runner( driver_name_1, - driver_version_1, - Some(&wdk_metadata), + &driver_dir_1, + &target_dir_1, + target_arch, + false, + false, ); - let (workspace_member_2, package_2) = get_cargo_metadata_package( - &cwd.join(driver_name_2), + test_build_action.expect_package_runner( driver_name_2, - driver_version_2, - Some(&wdk_metadata), - ); - let (workspace_member_3, package_3) = - get_cargo_metadata_package(&cwd.join(non_driver), non_driver, non_driver_version, None); - - set_up_and_assert( - test_context, - BuildActionRunMode::WithEnv, - |test_build_action| { - test_build_action - .set_up_workspace_with_multiple_driver_projects( - &cwd, - Some(wdk_metadata), - vec![ - (workspace_member_1, package_1), - (workspace_member_2, package_2), - (workspace_member_3, package_3), - ], - ) - .expect_detect_wdk_build_number(25100u32) - .expect_root_manifest_exists(&cwd, true) - .expect_cargo_build(driver_name_1, &cwd.join(driver_name_1), Some(artifact_1)) - .expect_probe_target_arch_using_cargo_rustc( - &cwd.join(driver_name_1), - target_arch, - None, - ) - .expect_default_package_task_steps_for_workspace( - driver_name_1, - driver_type, - target_arch, - false, - ) - .expect_cargo_build(driver_name_2, &cwd.join(driver_name_2), Some(artifact_2)) - .expect_probe_target_arch_using_cargo_rustc( - &cwd.join(driver_name_2), - target_arch, - None, - ) - .expect_default_package_task_steps_for_workspace( - driver_name_2, - driver_type, - target_arch, - false, - ) - .expect_cargo_build(non_driver, &cwd.join(non_driver), Some(artifact_non_driver)) - }, - assert_build_action_success, + &driver_dir_2, + &target_dir_2, + target_arch, + false, + false, ); + + let build_action = initialize_build_action(&mut test_build_action); + let result = crate::test_utils::with_env::<&str, &str, _, _>(&[], || build_action.run()); + + assert!(result.is_ok(), "build action failed unexpectedly: {result:?}"); } #[test] -pub fn given_a_workspace_with_multiple_driver_and_non_driver_projects_when_cwd_is_non_driver_project_then_it_builds_but_skips_packaging() - { - let workspace_root_dir = PathBuf::from("C:\\tmp"); - let test_context = BuildTestContext::default() - .with_cwd(workspace_root_dir.join("non-driver")) - .with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let driver_type = "KMDF"; - let driver_name_1 = "sample-kmdf-1"; - let driver_version_1 = "0.0.1"; - let driver_name_2 = "sample-kmdf-2"; - let driver_version_2 = "0.0.2"; - let non_driver = "non-driver"; - let non_driver_version = "0.0.3"; - let wdk_metadata = get_cargo_metadata_wdk_metadata(driver_type, 1, 33); - let (workspace_member_1, package_1) = get_cargo_metadata_package( - &workspace_root_dir.join(driver_name_1), - driver_name_1, - driver_version_1, - Some(&wdk_metadata), - ); - let (workspace_member_2, package_2) = get_cargo_metadata_package( - &workspace_root_dir.join(driver_name_2), - driver_name_2, - driver_version_2, - Some(&wdk_metadata), - ); - let (workspace_member_3, package_3) = get_cargo_metadata_package( - &workspace_root_dir.join(non_driver), - non_driver, - non_driver_version, +fn given_a_workspace_member_when_build_runner_fails_then_the_build_error_is_propagated() { + let workspace_root = PathBuf::from(r"C:\tmp\workspace"); + let cwd = workspace_root.join(DEFAULT_DRIVER_NAME); + let mut test_build_action = + TestBuildAction::new(cwd.clone(), None, None, false, false) + .set_up_workspace_with_multiple_driver_projects( + &workspace_root, + vec![( + DEFAULT_DRIVER_NAME, + cwd.clone(), + Some(default_wdk_metadata()), + "cdylib", + "cdylib", + "main.rs", + )], + ); + + test_build_action.expect_build_runner( + DEFAULT_DRIVER_NAME, + &cwd, None, + None, + Err(build_task_error()), ); - set_up_and_assert( - test_context, - BuildActionRunMode::Direct, - |test_build_action| { - test_build_action - .set_up_workspace_with_multiple_driver_projects( - &workspace_root_dir, - Some(wdk_metadata), - vec![ - (workspace_member_1, package_1), - (workspace_member_2, package_2), - (workspace_member_3, package_3), - ], - ) - .expect_detect_wdk_build_number(25100u32) - .expect_root_manifest_exists(&cwd, true) - .expect_cargo_build(non_driver, &cwd, None) - }, - assert_build_action_success, - ); -} - -#[test] -pub fn given_a_workspace_with_multiple_distinct_wdk_configurations_at_each_workspace_member_level_when_default_values_are_provided_then_wdk_metadata_parse_should_fail() - { - let test_context = BuildTestContext::default().with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let driver_type_1 = "KMDF"; - let driver_name_1 = "sample-kmdf-1"; - let driver_type_2 = "UMDF"; - let driver_version_1 = "0.0.1"; - let driver_name_2 = "sample-kmdf-2"; - let driver_version_2 = "0.0.2"; - let wdk_metadata_1 = get_cargo_metadata_wdk_metadata(driver_type_1, 1, 33); - let wdk_metadata_2 = get_cargo_metadata_wdk_metadata(driver_type_2, 1, 33); - let (workspace_member_1, package_1) = get_cargo_metadata_package( - &cwd.join(driver_name_1), - driver_name_1, - driver_version_1, - Some(&wdk_metadata_1), - ); - let (workspace_member_2, package_2) = get_cargo_metadata_package( - &cwd.join(driver_name_2), - driver_name_2, - driver_version_2, - Some(&wdk_metadata_2), - ); - - set_up_and_assert( - test_context, - BuildActionRunMode::Direct, - |test_build_action| { - test_build_action - .set_up_workspace_with_multiple_driver_projects( - &cwd, - Some(wdk_metadata_1), - vec![ - (workspace_member_1, package_1), - (workspace_member_2, package_2), - ], - ) - .expect_detect_wdk_build_number(25100u32) - .expect_root_manifest_exists(&cwd, true) - .expect_cargo_build(driver_name_1, &cwd.join(driver_name_1), None) - .expect_cargo_build(driver_name_2, &cwd.join(driver_name_2), None) - }, - assert_multiple_wdk_configurations_detected, - ); -} - -#[test] -pub fn given_a_workspace_with_multiple_distinct_wdk_configurations_at_root_and_workspace_member_level_when_default_values_are_provided_then_wdk_metadata_parse_should_fail() - { - let test_context = BuildTestContext::default().with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let driver_type_1 = "KMDF"; - let driver_name_1 = "sample-kmdf-1"; - let driver_type_2 = "UMDF"; - let driver_version_1 = "0.0.1"; - let driver_name_2 = "sample-kmdf-2"; - let driver_version_2 = "0.0.2"; - let wdk_metadata_1 = get_cargo_metadata_wdk_metadata(driver_type_1, 1, 33); - let wdk_metadata_2 = get_cargo_metadata_wdk_metadata(driver_type_2, 1, 33); - let (workspace_member_1, package_1) = get_cargo_metadata_package( - &cwd.join(driver_name_1), - driver_name_1, - driver_version_1, - Some(&wdk_metadata_1), - ); - let (workspace_member_2, package_2) = get_cargo_metadata_package( - &cwd.join(driver_name_2), - driver_name_2, - driver_version_2, - Some(&wdk_metadata_1), - ); - - set_up_and_assert( - test_context, - BuildActionRunMode::Direct, - |test_build_action| { - test_build_action - .set_up_workspace_with_multiple_driver_projects( - &cwd, - Some(wdk_metadata_2), - vec![ - (workspace_member_1, package_1), - (workspace_member_2, package_2), - ], - ) - .expect_root_manifest_exists(&cwd, true) - .expect_detect_wdk_build_number(25100u32) - .expect_cargo_build(driver_name_1, &cwd.join(driver_name_1), None) - .expect_cargo_build(driver_name_2, &cwd.join(driver_name_2), None) - }, - assert_multiple_wdk_configurations_detected, - ); -} - -#[test] -pub fn given_a_workspace_only_with_non_driver_projects_when_cwd_is_workspace_root_then_build_should_be_successful() - { - let test_context = BuildTestContext::default().with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let non_driver = "non-driver"; - let non_driver_version = "0.0.3"; - let (workspace_member_3, package_3) = - get_cargo_metadata_package(&cwd.join(non_driver), non_driver, non_driver_version, None); - - set_up_and_assert( - test_context, - BuildActionRunMode::Direct, - |test_build_action| { - test_build_action - .set_up_workspace_with_multiple_driver_projects( - &cwd, - None, - vec![(workspace_member_3, package_3)], - ) - .expect_root_manifest_exists(&cwd, true) - .expect_detect_wdk_build_number(25100u32) - .expect_cargo_build(non_driver, &cwd.join(non_driver), None) - }, - assert_build_action_success, - ); -} - -#[test] -pub fn given_a_workspace_only_with_non_driver_projects_when_cwd_is_workspace_member_then_build_should_be_successful() - { - let workspace_root_dir = PathBuf::from("C:\\tmp"); - let test_context = BuildTestContext::default() - .with_cwd(workspace_root_dir.join("non-driver")) - .with_verify_signature(true); - let cwd = test_context.cwd.clone(); - let non_driver = "non-driver"; - let non_driver_version = "0.0.3"; - let (workspace_member_3, package_3) = get_cargo_metadata_package( - &workspace_root_dir.join(non_driver), - non_driver, - non_driver_version, - None, - ); - - set_up_and_assert( - test_context, - BuildActionRunMode::Direct, - |test_build_action| { - test_build_action - .set_up_workspace_with_multiple_driver_projects( - &workspace_root_dir, - None, - vec![(workspace_member_3, package_3)], - ) - .expect_root_manifest_exists(&cwd, true) - .expect_detect_wdk_build_number(25100u32) - .expect_cargo_build(non_driver, &cwd, None) - }, - assert_build_action_success, - ); -} - -const DEFAULT_DRIVER_TYPE: &str = "KMDF"; -const DEFAULT_DRIVER_NAME: &str = "sample-kmdf"; -const DEFAULT_DRIVER_VERSION: &str = "0.0.1"; -const DEFAULT_TARGET_ARCH: CpuArchitecture = CpuArchitecture::Amd64; - -#[derive(Clone, Copy)] -enum BuildActionRunMode { - Direct, - WithEnv, -} - -#[derive(Clone)] -struct BuildTestContext { - cwd: PathBuf, - profile: Option, - target_arch: Option, - verify_signature: bool, - sample_class: bool, -} + let build_action = initialize_build_action(&mut test_build_action); + let result = build_action.run_from_workspace_root(&cwd); -impl Default for BuildTestContext { - fn default() -> Self { - Self { - cwd: PathBuf::from("C:\\tmp"), - profile: None, - target_arch: None, - verify_signature: false, - sample_class: false, - } - } + assert!(matches!(result, Err(BuildActionError::BuildTask(_)))); } -impl BuildTestContext { - fn with_cwd(mut self, cwd: impl Into) -> Self { - self.cwd = cwd.into(); - self - } - - fn with_profile(mut self, profile: Profile) -> Self { - self.profile = Some(profile); - self - } - - fn with_target_arch(mut self, target_arch: CpuArchitecture) -> Self { - self.target_arch = Some(target_arch); - self - } - - fn with_verify_signature(mut self, verify_signature: bool) -> Self { - self.verify_signature = verify_signature; - self - } - - fn with_sample_class(mut self, sample_class: bool) -> Self { - self.sample_class = sample_class; - self - } - - fn default_target_arch(&self) -> CpuArchitecture { - self.target_arch.unwrap_or(DEFAULT_TARGET_ARCH) - } -} - -fn set_up_and_assert( - test_context: BuildTestContext, - run_mode: BuildActionRunMode, - set_expectations_fn: SetupFn, - assert_fn: AssertFn, -) where - SetupFn: FnOnce(TestBuildAction) -> TestBuildAction, - AssertFn: FnOnce(Result<(), BuildActionError>), -{ - let test_build_action = set_expectations_fn(TestBuildAction::new( - test_context.cwd.clone(), - test_context.profile, - test_context.target_arch, - test_context.sample_class, - )); - let build_action = initialize_build_action( - &test_context.cwd, - test_context.profile.as_ref(), - test_context.target_arch, - test_context.verify_signature, - test_context.sample_class, - &test_build_action, - ); - assert!(build_action.is_ok()); - let build_action = build_action.expect("Failed to init build action"); - let run_result = match run_mode { - BuildActionRunMode::Direct => build_action.run(), - BuildActionRunMode::WithEnv => { - crate::test_utils::with_env::<&str, &str, _, _>(&[], || build_action.run()) - } - }; - assert_fn(run_result); -} - -fn initialize_build_action<'a>( - cwd: &'a PathBuf, - profile: Option<&'a Profile>, - target_arch: Option, - verify_signature: bool, - sample_class: bool, - test_build_action: &'a TestBuildAction, -) -> Result, anyhow::Error> { - BuildAction::new( +fn initialize_build_action(test_build_action: &mut TestBuildAction) -> BuildAction<'_> { + BuildAction::new_with_runners( &BuildActionParams { - working_dir: cwd, - profile, - target_arch, - verify_signature, - is_sample_class: sample_class, + working_dir: &test_build_action.cwd, + profile: test_build_action.profile.as_ref(), + target_arch: test_build_action.target_arch, + verify_signature: test_build_action.verify_signature, + is_sample_class: test_build_action.sample_class, verbosity_level: clap_verbosity_flag::Verbosity::new(1, 0), }, - test_build_action.mock_wdk_build_provider(), - test_build_action.mock_run_command(), - test_build_action.mock_fs_provider(), - test_build_action.mock_metadata_provider(), + &test_build_action.mock_wdk_build_provider, + &test_build_action.mock_run_command, + &test_build_action.mock_fs_provider, + &test_build_action.mock_metadata_provider, + std::mem::take(&mut test_build_action.mock_build_task_runner), + std::mem::take(&mut test_build_action.mock_package_task_runner), ) + .expect("failed to initialize build action") } -fn get_certmgr_success_output() -> Output { - Output { - status: ExitStatus::default(), - stdout: r"==============No Certificates ========== - ==============No CTLs ========== - ==============No CRLs ========== - ============================================== - CertMgr Succeeded" - .as_bytes() - .to_vec(), - stderr: vec![], - } -} - -fn default_standalone_build_output(test_context: &BuildTestContext) -> Output { - let target_triple = test_context.target_arch.map(to_target_triple); - create_cargo_build_output_json( - DEFAULT_DRIVER_NAME, - DEFAULT_DRIVER_VERSION, - &test_context.cwd, - target_triple.as_deref(), - test_context.profile, - ) +fn default_wdk_metadata() -> TestWdkMetadata { + get_cargo_metadata_wdk_metadata("KMDF", 1, 33) } -fn set_up_default_standalone_driver_project( - test_build_action: TestBuildAction, +fn expected_target_dir( cwd: &Path, -) -> TestBuildAction { - let wdk_metadata = get_cargo_metadata_wdk_metadata(DEFAULT_DRIVER_TYPE, 1, 33); - let package_metadata = - get_cargo_metadata_package(cwd, DEFAULT_DRIVER_NAME, DEFAULT_DRIVER_VERSION, Some(&wdk_metadata)); - test_build_action.set_up_standalone_driver_project(package_metadata) -} - -fn assert_build_action_success(result: Result<(), BuildActionError>) { - assert!(result.is_ok(), "build action failed unexpectedly: {result:?}"); -} - -fn assert_workspace_member_build_failed(result: Result<(), BuildActionError>) { - assert!(matches!( - result.as_ref().expect_err("expected error"), - BuildActionError::OneOrMoreWorkspaceMembersFailedToBuild(_) - )); + target_arch: Option, + profile: Option, +) -> PathBuf { + let mut target_dir = cwd.join("target"); + if let Some(target_arch) = target_arch { + target_dir = target_dir.join(to_target_triple(target_arch)); + } + target_dir.join(match profile { + Some(Profile::Release) => "release", + _ => "debug", + }) } -fn assert_wdk_metadata_deserialization_failed(result: Result<(), BuildActionError>) { - assert!(matches!( - result.as_ref().expect_err("expected error"), - BuildActionError::WdkMetadataParse(TryFromCargoMetadataError::WdkMetadataDeserialization { - metadata_source: _, - error_source: _ - }) - )); +fn cargo_build_messages( + package_name: &str, + package_version: &str, + cwd: &Path, + target_triple: Option<&str>, + profile: Option, +) -> Vec> { + let output = + create_cargo_build_output_json(package_name, package_version, cwd, target_triple, profile); + Message::parse_stream(io::Cursor::new(output.stdout)).collect() } -fn assert_multiple_wdk_configurations_detected(result: Result<(), BuildActionError>) { - assert!(matches!( - result.expect_err("expected error"), - BuildActionError::WdkMetadataParse( - TryFromCargoMetadataError::MultipleWdkConfigurationsDetected { - wdk_metadata_configurations: _ - } - ) - )); +fn build_task_error() -> super::error::BuildTaskError { + super::error::BuildTaskError::CargoBuild(CommandError::from_output( + "cargo", + &["build"], + &Output { + status: ExitStatus::from_raw(1), + stdout: vec![], + stderr: b"cargo build failed".to_vec(), + }, + )) } -/// Helper functions -//////////////////////////////////////////////////////////////////////////////// struct TestBuildAction { cwd: PathBuf, profile: Option, target_arch: Option, + verify_signature: bool, sample_class: bool, - - cargo_metadata: Option, - // mocks - mock_run_command: CommandExec, - mock_wdk_build_provider: WdkBuild, - mock_fs_provider: Fs, - mock_metadata_provider: MetadataProvider, + mock_run_command: MockCommandExec, + mock_wdk_build_provider: MockWdkBuild, + mock_fs_provider: MockFs, + mock_metadata_provider: MockMetadata, + mock_build_task_runner: BuildTaskRunner, + mock_package_task_runner: PackageTaskRunner, } impl TestBuildAction { @@ -1419,1259 +545,288 @@ impl TestBuildAction { cwd: PathBuf, profile: Option, target_arch: Option, - sample_class: bool, - ) -> Self { - let mock_run_command = CommandExec::default(); - let mock_wdk_build_provider = WdkBuild::default(); - let mock_fs_provider = Fs::default(); - let mock_metadata_provider = MetadataProvider::default(); - - Self { - cwd, - profile, - target_arch, - sample_class, - mock_run_command, - mock_wdk_build_provider, - mock_fs_provider, - mock_metadata_provider, - cargo_metadata: None, - } - } - - fn set_up_standalone_driver_project( - mut self, - package_metadata: (TestMetadataWorkspaceMemberId, TestMetadataPackage), - ) -> Self { - let cargo_toml_metadata = get_cargo_metadata( - &self.cwd, - vec![package_metadata.1], - &[package_metadata.0], - None, - ); - let cargo_toml_metadata = - serde_json::from_str::(&cargo_toml_metadata) - .expect("Failed to parse cargo metadata in set_up_standalone_driver_project"); - let cargo_toml_metadata_clone = cargo_toml_metadata.clone(); - self.mock_metadata_provider - .expect_get_cargo_metadata_at_path() - .once() - .returning(move |_| Ok(cargo_toml_metadata_clone.clone())); - self.cargo_metadata = Some(cargo_toml_metadata); - self - } - - fn set_up_workspace_with_multiple_driver_projects( - mut self, - workspace_root_dir: &Path, - workspace_additional_metadata: Option, - package_metadata_list: Vec<(TestMetadataWorkspaceMemberId, TestMetadataPackage)>, - ) -> Self { - let cargo_toml_metadata = get_cargo_metadata( - workspace_root_dir, - package_metadata_list.iter().map(|p| p.1.clone()).collect(), - package_metadata_list - .into_iter() - .map(|p| p.0) - .collect::>() - .as_slice(), - workspace_additional_metadata, - ); - let cargo_toml_metadata = serde_json::from_str::( - &cargo_toml_metadata, - ) - .expect("Failed to parse cargo metadata in set_up_workspace_with_multiple_driver_projects"); - let cargo_toml_metadata_clone = cargo_toml_metadata.clone(); - self.mock_metadata_provider - .expect_get_cargo_metadata_at_path() - .once() - .returning(move |_| Ok(cargo_toml_metadata_clone.clone())); - self.cargo_metadata = Some(cargo_toml_metadata); - self - } - - fn set_up_with_custom_toml(mut self, cargo_toml_metadata: &str) -> Self { - let cargo_toml_metadata = - serde_json::from_str::(cargo_toml_metadata) - .expect("Failed to parse cargo metadata in set_up_with_custom_toml"); - let cargo_toml_metadata_clone = cargo_toml_metadata.clone(); - self.mock_metadata_provider - .expect_get_cargo_metadata_at_path() - .once() - .returning(move |_| Ok(cargo_toml_metadata_clone.clone())); - self.cargo_metadata = Some(cargo_toml_metadata); - self - } - - fn setup_target_dir(&self, dir_path: &Path) -> PathBuf { - let mut base = dir_path.join("target"); - let profile_dir_name = match self.profile { - Some(Profile::Release) => "release", - _ => "debug", - }; - if let Some(target_arch) = self.target_arch { - let triple = to_target_triple(target_arch); - base = base.join(triple); - } - base.join(profile_dir_name) - } -} - -// Presence of method ensures specific mock expectation is set -// Dir argument in any method means to operate on the relevant dir -// Output argument in any method means to override return output from default -// is_success boolean means success result of copy operation -// does_exist boolean means existence of the file or dir -// is_created boolean means whether the dir was created or not -impl TestBuildAction { - fn expect_default_build_task_steps( - self, - driver_name: &str, - cargo_build_output: Option, - ) -> Self { - let cwd = self.cwd.clone(); - self.expect_detect_wdk_build_number(25100u32) - .expect_root_manifest_exists(&cwd, true) - .expect_cargo_build(driver_name, &cwd, cargo_build_output) - } - - fn expect_default_package_task_steps( - self, - driver_name: &str, - driver_type: &str, - target_arch: CpuArchitecture, - verify_signature: bool, - ) -> Self { - let cwd = self.cwd.clone(); - let expected_certmgr_output = get_certmgr_success_output(); - let expectations = self - .expect_final_package_dir_exists(driver_name, &cwd, true) - .expect_inx_file_exists(driver_name, &cwd, true) - .expect_rename_driver_binary_dll_to_sys(driver_name, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(driver_name, &cwd, true) - .expect_copy_pdb_file_to_package_folder(driver_name, &cwd, true) - .expect_copy_inx_file_to_package_folder(driver_name, &cwd, true, &cwd) - .expect_copy_map_file_to_package_folder(driver_name, &cwd, true) - .expect_stampinf(driver_name, &cwd, target_arch, None) - .expect_inf2cat(driver_name, &cwd, target_arch, None) - .expect_self_signed_cert_file_exists(&cwd, false) - .expect_certmgr_exists_check(Some(expected_certmgr_output)) - .expect_makecert(&cwd, None) - .expect_copy_self_signed_cert_file_to_package_folder(driver_name, &cwd, true) - .expect_signtool_sign_driver_binary_sys_file(driver_name, &cwd, None) - .expect_signtool_sign_cat_file(driver_name, &cwd, None) - .expect_infverif(driver_name, &cwd, driver_type, None); - if !verify_signature { - return expectations; - } - expectations - .expect_signtool_verify_driver_binary_sys_file(driver_name, &cwd, None) - .expect_signtool_verify_cat_file(driver_name, &cwd, None) - } - - fn expect_default_package_task_steps_for_workspace( - self, - driver_name: &str, - driver_type: &str, - target_arch: CpuArchitecture, verify_signature: bool, + sample_class: bool, ) -> Self { - let cwd = self.cwd.clone(); - let expected_certmgr_output = get_certmgr_success_output(); - let expectations = self - .expect_final_package_dir_exists(driver_name, &cwd, true) - .expect_inx_file_exists(driver_name, &cwd.join(driver_name), true) - .expect_rename_driver_binary_dll_to_sys(driver_name, &cwd) - .expect_copy_driver_binary_sys_to_package_folder(driver_name, &cwd, true) - .expect_copy_pdb_file_to_package_folder(driver_name, &cwd, true) - .expect_copy_inx_file_to_package_folder(driver_name, &cwd.join(driver_name), true, &cwd) - .expect_copy_map_file_to_package_folder(driver_name, &cwd, true) - .expect_stampinf(driver_name, &cwd, target_arch, None) - .expect_inf2cat(driver_name, &cwd, target_arch, None) - .expect_self_signed_cert_file_exists(&cwd, false) - .expect_certmgr_exists_check(Some(expected_certmgr_output)) - .expect_makecert(&cwd, None) - .expect_copy_self_signed_cert_file_to_package_folder(driver_name, &cwd, true) - .expect_signtool_sign_driver_binary_sys_file(driver_name, &cwd, None) - .expect_signtool_sign_cat_file(driver_name, &cwd, None) - .expect_infverif(driver_name, &cwd, driver_type, None); - if !verify_signature { - return expectations; - } - expectations - .expect_signtool_verify_driver_binary_sys_file(driver_name, &cwd, None) - .expect_signtool_verify_cat_file(driver_name, &cwd, None) - } - - fn expect_root_manifest_exists(mut self, root_dir: &Path, does_exist: bool) -> Self { - self.mock_fs_provider - .expect_exists() - .with(eq(root_dir.join("Cargo.toml"))) - .once() - .returning(move |_| does_exist); - self - } - - fn expect_self_signed_cert_file_exists(mut self, driver_dir: &Path, does_exist: bool) -> Self { - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_src_driver_cert_path = expected_target_dir.join("WDRLocalTestCert.cer"); - self.mock_fs_provider - .expect_exists() - .with(eq(expected_src_driver_cert_path)) - .once() - .returning(move |_| does_exist); - self - } - - fn expect_final_package_dir_exists( - mut self, - driver_name: &str, - cwd: &Path, - does_exist: bool, - ) -> Self { - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(cwd); - let expected_final_package_dir_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}_package")); - self.mock_fs_provider - .expect_exists() - .with(eq(expected_final_package_dir_path)) - .once() - .returning(move |_| does_exist); - self - } - - fn expect_dir_created(mut self, driver_name: &str, cwd: &Path, created: bool) -> Self { - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(cwd); - let expected_final_package_dir_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}_package")); - self.mock_fs_provider - .expect_create_dir() - .with(eq(expected_final_package_dir_path.clone())) - .once() - .returning(move |_| { - if created { - Ok(()) - } else { - Err(FileError::CreateDirError( - expected_final_package_dir_path.clone(), - std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "create error"), - )) - } - }); - self - } - - fn expect_cargo_build( - mut self, - driver_name: &str, - cwd: &Path, - override_output: Option, - ) -> Self { - // cargo build on the package - let expected_cargo_command: &'static str = "cargo"; - let manifest_path = cwd - .join("Cargo.toml") - .to_string_lossy() - .trim_start_matches("\\\\?\\") - .to_string(); - let mut expected_cargo_build_args: Vec = vec![ - "build", - "--message-format=json", - "-p", - &driver_name, - "--manifest-path", - &manifest_path, - ] - .into_iter() - .map(ToString::to_string) - .collect(); - if let Some(profile) = self.profile { - expected_cargo_build_args.push("--profile".to_string()); - expected_cargo_build_args.push(profile.to_string()); - } - - if let Some(target_arch) = self.target_arch { - expected_cargo_build_args.push("--target".to_string()); - expected_cargo_build_args.push(to_target_triple(target_arch)); - } - - expected_cargo_build_args.push("-v".to_string()); - let expected_output = override_output.unwrap_or_else(|| Output { - status: ExitStatus::default(), - stdout: vec![], - stderr: vec![], - }); - self.mock_run_command - .expect_run() - .withf( - move |command: &str, - args: &[&str], - _env_vars: &Option<&HashMap<&str, &str>>, - _working_dir: &Option<&Path>| - -> bool { - command == expected_cargo_command && args == expected_cargo_build_args - }, - ) - .once() - .returning(move |_, _, _, _| Ok(expected_output.clone())); - self - } - - fn expect_probe_target_arch_using_cargo_rustc( - mut self, - driver_dir: &Path, - detected_arch: CpuArchitecture, - override_output: Option, - ) -> Self { - if self.target_arch.is_some() { - println!("`cargo rustc` must not be probed when target architecture is already set"); - return self; - } - let expected_working_dir = driver_dir.to_path_buf(); - let arch_str = match detected_arch { - CpuArchitecture::Amd64 => "x86_64", - CpuArchitecture::Arm64 => "aarch64", - }; - self.mock_run_command - .expect_run() - .withf( - move |command: &str, - args: &[&str], - _env_vars: &Option<&HashMap<&str, &str>>, - working_dir: &Option<&Path>| { - command == "cargo" - && args == ["rustc", "--", "--print", "cfg"] - && working_dir.is_some_and(|d| d == expected_working_dir.as_path()) - }, - ) - .once() - .returning(move |_, _, _, _| match override_output.clone() { - Some(output) => match output.status.code() { - Some(0) => Ok(Output { - status: ExitStatus::from_raw(0), - stdout: vec![], - stderr: vec![], - }), - _ => Err(CommandError::from_output( - "cargo", - &["rustc", "--", "--print", "cfg"], - &output, - )), - }, - None => Ok(Output { - status: ExitStatus::default(), - stdout: format!("target_arch=\"{arch_str}\"\n").as_bytes().to_vec(), - stderr: vec![], - }), - }); - self - } - - fn expect_inx_file_exists( - mut self, - driver_name: &str, - driver_dir: &Path, - does_exist: bool, - ) -> Self { - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_inx_file_path = - driver_dir.join(format!("{expected_driver_name_underscored}.inx")); - self.mock_fs_provider - .expect_exists() - .with(eq(expected_inx_file_path)) - .once() - .returning(move |_| does_exist); - self - } - - fn expect_rename_driver_binary_dll_to_sys( - mut self, - driver_name: &str, - driver_dir: &Path, - ) -> Self { - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_src_driver_dll_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}.dll")); - let expected_src_driver_sys_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}.sys")); - self.mock_fs_provider - .expect_rename() - .with( - eq(expected_src_driver_dll_path), - eq(expected_src_driver_sys_path), - ) - .once() - .returning(|_, _| Ok(())); - self - } - - fn expect_copy_driver_binary_sys_to_package_folder( - mut self, - driver_name: &str, - driver_dir: &Path, - is_success: bool, - ) -> Self { - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_final_package_dir_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}_package")); - let mock_non_zero_bytes_copied_size = 1000u64; - - let expected_src_driver_sys_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}.sys")); - let expected_dest_driver_binary_path = - expected_final_package_dir_path.join(format!("{expected_driver_name_underscored}.sys")); - let expected_src_driver_binary_path = expected_src_driver_sys_path; - self.mock_fs_provider - .expect_copy() - .with( - eq(expected_src_driver_binary_path.clone()), - eq(expected_dest_driver_binary_path.clone()), - ) - .once() - .returning(move |_, _| { - if is_success { - Ok(mock_non_zero_bytes_copied_size) - } else { - Err(FileError::CopyError( - expected_src_driver_binary_path.clone(), - expected_dest_driver_binary_path.clone(), - std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "copy error"), - )) - } - }); - self + Self { + cwd, + profile, + target_arch, + verify_signature, + sample_class, + mock_run_command: MockCommandExec::new(), + mock_wdk_build_provider: MockWdkBuild::new(), + mock_fs_provider: MockFs::new(), + mock_metadata_provider: MockMetadata::new(), + mock_build_task_runner: BuildTaskRunner::default(), + mock_package_task_runner: PackageTaskRunner::default(), + } } - fn expect_copy_pdb_file_to_package_folder( + fn set_up_standalone_driver_project( mut self, - driver_name: &str, - driver_dir: &Path, - is_success: bool, + package_name: &str, + metadata: Option, ) -> Self { - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_final_package_dir_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}_package")); - let mock_non_zero_bytes_copied_size = 1000u64; - - // copy pdb file to package directory - let expected_src_driver_pdb_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}.pdb")); - let expected_dest_driver_pdb_path = - expected_final_package_dir_path.join(format!("{expected_driver_name_underscored}.pdb")); - self.mock_fs_provider - .expect_copy() - .with( - eq(expected_src_driver_pdb_path.clone()), - eq(expected_dest_driver_pdb_path.clone()), - ) + let is_driver = metadata.is_some(); + let cargo_toml_metadata = metadata_from_packages( + &self.cwd, + vec![( + package_name, + self.cwd.clone(), + metadata, + if is_driver { "cdylib" } else { "lib" }, + if is_driver { "cdylib" } else { "lib" }, + if is_driver { "main.rs" } else { "lib.rs" }, + )], + ); + let cargo_toml_metadata_clone = cargo_toml_metadata.clone(); + self.mock_metadata_provider + .expect_get_cargo_metadata_at_path() .once() - .returning(move |_, _| { - if is_success { - Ok(mock_non_zero_bytes_copied_size) - } else { - Err(FileError::CopyError( - expected_src_driver_pdb_path.clone(), - expected_dest_driver_pdb_path.clone(), - std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "copy error"), - )) - } - }); + .returning(move |_| Ok(cargo_toml_metadata_clone.clone())); self } - fn expect_copy_inx_file_to_package_folder( + fn set_up_workspace_with_multiple_driver_projects( mut self, - driver_name: &str, - driver_dir: &Path, - is_success: bool, workspace_root_dir: &Path, + packages: Vec<(&str, PathBuf, Option, &str, &str, &str)>, ) -> Self { - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(workspace_root_dir); - let expected_final_package_dir_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}_package")); - let mock_non_zero_bytes_copied_size = 1000u64; - - // copy inx file to package directory - let expected_src_driver_inx_path = - driver_dir.join(format!("{expected_driver_name_underscored}.inx")); - let expected_dest_driver_inf_path = - expected_final_package_dir_path.join(format!("{expected_driver_name_underscored}.inf")); - self.mock_fs_provider - .expect_copy() - .with( - eq(expected_src_driver_inx_path.clone()), - eq(expected_dest_driver_inf_path.clone()), - ) + let cargo_toml_metadata = metadata_from_packages(workspace_root_dir, packages); + let cargo_toml_metadata_clone = cargo_toml_metadata.clone(); + self.mock_metadata_provider + .expect_get_cargo_metadata_at_path() .once() - .returning(move |_, _| { - if is_success { - Ok(mock_non_zero_bytes_copied_size) - } else { - Err(FileError::CopyError( - expected_src_driver_inx_path.clone(), - expected_dest_driver_inf_path.clone(), - std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "copy error"), - )) - } - }); + .returning(move |_| Ok(cargo_toml_metadata_clone.clone())); self } - fn expect_copy_map_file_to_package_folder( - mut self, - driver_name: &str, - driver_dir: &Path, - is_success: bool, - ) -> Self { - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_final_package_dir_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}_package")); - let mock_non_zero_bytes_copied_size = 1000u64; - - // copy map file to package directory - let expected_src_driver_map_path = expected_target_dir - .join("deps") - .join(format!("{expected_driver_name_underscored}.map")); - let expected_dest_driver_map_path = - expected_final_package_dir_path.join(format!("{expected_driver_name_underscored}.map")); - self.mock_fs_provider - .expect_copy() - .with( - eq(expected_src_driver_map_path.clone()), - eq(expected_dest_driver_map_path.clone()), - ) + fn set_up_with_custom_toml(mut self, cargo_toml_metadata: &str) -> Self { + let cargo_toml_metadata = serde_json::from_str::(cargo_toml_metadata) + .expect("failed to parse cargo metadata"); + let cargo_toml_metadata_clone = cargo_toml_metadata.clone(); + self.mock_metadata_provider + .expect_get_cargo_metadata_at_path() .once() - .returning(move |_, _| { - if is_success { - Ok(mock_non_zero_bytes_copied_size) - } else { - Err(FileError::CopyError( - expected_src_driver_map_path.clone(), - expected_dest_driver_map_path.clone(), - std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "copy error"), - )) - } - }); + .returning(move |_| Ok(cargo_toml_metadata_clone.clone())); self } - fn expect_copy_self_signed_cert_file_to_package_folder( - mut self, - driver_name: &str, - driver_dir: &Path, - is_success: bool, - ) -> Self { - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_final_package_dir_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}_package")); - let mock_non_zero_bytes_copied_size = 1000u64; - - // copy self signed certificate to package directory - let expected_src_cert_file_path = expected_target_dir.join("WDRLocalTestCert.cer"); - let expected_dest_driver_cert_path = - expected_final_package_dir_path.join("WDRLocalTestCert.cer"); - self.mock_fs_provider - .expect_copy() - .with( - eq(expected_src_cert_file_path.clone()), - eq(expected_dest_driver_cert_path.clone()), - ) - .once() - .returning(move |_, _| { - if is_success { - Ok(mock_non_zero_bytes_copied_size) - } else { - Err(FileError::CopyError( - expected_src_cert_file_path.clone(), - expected_dest_driver_cert_path.clone(), - std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "copy error"), - )) - } + fn expect_metadata_for_paths(&mut self, metadata_by_path: Vec<(PathBuf, CargoMetadata)>) { + self.mock_metadata_provider + .expect_get_cargo_metadata_at_path() + .times(metadata_by_path.len()) + .returning(move |path| { + let requested_path = PathBuf::from(path); + metadata_by_path + .iter() + .find_map(|(expected_path, metadata)| { + (requested_path == *expected_path).then_some(metadata.clone()) + }) + .ok_or_else(|| cargo_metadata::Error::from(io::Error::new( + io::ErrorKind::NotFound, + format!("unexpected metadata path: {}", requested_path.display()), + ))) }); - self - } - - fn expect_stampinf( - mut self, - driver_name: &str, - driver_dir: &Path, - target_arch: CpuArchitecture, - override_output: Option, - ) -> Self { - // Run stampinf command - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_final_package_dir_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}_package")); - let expected_dest_driver_inf_path = - expected_final_package_dir_path.join(format!("{expected_driver_name_underscored}.inf")); - - let expected_stampinf_command: &'static str = "stampinf"; - let wdk_metadata = Wdk::try_from( - self.cargo_metadata - .as_ref() - .expect("cargo metadata must be available"), - ) - .expect("Wdk metadata must be available"); - - if let DriverConfig::Kmdf(kmdf_config) = wdk_metadata.driver_model { - let expected_cat_file_name = format!("{expected_driver_name_underscored}.cat"); - let expected_stampinf_args: Vec = vec![ - "-f".to_string(), - expected_dest_driver_inf_path.to_string_lossy().to_string(), - "-d".to_string(), - "*".to_string(), - "-a".to_string(), - target_arch.to_string(), - "-c".to_string(), - expected_cat_file_name, - "-v".to_string(), - "*".to_string(), - "-k".to_string(), - format!( - "{}.{}", - kmdf_config.kmdf_version_major, kmdf_config.target_kmdf_version_minor - ), - ]; - - self.mock_run_command - .expect_run() - .withf( - move |command: &str, - args: &[&str], - _env_vars: &Option<&HashMap<&str, &str>>, - _working_dir: &Option<&Path>| - -> bool { - println!("command: {command}, args: {args:?}"); - println!( - "expected_command: {expected_stampinf_command}, expected_args: \ - {expected_stampinf_args:?}" - ); - command == expected_stampinf_command && args == expected_stampinf_args - }, - ) - .once() - .returning(move |_, _, _, _| match override_output.clone() { - Some(output) => match output.status.code() { - Some(0) => Ok(Output { - status: ExitStatus::from_raw(0), - stdout: vec![], - stderr: vec![], - }), - _ => Err(CommandError::from_output("stampinf", &[], &output)), - }, - None => Ok(Output { - status: ExitStatus::default(), - stdout: vec![], - stderr: vec![], - }), - }); - } - self } - fn expect_inf2cat( - mut self, - driver_name: &str, - driver_dir: &Path, - target_arch: CpuArchitecture, - override_output: Option, - ) -> Self { - // Run inf2cat command - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_final_package_dir_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}_package")); - - let expected_inf2cat_command: &'static str = "inf2cat"; - - let expected_inf2cat_arg = match target_arch { - CpuArchitecture::Amd64 => "10_x64", - CpuArchitecture::Arm64 => "Server10_arm64", - }; - let expected_inf2cat_args: Vec = vec![ - format!( - "/driver:{}", - expected_final_package_dir_path.to_string_lossy() - ), - format!("/os:{}", expected_inf2cat_arg), - "/uselocaltime".to_string(), - ]; - - self.mock_run_command - .expect_run() - .withf( - move |command: &str, - args: &[&str], - _env_vars: &Option<&HashMap<&str, &str>>, - _working_dir: &Option<&Path>| - -> bool { - println!("command: {command}, args: {args:?}"); - println!( - "expected_command: {expected_inf2cat_command}, expected_args: \ - {expected_inf2cat_args:?}" - ); - command == expected_inf2cat_command && args == expected_inf2cat_args - }, - ) + fn expect_detect_wdk_build_number(&mut self, build_number: u32) { + self.mock_wdk_build_provider + .expect_detect_wdk_build_number() .once() - .returning(move |_, _, _, _| match override_output.clone() { - Some(output) => match output.status.code() { - Some(0) => Ok(Output { - status: ExitStatus::from_raw(0), - stdout: vec![], - stderr: vec![], - }), - _ => Err(CommandError::from_output("inf2cat", &[], &output)), - }, - None => Ok(Output { - status: ExitStatus::default(), - stdout: vec![], - stderr: vec![], - }), - }); - self + .returning(move || Ok(build_number)); } - fn expect_certmgr_exists_check(mut self, override_output: Option) -> Self { - // check for cert in cert store using certmgr - let expected_certmgr_command: &'static str = "certmgr.exe"; - let expected_certmgr_args: Vec = - vec!["-s".to_string(), "WDRTestCertStore".to_string()]; - self.mock_run_command - .expect_run() - .withf( - move |command: &str, - args: &[&str], - _env_vars: &Option<&HashMap<&str, &str>>, - _working_dir: &Option<&Path>| - -> bool { - command == expected_certmgr_command && args == expected_certmgr_args - }, - ) - .returning(move |_, _, _, _| match override_output.clone() { - Some(output) => match output.status.code() { - Some(0) => Ok(Output { - status: ExitStatus::from_raw(0), - stdout: output.stdout, - stderr: output.stderr, - }), - _ => Err(CommandError::from_output("certmgr", &[], &output)), - }, - None => Ok(Output { - status: ExitStatus::default(), - stdout: vec![], - stderr: vec![], - }), - }); - self - } - - fn expect_certmgr_create_cert_from_store( - mut self, - driver_dir: &Path, - override_output: Option, - ) -> Self { - // create cert from store using certmgr - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_self_signed_cert_file_path = expected_target_dir.join("WDRLocalTestCert.cer"); - - let expected_certmgr_command: &'static str = "certmgr.exe"; - let expected_certmgr_args: Vec = vec![ - "-put".to_string(), - "-s".to_string(), - "WDRTestCertStore".to_string(), - "-c".to_string(), - "-n".to_string(), - "WDRLocalTestCert".to_string(), - expected_self_signed_cert_file_path - .to_string_lossy() - .to_string(), - ]; - self.mock_run_command - .expect_run() - .withf( - move |command: &str, - args: &[&str], - _env_vars: &Option<&HashMap<&str, &str>>, - _working_dir: &Option<&Path>| - -> bool { - command == expected_certmgr_command && args == expected_certmgr_args - }, - ) + fn expect_root_manifest_exists(&mut self, root_dir: &Path, exists: bool) { + let cargo_toml_path = root_dir.join("Cargo.toml"); + self.mock_fs_provider + .expect_exists() + .with(eq(cargo_toml_path)) .once() - .returning(move |_, _, _, _| match override_output.clone() { - Some(output) => match output.status.code() { - Some(0) => Ok(Output { - status: ExitStatus::from_raw(0), - stdout: vec![], - stderr: vec![], - }), - _ => Err(CommandError::from_output("certmgr", &[], &output)), - }, - None => Ok(Output { - status: ExitStatus::default(), - stdout: vec![], - stderr: vec![], - }), - }); - self + .returning(move |_| exists); } - fn expect_makecert(mut self, driver_dir: &Path, override_output: Option) -> Self { - // create self signed certificate using makecert - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_makecert_command: &'static str = "makecert"; - let expected_src_driver_cert_path = expected_target_dir.join("WDRLocalTestCert.cer"); - let expected_makecert_args: Vec = vec![ - "-r".to_string(), - "-pe".to_string(), - "-a".to_string(), - "SHA256".to_string(), - "-eku".to_string(), - "1.3.6.1.5.5.7.3.3".to_string(), - "-ss".to_string(), - "WDRTestCertStore".to_string(), - "-n".to_string(), - "CN=WDRLocalTestCert".to_string(), - expected_src_driver_cert_path.to_string_lossy().to_string(), - ]; - - self.mock_run_command - .expect_run() - .withf( - move |command: &str, - args: &[&str], - _env_vars: &Option<&HashMap<&str, &str>>, - _working_dir: &Option<&Path>| - -> bool { - command == expected_makecert_command && args == expected_makecert_args - }, - ) + fn expect_read_dir_entries(&mut self, root_dir: &Path) { + let root_dir = root_dir.to_path_buf(); + self.mock_fs_provider + .expect_read_dir_entries() + .with(eq(root_dir.clone())) .once() - .returning(move |_, _, _, _| match override_output.clone() { - Some(output) => match output.status.code() { - Some(0) => Ok(Output { - status: ExitStatus::from_raw(0), - stdout: vec![], - stderr: vec![], - }), - _ => Err(CommandError::from_output("makecert", &[], &output)), - }, - None => Ok(Output { - status: ExitStatus::default(), - stdout: vec![], - stderr: vec![], - }), + .returning(move |_| { + let mut entries = fs::read_dir(&root_dir) + .map_err(|e| FileError::ReadDirError(root_dir.clone(), e))? + .collect::, _>>() + .map_err(|e| FileError::ReadDirEntriesError(root_dir.clone(), e))?; + entries.sort_by_key(std::fs::DirEntry::path); + Ok(entries) }); - self } - fn expect_signtool_sign_driver_binary_sys_file( - mut self, - driver_name: &str, - driver_dir: &Path, - override_output: Option, - ) -> Self { - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_final_package_dir_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}_package")); - let expected_signtool_command: &'static str = "signtool"; - - // sign driver binary using signtool - let expected_dest_driver_binary_path = - expected_final_package_dir_path.join(format!("{expected_driver_name_underscored}.sys")); - let expected_signtool_args: Vec = vec![ - "sign".to_string(), - "/v".to_string(), - "/s".to_string(), - "WDRTestCertStore".to_string(), - "/n".to_string(), - "WDRLocalTestCert".to_string(), - "/t".to_string(), - "http://timestamp.digicert.com".to_string(), - "/fd".to_string(), - "SHA256".to_string(), - expected_dest_driver_binary_path - .to_string_lossy() - .to_string(), - ]; - - self.mock_run_command - .expect_run() - .withf( - move |command: &str, - args: &[&str], - _env_vars: &Option<&HashMap<&str, &str>>, - _working_dir: &Option<&Path>| - -> bool { - command == expected_signtool_command && args == expected_signtool_args - }, - ) - .once() - .returning(move |_, _, _, _| match override_output.clone() { - Some(output) => match output.status.code() { - Some(0) => Ok(Output { - status: ExitStatus::from_raw(0), - stdout: vec![], - stderr: vec![], - }), - _ => Err(CommandError::from_output("signtool", &[], &output)), - }, - None => Ok(Output { - status: ExitStatus::default(), - stdout: vec![], - stderr: vec![], - }), + fn expect_dir_file_types(&mut self) { + self.mock_fs_provider + .expect_dir_file_type() + .returning(|dir| { + dir.file_type() + .map_err(|e| FileError::DirFileTypeError(dir.path(), e)) }); - self } - fn expect_signtool_sign_cat_file( - mut self, - driver_name: &str, - driver_dir: &Path, - override_output: Option, - ) -> Self { - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_final_package_dir_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}_package")); - let expected_signtool_command: &'static str = "signtool"; - - // sign driver cat file using signtool - let expected_dest_driver_cat_file_path = - expected_final_package_dir_path.join(format!("{expected_driver_name_underscored}.cat")); - let expected_signtool_args: Vec = vec![ - "sign".to_string(), - "/v".to_string(), - "/s".to_string(), - "WDRTestCertStore".to_string(), - "/n".to_string(), - "WDRLocalTestCert".to_string(), - "/t".to_string(), - "http://timestamp.digicert.com".to_string(), - "/fd".to_string(), - "SHA256".to_string(), - expected_dest_driver_cat_file_path - .to_string_lossy() - .to_string(), - ]; - self.mock_run_command - .expect_run() - .withf( - move |command: &str, - args: &[&str], - _env_vars: &Option<&HashMap<&str, &str>>, - _working_dir: &Option<&Path>| - -> bool { - command == expected_signtool_command && args == expected_signtool_args - }, - ) + fn expect_dir_cargo_toml_exists(&mut self, dir: &Path, exists: bool) { + let cargo_toml_path = dir.join("Cargo.toml"); + self.mock_fs_provider + .expect_exists() + .with(eq(cargo_toml_path)) .once() - .returning(move |_, _, _, _| match override_output.clone() { - Some(output) => match output.status.code() { - Some(0) => Ok(Output { - status: ExitStatus::from_raw(0), - stdout: vec![], - stderr: vec![], - }), - _ => Err(CommandError::from_output("signtool", &[], &output)), - }, - None => Ok(Output { - status: ExitStatus::default(), - stdout: vec![], - stderr: vec![], - }), - }); - self + .returning(move |_| exists); } - fn expect_signtool_verify_driver_binary_sys_file( - mut self, - driver_name: &str, - driver_dir: &Path, - override_output: Option, - ) -> Self { - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_final_package_dir_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}_package")); - let expected_signtool_command: &'static str = "signtool"; - - // verify signed driver binary using signtool - let expected_dest_driver_binary_path = - expected_final_package_dir_path.join(format!("{expected_driver_name_underscored}.sys")); - let expected_signtool_verify_args: Vec = vec![ - "verify".to_string(), - "/v".to_string(), - "/pa".to_string(), - expected_dest_driver_binary_path - .to_string_lossy() - .to_string(), - ]; - self.mock_run_command + fn expect_build_runner( + &mut self, + package_name: &str, + working_dir: &Path, + profile: Option, + target_arch: Option, + result: Result>, super::error::BuildTaskError>, + ) { + let expected_package_name = package_name.to_string(); + let expected_working_dir = working_dir.to_path_buf(); + let expected_profile = profile; + let expected_target_arch = target_arch; + self.mock_build_task_runner .expect_run() - .withf( - move |command: &str, - args: &[&str], - _env_vars: &Option<&HashMap<&str, &str>>, - _working_dir: &Option<&Path>| - -> bool { - command == expected_signtool_command && args == expected_signtool_verify_args - }, - ) + .withf(move |params: &BuildTaskRunParams<'_>, _command_exec| { + params.package_name == expected_package_name + && params.working_dir == expected_working_dir + && params.profile.copied() == expected_profile + && params.target_arch == expected_target_arch + }) .once() - .returning(move |_, _, _, _| match override_output.clone() { - Some(output) => match output.status.code() { - Some(0) => Ok(Output { - status: ExitStatus::from_raw(0), - stdout: vec![], - stderr: vec![], - }), - _ => Err(CommandError::from_output("signtool", &[], &output)), - }, - None => Ok(Output { - status: ExitStatus::default(), - stdout: vec![], - stderr: vec![], - }), - }); - self + .return_once(move |_, _| result); } - fn expect_signtool_verify_cat_file( - mut self, - driver_name: &str, - driver_dir: &Path, - override_output: Option, - ) -> Self { - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_final_package_dir_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}_package")); - let expected_signtool_command: &'static str = "signtool"; - - // verify signed driver cat file using signtool - let expected_dest_driver_cat_file_path = - expected_final_package_dir_path.join(format!("{expected_driver_name_underscored}.cat")); - let expected_signtool_verify_args: Vec = vec![ - "verify".to_string(), - "/v".to_string(), - "/pa".to_string(), - expected_dest_driver_cat_file_path - .to_string_lossy() - .to_string(), - ]; - self.mock_run_command + fn expect_package_runner( + &mut self, + package_name: &str, + working_dir: &Path, + target_dir: &Path, + target_arch: CpuArchitecture, + verify_signature: bool, + sample_class: bool, + ) { + let expected_package_name = package_name.to_string(); + let expected_working_dir = working_dir.to_path_buf(); + let expected_target_dir = target_dir.to_path_buf(); + self.mock_package_task_runner .expect_run() - .withf( - move |command: &str, - args: &[&str], - _env_vars: &Option<&HashMap<&str, &str>>, - _working_dir: &Option<&Path>| - -> bool { - command == expected_signtool_command && args == expected_signtool_verify_args - }, - ) - .once() - .returning(move |_, _, _, _| match override_output.clone() { - Some(output) => match output.status.code() { - Some(0) => Ok(Output { - status: ExitStatus::from_raw(0), - stdout: vec![], - stderr: vec![], - }), - _ => Err(CommandError::from_output("stampinf", &[], &output)), - }, - None => Ok(Output { - status: ExitStatus::default(), - stdout: vec![], - stderr: vec![], - }), - }); - self - } - - fn expect_detect_wdk_build_number(mut self, expected_wdk_build_number: u32) -> Self { - self.mock_wdk_build_provider - .expect_detect_wdk_build_number() + .withf(move |params: &PackageTaskParams<'_>, _, _, _| { + params.package_name == expected_package_name + && params.working_dir == expected_working_dir + && params.target_dir == expected_target_dir + && *params.target_arch == target_arch + && params.verify_signature == verify_signature + && params.sample_class == sample_class + && matches!(params.driver_model, DriverConfig::Kmdf(_)) + }) .once() - .returning(move || Ok(expected_wdk_build_number)); - self + .return_once(|_, _, _, _| Ok(())); } - fn expect_infverif( - mut self, - driver_name: &str, - driver_dir: &Path, - driver_type: &str, - override_output: Option, - ) -> Self { - let mut expected_infverif_args = vec!["/v".to_string()]; - if driver_type.eq_ignore_ascii_case("KMDF") || driver_type.eq_ignore_ascii_case("WDM") { - expected_infverif_args.push("/w".to_string()); - } else { - expected_infverif_args.push("/u".to_string()); - } - if self.sample_class { - expected_infverif_args.push("/msft".to_string()); - } - let expected_infverif_command: &'static str = "infverif"; - let expected_driver_name_underscored = driver_name.replace('-', "_"); - let expected_target_dir = self.setup_target_dir(driver_dir); - let expected_final_package_dir_path = - expected_target_dir.join(format!("{expected_driver_name_underscored}_package")); - let expected_dest_inf_file_path = - expected_final_package_dir_path.join(format!("{expected_driver_name_underscored}.inf")); - expected_infverif_args.push(expected_dest_inf_file_path.to_string_lossy().to_string()); - + fn expect_probe_target_arch_using_cargo_rustc( + &mut self, + working_dir: &Path, + detected_arch: CpuArchitecture, + ) { + let expected_working_dir = working_dir.to_path_buf(); + let arch_str = match detected_arch { + CpuArchitecture::Amd64 => "x86_64", + CpuArchitecture::Arm64 => "aarch64", + }; self.mock_run_command .expect_run() .withf( move |command: &str, args: &[&str], _env_vars: &Option<&HashMap<&str, &str>>, - _working_dir: &Option<&Path>| - -> bool { - command == expected_infverif_command && args == expected_infverif_args + working_dir: &Option<&Path>| { + command == "cargo" + && args == ["rustc", "--", "--print", "cfg"] + && working_dir.is_some_and(|dir| dir == expected_working_dir.as_path()) }, ) .once() - .returning(move |_, _, _, _| match override_output.clone() { - Some(output) => match output.status.code() { - Some(0) => Ok(Output { - status: ExitStatus::from_raw(0), - stdout: vec![], - stderr: vec![], - }), - _ => Err(CommandError::from_output("infverif", &[], &output)), - }, - None => Ok(Output { + .returning(move |_, _, _, _| { + Ok(Output { status: ExitStatus::default(), - stdout: vec![], + stdout: format!("target_arch=\"{arch_str}\"\n").into_bytes(), stderr: vec![], - }), + }) }); - self - } - - const fn mock_wdk_build_provider(&self) -> &WdkBuild { - &self.mock_wdk_build_provider } +} - const fn mock_run_command(&self) -> &CommandExec { - &self.mock_run_command - } +struct TestWorkspaceRoot { + root: PathBuf, +} - const fn mock_fs_provider(&self) -> &Fs { - &self.mock_fs_provider +impl TestWorkspaceRoot { + fn new(prefix: &str) -> Self { + static NEXT_ID: AtomicU64 = AtomicU64::new(0); + let unique_id = NEXT_ID.fetch_add(1, Ordering::Relaxed); + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("target") + .join("test-artifacts") + .join(format!("{prefix}-{unique_id}")); + if root.exists() { + fs::remove_dir_all(&root).expect("failed to remove stale test workspace"); + } + fs::create_dir_all(&root).expect("failed to create test workspace"); + Self { root } } +} - const fn mock_metadata_provider(&self) -> &MetadataProvider { - &self.mock_metadata_provider +impl Drop for TestWorkspaceRoot { + fn drop(&mut self) { + if self.root.exists() { + let _ = fs::remove_dir_all(&self.root); + } } } -fn invalid_driver_cargo_toml() -> String { - r#" - { - "packages": [ - { - "name": "sample-driver", - "version": "0.0.1", - "id": "path+file:///C:/tmp/sample-driver#0.0.1", - "license": "MIT OR Apache-2.0", - "license_file": null, - "description": null, - "source": null, - "dependencies": [], - "targets": [ - { - "kind": [ - "cdylib" - ], - "crate_types": [ - "cdylib" - ], - "name": "sample_driver", - "src_path": "C:\\tmp\\sample-driver\\src\\lib.rs", - "edition": "2021", - "doc": true, - "doctest": false, - "test": false - }, - { - "kind": [ - "custom-build" - ], - "crate_types": [ - "bin" - ], - "name": "build-script-build", - "src_path": "C:\\tmp\\sample-driver\\build.rs", - "edition": "2021", - "doc": false, - "doctest": false, - "test": false - } - ], - "features": { - "default": [], - "nightly": [ - "wdk/nightly", - "wdk-sys/nightly" - ] - }, - "manifest_path": "C:\\tmp\\sample-driver\\Cargo.toml", - "metadata": { - "wdk": {} - }, - "publish": [], - "authors": [], - "categories": [], - "keywords": [], - "readme": null, - "repository": null, - "homepage": null, - "documentation": null, - "edition": "2021", - "links": null, - "default_run": null, - "rust_version": null - } - ], - "workspace_members": [ - "path+file:///C:/tmp/sample-driver#0.0.1" - ], - "target_directory": "C:\\tmp\\sample-driver\\target", - "version": 1, - "workspace_root": "C:\\tmp\\sample-driver", - "metadata": { - "wdk": { - "driver-model": { - "driver-type": "KMDF" - } - } - } - } - "# - .to_string() +fn metadata_from_packages( + workspace_root_dir: &Path, + packages: Vec<(&str, PathBuf, Option, &str, &str, &str)>, +) -> CargoMetadata { + let mut package_json = Vec::new(); + let mut workspace_member_ids = Vec::new(); + for (package_name, package_dir, metadata, target_kind, crate_type, source_file) in packages { + let (workspace_member_id, package) = get_cargo_metadata_package_with_target( + &package_dir, + package_name, + DEFAULT_DRIVER_VERSION, + metadata, + target_kind, + crate_type, + source_file, + ); + workspace_member_ids.push(workspace_member_id); + package_json.push(package); + } + serde_json::from_str::(&get_cargo_metadata( + workspace_root_dir, + package_json, + &workspace_member_ids, + None, + )) + .expect("failed to parse cargo metadata") } #[derive(Clone)] struct TestMetadataPackage(String); + #[derive(Clone)] struct TestMetadataWorkspaceMemberId(String); + #[derive(Clone)] struct TestWdkMetadata(String); @@ -2704,7 +859,6 @@ fn get_cargo_metadata( .map(|p| p.0) .collect::>() .join(", "), - // Require quotes around each member workspace_member_list .iter() .map(|s| format!("\"{}\"", s.0)) @@ -2714,25 +868,19 @@ fn get_cargo_metadata( ) } -fn get_cargo_metadata_package( +fn get_cargo_metadata_package_with_target( root_dir: &Path, - default_package_name: &str, - default_package_version: &str, - metadata: Option<&TestWdkMetadata>, + package_name: &str, + package_version: &str, + metadata: Option, + target_kind: &str, + crate_type: &str, + source_file: &str, ) -> (TestMetadataWorkspaceMemberId, TestMetadataPackage) { let normalized_root = root_dir.to_string_lossy().replace('\\', "/"); let normalized_root = normalized_root.trim_start_matches("//?/"); - let package_id = - format!("path+file:///{normalized_root}#{default_package_name}@{default_package_version}"); - let (metadata_section, has_metadata) = metadata.map_or_else( - || (String::from("null"), false), - |metadata| ((metadata.0).clone(), true), - ); - let (target_kind, crate_type, source_file) = if has_metadata { - ("cdylib", "cdylib", "main.rs") - } else { - ("lib", "lib", "lib.rs") - }; + let package_id = format!("path+file:///{normalized_root}#{package_name}@{package_version}"); + let metadata_section = metadata.map_or_else(|| String::from("null"), |metadata| metadata.0); let manifest_path = root_dir .join("Cargo.toml") .to_string_lossy() @@ -2749,8 +897,8 @@ fn get_cargo_metadata_package( TestMetadataPackage(format!( r#" {{ - "name": "{default_package_name}", - "version": "{default_package_version}", + "name": "{package_name}", + "version": "{package_version}", "id": "{package_id}", "dependencies": [], "targets": [ @@ -2761,7 +909,7 @@ fn get_cargo_metadata_package( "crate_types": [ "{crate_type}" ], - "name": "{default_package_name}", + "name": "{package_name}", "src_path": "{source_path}", "edition": "2021", "doc": true, @@ -2807,9 +955,6 @@ fn get_cargo_metadata_wdk_metadata( )) } -/// Creates a valid cargo compiler-artifact JSON message for testing. -/// This simulates the JSON output that `cargo build --message-format=json` -/// produces. fn create_cargo_build_output_json( package_name: &str, package_version: &str, @@ -2834,7 +979,6 @@ fn strip_windows_extended_prefix(path: &Path) -> String { return path_str.into_owned(); }; - // Handle UNC paths without_prefix.strip_prefix("UNC\\").map_or_else( || without_prefix.to_string(), |unc_rest| format!(r"\\{unc_rest}"), @@ -2851,22 +995,16 @@ fn create_cargo_build_output_json_with_manifest( is_driver: bool, ) -> Output { let normalized_name = package_name.replace('-', "_"); - - // Determine profile directory name let profile_dir = match profile { Some(Profile::Release) => "release", _ => "debug", }; - - // For non-driver projects, use "lib" instead of "cdylib" to ensure BuildTask - // returns DllNotFound let (kind, crate_types, file_ext) = if is_driver { ("cdylib", "cdylib", "dll") } else { ("lib", "lib", "rlib") }; - // Build the artifact path based on target_triple and profile let mut artifact_path = workspace_root.join("target"); if let Some(target) = target_triple { artifact_path = artifact_path.join(target); @@ -2880,7 +1018,6 @@ fn create_cargo_build_output_json_with_manifest( let package_id = format!("path+file:///{package_dir}#{package_name}@{package_version}"); let manifest_path = strip_windows_extended_prefix(manifest_path); let artifact_path = strip_windows_extended_prefix(&artifact_path); - let pdb_path = Path::new(&artifact_path) .with_extension("pdb") .to_string_lossy() @@ -2935,11 +1072,14 @@ mod get_target_dir_from_output { fn unparsable_output_fails() { let workspace_root_dir = PathBuf::from(r"C:\tmp\sample-kmdf"); let wdk_metadata = super::get_cargo_metadata_wdk_metadata("KMDF", 1, 0); - let (_workspace_member, package_json) = super::get_cargo_metadata_package( + let (_workspace_member, package_json) = super::get_cargo_metadata_package_with_target( &workspace_root_dir, "sample-kmdf", "0.0.1", - Some(&wdk_metadata), + Some(wdk_metadata), + "cdylib", + "cdylib", + "main.rs", ); let package = serde_json::from_str::(&package_json.0) .expect("Failed to parse package json"); @@ -2963,11 +1103,14 @@ mod get_target_dir_from_output { fn no_matching_artifact_fails() { let workspace_root_dir = PathBuf::from(r"C:\tmp\sample-kmdf"); let wdk_metadata = super::get_cargo_metadata_wdk_metadata("KMDF", 1, 0); - let (_workspace_member, package_json) = super::get_cargo_metadata_package( + let (_workspace_member, package_json) = super::get_cargo_metadata_package_with_target( &workspace_root_dir, "sample-kmdf", "0.0.1", - Some(&wdk_metadata), + Some(wdk_metadata), + "cdylib", + "cdylib", + "main.rs", ); let package = serde_json::from_str::(&package_json.0) .expect("Failed to parse package json"); @@ -2998,11 +1141,14 @@ mod get_target_dir_from_output { fn matching_artifact_without_dll_fails() { let workspace_root_dir = PathBuf::from(r"C:\tmp\sample-kmdf"); let wdk_metadata = super::get_cargo_metadata_wdk_metadata("KMDF", 1, 0); - let (_workspace_member, package_json) = super::get_cargo_metadata_package( + let (_workspace_member, package_json) = super::get_cargo_metadata_package_with_target( &workspace_root_dir, "sample-kmdf", "0.0.1", - Some(&wdk_metadata), + Some(wdk_metadata), + "cdylib", + "cdylib", + "main.rs", ); let package = serde_json::from_str::(&package_json.0) .expect("Failed to parse package json"); @@ -3048,11 +1194,14 @@ mod get_target_dir_from_output { fn matching_dll_resolves_target_dir() { let workspace_root_dir = PathBuf::from(r"C:\tmp\sample-kmdf"); let wdk_metadata = super::get_cargo_metadata_wdk_metadata("KMDF", 1, 0); - let (_workspace_member, package_json) = super::get_cargo_metadata_package( + let (_workspace_member, package_json) = super::get_cargo_metadata_package_with_target( &workspace_root_dir, "sample-kmdf", "0.0.1", - Some(&wdk_metadata), + Some(wdk_metadata), + "cdylib", + "cdylib", + "main.rs", ); let package = serde_json::from_str::(&package_json.0) .expect("Failed to parse package json"); @@ -3101,17 +1250,14 @@ mod get_target_arch_from_cargo_rustc { use wdk_build::CpuArchitecture; - use super::{BuildActionError, TestBuildAction}; + use super::{BuildActionError, TestBuildAction, initialize_build_action}; fn run_parse_test(cfg_output: Vec, expected_arch: CpuArchitecture) { let cwd = PathBuf::from(r"C:\tmp"); - let mut test_build_action = TestBuildAction::new(cwd.clone(), None, None, false); + let mut test_build_action = TestBuildAction::new(cwd.clone(), None, None, false, false); expect_cargo_rustc_print_cfg(&mut test_build_action, cwd.clone(), cfg_output); - let build_action = - super::initialize_build_action(&cwd, None, None, true, false, &test_build_action) - .expect("Failed to init build action"); - + let build_action = initialize_build_action(&mut test_build_action); let arch = build_action .get_target_arch_from_cargo_rustc(&cwd) .expect("Expected target arch to be detected"); @@ -3142,17 +1288,14 @@ mod get_target_arch_from_cargo_rustc { #[test] fn unsupported_arch_returns_error() { let cwd = PathBuf::from(r"C:\tmp"); - let mut test_build_action = TestBuildAction::new(cwd.clone(), None, None, false); + let mut test_build_action = TestBuildAction::new(cwd.clone(), None, None, false, false); expect_cargo_rustc_print_cfg( &mut test_build_action, cwd.clone(), b"target_arch=\"mips\"\n".to_vec(), ); - let build_action = - super::initialize_build_action(&cwd, None, None, true, false, &test_build_action) - .expect("Failed to init build action"); - + let build_action = initialize_build_action(&mut test_build_action); let err = build_action .get_target_arch_from_cargo_rustc(&cwd) .expect_err("Expected UnsupportedArchitecture error"); @@ -3162,17 +1305,14 @@ mod get_target_arch_from_cargo_rustc { #[test] fn missing_target_arch_returns_error() { let cwd = PathBuf::from(r"C:\tmp"); - let mut test_build_action = TestBuildAction::new(cwd.clone(), None, None, false); + let mut test_build_action = TestBuildAction::new(cwd.clone(), None, None, false, false); expect_cargo_rustc_print_cfg( &mut test_build_action, cwd.clone(), b"some_other_cfg=\"value\"\n".to_vec(), ); - let build_action = - super::initialize_build_action(&cwd, None, None, true, false, &test_build_action) - .expect("Failed to init build action"); - + let build_action = initialize_build_action(&mut test_build_action); let err = build_action .get_target_arch_from_cargo_rustc(&cwd) .expect_err("Expected CannotDetectTargetArch error"); @@ -3182,13 +1322,10 @@ mod get_target_arch_from_cargo_rustc { #[test] fn invalid_utf8_returns_error() { let cwd = PathBuf::from(r"C:\tmp"); - let mut test_build_action = TestBuildAction::new(cwd.clone(), None, None, false); + let mut test_build_action = TestBuildAction::new(cwd.clone(), None, None, false, false); expect_cargo_rustc_print_cfg(&mut test_build_action, cwd.clone(), vec![0xFF, 0xFE]); - let build_action = - super::initialize_build_action(&cwd, None, None, true, false, &test_build_action) - .expect("Failed to init build action"); - + let build_action = initialize_build_action(&mut test_build_action); let err = build_action .get_target_arch_from_cargo_rustc(&cwd) .expect_err("Expected CannotDetectTargetArch error"); @@ -3207,8 +1344,7 @@ mod get_target_arch_from_cargo_rustc { move |command: &str, args: &[&str], _env_vars: &Option<&HashMap<&str, &str>>, - working_dir: &Option<&Path>| - -> bool { + working_dir: &Option<&Path>| { command == "cargo" && args == ["rustc", "--", "--print", "cfg"] && matches!(working_dir, Some(dir) if *dir == cwd.as_path())