From 1909fde00b23f46ed1a397690b9605f36b08e31a Mon Sep 17 00:00:00 2001 From: Shankar Seal Date: Tue, 1 Sep 2026 17:47:21 -0700 Subject: [PATCH 1/3] update netebpfext unit test to suspend fault injection during test init. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: ea587460-e416-414f-9687-d52ae0a34d8f --- ebpf-for-windows.sln | 6 +- external/usersim | 2 +- tests/netebpfext_unit/netebpf_ext_helper.cpp | 88 +++++++++++++++++-- tests/netebpfext_unit/netebpf_ext_helper.h | 24 ++++- tests/netebpfext_unit/netebpfext_unit.cpp | 50 ++++++++++- tests/netebpfext_unit/netebpfext_unit.vcxproj | 27 ++++++ 6 files changed, 186 insertions(+), 11 deletions(-) diff --git a/ebpf-for-windows.sln b/ebpf-for-windows.sln index cfe549a05a..4749cb3d01 100644 --- a/ebpf-for-windows.sln +++ b/ebpf-for-windows.sln @@ -2749,8 +2749,10 @@ Global {E619B985-44B3-4292-A585-5CD0C4315ED3}.MinSizeRel|x64.Build.0 = Debug|x64 {E619B985-44B3-4292-A585-5CD0C4315ED3}.MinSizeRel|x86.ActiveCfg = NativeOnlyDebug|x64 {E619B985-44B3-4292-A585-5CD0C4315ED3}.MinSizeRel|x86.Build.0 = NativeOnlyDebug|x64 - {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|ARM64.ActiveCfg = Debug|ARM64 - {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|x64.ActiveCfg = Debug|x64 + {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|ARM64.ActiveCfg = NativeOnlyDebug|ARM64 + {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|ARM64.Build.0 = NativeOnlyDebug|ARM64 + {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|x64.ActiveCfg = NativeOnlyDebug|x64 + {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|x64.Build.0 = NativeOnlyDebug|x64 {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|x86.ActiveCfg = NativeOnlyDebug|x64 {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|x86.Build.0 = NativeOnlyDebug|x64 {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyRelease|ARM64.ActiveCfg = Release|ARM64 diff --git a/external/usersim b/external/usersim index a4ef7d8fee..936a02690a 160000 --- a/external/usersim +++ b/external/usersim @@ -1 +1 @@ -Subproject commit a4ef7d8fee4597b6c3a63779365d704451c89e9f +Subproject commit 936a02690a1a32be0bb0c6d4983b78c00c2557f7 diff --git a/tests/netebpfext_unit/netebpf_ext_helper.cpp b/tests/netebpfext_unit/netebpf_ext_helper.cpp index 7b26e9c0c1..c5d9131b92 100644 --- a/tests/netebpfext_unit/netebpf_ext_helper.cpp +++ b/tests/netebpfext_unit/netebpf_ext_helper.cpp @@ -1,12 +1,55 @@ // Copyright (c) eBPF for Windows contributors // SPDX-License-Identifier: MIT +#include "cxplat_fault_injection.h" #include "ebpf_platform.h" #include "net_ebpf_ext_sock_addr.h" #include "netebpf_ext_helper.h" +#include "usersim/common.h" -DEVICE_OBJECT* _net_ebpf_ext_driver_device_object; +class _usersim_fault_injection_suspension +{ + public: + _usersim_fault_injection_suspension(bool suspend) : _suspended(suspend) + { + if (_suspended) { + usersim_fault_injection_suspend(); + } + } + ~_usersim_fault_injection_suspension() + { + if (_suspended) { + usersim_fault_injection_resume(); + } + } + + private: + bool _suspended; +}; + +const GUID* const _expected_program_info_providers[] = { + &EBPF_PROGRAM_TYPE_BIND, + &EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR, + &EBPF_PROGRAM_TYPE_SOCK_OPS, +}; + +constexpr bpf_attach_type_t _expected_hook_providers[] = { + BPF_ATTACH_TYPE_BIND, + BPF_CGROUP_INET4_CONNECT, + BPF_CGROUP_INET4_RECV_ACCEPT, + BPF_CGROUP_INET6_CONNECT, + BPF_CGROUP_INET6_RECV_ACCEPT, + BPF_CGROUP_INET4_CONNECT_AUTHORIZATION, + BPF_CGROUP_INET6_CONNECT_AUTHORIZATION, + BPF_CGROUP_INET4_BIND, + BPF_CGROUP_INET6_BIND, + BPF_CGROUP_INET4_LISTEN, + BPF_CGROUP_INET6_LISTEN, + BPF_CGROUP_SOCK_OPS, +}; + +DEVICE_OBJECT* _net_ebpf_ext_driver_device_object; constexpr uint32_t _test_destination_ipv4_address = 0x01020304; static FWP_BYTE_ARRAY16 _test_destination_ipv6_address = {1, 2, 3, 4}; // _get_sock_addr_action() uses destination_port % SOCK_ADDR_TEST_ACTION_ROUND_ROBIN @@ -41,8 +84,8 @@ netebpfext_initialize_fwp_classify_parameters(_Out_ fwp_classify_parameters_t* p parameters->user_id = _test_user_id; } -_netebpf_ext_helper::_netebpf_ext_helper(bool initialize_platform) - : _netebpf_ext_helper(nullptr, nullptr, nullptr, initialize_platform) +_netebpf_ext_helper::_netebpf_ext_helper(bool initialize_platform, fault_injection_policy_t fault_injection_policy) + : _netebpf_ext_helper(nullptr, nullptr, nullptr, initialize_platform, fault_injection_policy) { } @@ -50,8 +93,12 @@ _netebpf_ext_helper::_netebpf_ext_helper( _In_opt_ const void* npi_specific_characteristics, _In_opt_ _ebpf_extension_dispatch_function dispatch_function, _In_opt_ netebpfext_helper_base_client_context_t* client_context, - bool initialize_platform) + bool initialize_platform, + fault_injection_policy_t fault_injection_policy) { + _usersim_fault_injection_suspension fault_injection_suspension( + fault_injection_policy == fault_injection_policy_t::suspend); + // Do not use REQUIRE() in this constructor or the destructor will never be called // to clean up any state allocated before the REQUIRE. @@ -91,6 +138,7 @@ _netebpf_ext_helper::_netebpf_ext_helper( if (dispatch_function != nullptr && client_context != nullptr) { hook_client.ClientRegistrationInstance.NpiSpecificCharacteristics = npi_specific_characteristics; client_context->helper = this; + hook_client_context = client_context; nmr_hook_client_handle = std::make_unique(&hook_client, client_context); } @@ -100,6 +148,9 @@ _netebpf_ext_helper::_netebpf_ext_helper( _netebpf_ext_helper::~_netebpf_ext_helper() { + constexpr bool suspend_fault_injection = true; + _usersim_fault_injection_suspension fault_injection_suspension(suspend_fault_injection); + if (nmr_hook_client_handle) { nmr_hook_client_handle.reset(nullptr); } @@ -130,6 +181,27 @@ _netebpf_ext_helper::~_netebpf_ext_helper() } } +void +_netebpf_ext_helper::require_initialized() const +{ + REQUIRE(nmr_program_info_client_handle != nullptr); + REQUIRE(nmr_program_info_client_handle->is_registered()); + REQUIRE(program_info_providers.size() == EBPF_COUNT_OF(_expected_program_info_providers)); + for (const auto* provider : _expected_program_info_providers) { + REQUIRE(program_info_providers.contains(*provider)); + } + + if (hook_client_context != nullptr) { + REQUIRE(nmr_hook_client_handle != nullptr); + REQUIRE(nmr_hook_client_handle->is_registered()); + REQUIRE(hook_client_context->provider_binding_context != nullptr); + REQUIRE( + hook_provider_binding_count == (hook_client_context->desired_attach_types.empty() + ? EBPF_COUNT_OF(_expected_hook_providers) + : hook_client_context->desired_attach_types.size())); + } +} + std::vector _netebpf_ext_helper::program_info_provider_guids() { @@ -214,12 +286,18 @@ _netebpf_ext_helper::_hook_client_attach_provider( return STATUS_ACCESS_DENIED; } - return NmrClientAttachProvider( + NTSTATUS status = NmrClientAttachProvider( nmr_binding_handle, client_context, // Client binding context. &client_dispatch_table, &base_client_context->provider_binding_context, &provider_dispatch_table); + if (NT_SUCCESS(status)) { + // No synchronization is required here because usersim NMR executes pending attach actions serially in + // perform_bind(). + base_client_context->helper->hook_provider_binding_count++; + } + return status; } NTSTATUS diff --git a/tests/netebpfext_unit/netebpf_ext_helper.h b/tests/netebpfext_unit/netebpf_ext_helper.h index fcb5d0f9e3..cb8d985e7b 100644 --- a/tests/netebpfext_unit/netebpf_ext_helper.h +++ b/tests/netebpfext_unit/netebpf_ext_helper.h @@ -34,16 +34,28 @@ typedef struct _netebpfext_helper_base_client_context typedef class _netebpf_ext_helper { public: + enum class fault_injection_policy_t + { + suspend, + allow, + }; + // If the caller invokes platform functions itself, the caller must pass initialize_platform = false // and initialize/terminate the platform itself as needed. - _netebpf_ext_helper(bool initialize_platform = true); + _netebpf_ext_helper( + bool initialize_platform = true, + fault_injection_policy_t fault_injection_policy = fault_injection_policy_t::suspend); _netebpf_ext_helper( _In_opt_ const void* npi_specific_characteristics, _In_opt_ _ebpf_extension_dispatch_function dispatch_function, _In_opt_ netebpfext_helper_base_client_context_t* client_context, - bool initialize_platform = true); + bool initialize_platform = true, + fault_injection_policy_t fault_injection_policy = fault_injection_policy_t::suspend); ~_netebpf_ext_helper(); + void + require_initialized() const; + std::vector program_info_provider_guids(); @@ -216,6 +228,12 @@ typedef class _netebpf_ext_helper } } + bool + is_registered() const + { + return nmr_client_handle != INVALID_HANDLE_VALUE; + } + HANDLE nmr_client_handle; } nmr_client_registration_t; @@ -282,6 +300,8 @@ typedef class _netebpf_ext_helper }; _ebpf_extension_dispatch_function hook_invoke_function = nullptr; + netebpfext_helper_base_client_context_t* hook_client_context = nullptr; + size_t hook_provider_binding_count = 0; std::unique_ptr nmr_program_info_client_handle; std::unique_ptr nmr_hook_client_handle; diff --git a/tests/netebpfext_unit/netebpfext_unit.cpp b/tests/netebpfext_unit/netebpfext_unit.cpp index 8979dd09db..f62d9362aa 100644 --- a/tests/netebpfext_unit/netebpfext_unit.cpp +++ b/tests/netebpfext_unit/netebpfext_unit.cpp @@ -37,9 +37,40 @@ typedef enum _sock_addr_test_action SOCK_ADDR_TEST_ACTION_ROUND_ROBIN } sock_addr_test_action_t; +_Must_inspect_result_ ebpf_result_t +netebpfext_unit_invoke_noop_program( + _In_ const void* client_binding_context, _In_ const void* context, _Out_ uint32_t* result) +{ + UNREFERENCED_PARAMETER(client_binding_context); + UNREFERENCED_PARAMETER(context); + *result = 0; + return EBPF_SUCCESS; +} + +TEST_CASE("nmr_provider_init", "[netebpfext]") +{ + // Verify that every program-info and hook NPI provider binds successfully. This variation can run with fault + // injection enabled to exercise failures during NMR provider initialization. + constexpr bool initialize_platform = true; + constexpr auto allow_fault_injection = netebpf_ext_helper_t::fault_injection_policy_t::allow; + ebpf_extension_data_t npi_specific_characteristics = { + .header = EBPF_ATTACH_CLIENT_DATA_HEADER_VERSION, + }; + netebpfext_helper_base_client_context_t client_context = {}; + + netebpf_ext_helper_t helper( + &npi_specific_characteristics, + (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_noop_program, + &client_context, + initialize_platform, + allow_fault_injection); + helper.require_initialized(); +} + TEST_CASE("query program info", "[netebpfext]") { netebpf_ext_helper_t helper; + helper.require_initialized(); std::vector expected_guids = { EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR, EBPF_PROGRAM_TYPE_SOCK_OPS, EBPF_PROGRAM_TYPE_BIND}; std::vector expected_program_names = {"sock_addr", "sockops", "bind"}; @@ -104,6 +135,7 @@ TEST_CASE("bind_invoke", "[netebpfext]") &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_bind_program, (netebpfext_helper_base_client_context_t*)client_context); + helper.require_initialized(); netebpfext_initialize_fwp_classify_parameters(¶meters); @@ -126,6 +158,7 @@ TEST_CASE("bind_invoke", "[netebpfext]") TEST_CASE("bind_context", "[netebpfext]") { netebpf_ext_helper_t helper; + helper.require_initialized(); auto bind_program_data = helper.get_program_info_provider_data(EBPF_PROGRAM_TYPE_BIND); REQUIRE(bind_program_data != nullptr); @@ -277,6 +310,7 @@ TEST_CASE("bind_hard_soft_permit", "[netebpfext][bind]") &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_bind_program, (netebpfext_helper_base_client_context_t*)client_context); + helper.require_initialized(); netebpfext_initialize_fwp_classify_parameters(¶meters); @@ -430,6 +464,7 @@ TEST_CASE("sock_addr_invoke", "[netebpfext]") &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_sock_addr_program, (netebpfext_helper_base_client_context_t*)client_context); + helper.require_initialized(); netebpfext_initialize_fwp_classify_parameters(¶meters); @@ -941,6 +976,7 @@ TEST_CASE("sock_addr_invoke_concurrent1", "[netebpfext_concurrent]") &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_sock_addr_program, (netebpfext_helper_base_client_context_t*)client_context); + helper.require_initialized(); std::vector threads; @@ -997,6 +1033,7 @@ TEST_CASE("sock_addr_invoke_concurrent2", "[netebpfext_concurrent]") &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_sock_addr_program, (netebpfext_helper_base_client_context_t*)client_context); + helper.require_initialized(); std::vector threads; @@ -1051,6 +1088,7 @@ TEST_CASE("sock_addr_invoke_concurrent3", "[netebpfext_concurrent]") &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_sock_addr_program, (netebpfext_helper_base_client_context_t*)client_context); + helper.require_initialized(); std::vector threads; @@ -1091,6 +1129,7 @@ TEST_CASE("sock_addr_invoke_concurrent3", "[netebpfext_concurrent]") TEST_CASE("sock_addr_context", "[netebpfext]") { netebpf_ext_helper_t helper; + helper.require_initialized(); auto sock_addr_program_data = helper.get_program_info_provider_data(EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR); REQUIRE(sock_addr_program_data != nullptr); @@ -1171,6 +1210,7 @@ TEST_CASE("sock_addr_connect_authorization_invoke", "[netebpfext]") &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_sock_addr_program, (netebpfext_helper_base_client_context_t*)client_context); + helper.require_initialized(); netebpfext_initialize_fwp_classify_parameters(¶meters); @@ -1255,6 +1295,7 @@ TEST_CASE("wfp_filter_delete_failure_runtime_retry", "[netebpfext][wfp_cleanup]" &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_sock_addr_program, (netebpfext_helper_base_client_context_t*)client_context); + helper.require_initialized(); // Attaching the connect program creates WFP filters. REQUIRE(usersim_fwp_get_fwpm_filter_count() > 0); @@ -1290,6 +1331,7 @@ TEST_CASE("wfp_filter_delete_failure_unload_reclaim", "[netebpfext][wfp_cleanup] &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_sock_addr_program, (netebpfext_helper_base_client_context_t*)client_context); + helper.require_initialized(); REQUIRE(usersim_fwp_get_fwpm_filter_count() > 0); @@ -1327,6 +1369,7 @@ TEST_CASE("wfp_filter_delete_failure_unload_deletes_stale_filter", "[netebpfext] &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_sock_addr_program, (netebpfext_helper_base_client_context_t*)client_context); + helper.require_initialized(); REQUIRE(usersim_fwp_get_fwpm_filter_count() > 0); @@ -1429,6 +1472,7 @@ TEST_CASE("sock_ops_invoke", "[netebpfext]") &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_sock_ops_program, (netebpfext_helper_base_client_context_t*)client_context); + helper.require_initialized(); netebpfext_initialize_fwp_classify_parameters(¶meters); @@ -1454,6 +1498,7 @@ TEST_CASE("sock_ops_invoke", "[netebpfext]") TEST_CASE("sock_ops_context", "[netebpfext]") { netebpf_ext_helper_t helper; + helper.require_initialized(); auto sock_ops_program_data = helper.get_program_info_provider_data(EBPF_PROGRAM_TYPE_SOCK_OPS); REQUIRE(sock_ops_program_data != nullptr); @@ -1606,6 +1651,7 @@ TEST_CASE("sock_ops_invoke_concurrent1", "[netebpfext_concurrent]") &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_sock_ops_program, (netebpfext_helper_base_client_context_t*)client_context); + helper.require_initialized(); std::vector threads; @@ -1651,6 +1697,7 @@ TEST_CASE("sock_ops_invoke_concurrent2", "[netebpfext_concurrent]") &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_sock_ops_program, (netebpfext_helper_base_client_context_t*)client_context); + helper.require_initialized(); std::vector threads; @@ -1696,7 +1743,7 @@ TEST_CASE("sock_addr_listen_invoke", "[netebpfext]") &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_sock_addr_program, (netebpfext_helper_base_client_context_t*)client_context); - REQUIRE(helper.get_program_info_provider_data(EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR) != nullptr); + helper.require_initialized(); netebpfext_initialize_fwp_classify_parameters(¶meters); @@ -1734,6 +1781,7 @@ TEST_CASE("sock_addr_listen_invoke", "[netebpfext]") TEST_CASE("sock_addr_listen_context", "[netebpfext]") { netebpf_ext_helper_t helper; + helper.require_initialized(); auto sock_addr_program_data = helper.get_program_info_provider_data(EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR); REQUIRE(sock_addr_program_data != nullptr); diff --git a/tests/netebpfext_unit/netebpfext_unit.vcxproj b/tests/netebpfext_unit/netebpfext_unit.vcxproj index 95a627825c..2b377ebeff 100644 --- a/tests/netebpfext_unit/netebpfext_unit.vcxproj +++ b/tests/netebpfext_unit/netebpfext_unit.vcxproj @@ -18,6 +18,12 @@ $(EbpfPlatformToolset) Unicode + + Application + true + $(EbpfPlatformToolset) + Unicode + Application true @@ -38,6 +44,9 @@ + + + @@ -48,6 +57,9 @@ true + + true + true @@ -69,6 +81,21 @@ $(SolutionDir)$(Platform)\$(ConfigurationName)\;%(Link.AdditionalLibraryDirectories) + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)libs\api_common;$(SolutionDir)include;$(SolutionDir)libs\api;$(SolutionDir)libs\ebpfnetsh;$(SolutionDir)tests\libs\util;$(SolutionDir)tests\libs\common;$(OutDir);$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)external\ebpf-verifier\external;$(SolutionDir)external\ebpf-verifier\build\shim;$(SolutionDir)libs\service;$(SolutionDir)rpc_interface;$(SolutionDir)libs\runtime;$(SolutionDir)libs\runtime\user;$(SolutionDir)libs\shared;$(SolutionDir)libs\shared\user;$(SolutionDir)external\usersim\inc;$(SolutionDir)external\usersim\src;$(SolutionDir)external\usersim\cxplat\inc;$(SolutionDir)external\usersim\cxplat\inc\winuser;$(SolutionDir)libs\execution_context;$(SolutionDir)tests\end_to_end;$(SolutionDir)tests\sample;$(SolutionDir)tests\sample\ext\inc;$(SolutionDir)\tests\xdp;$(SolutionDir)tools\export_program_info;$(SolutionDir)libs\thunk;$(SolutionDir)libs\thunk\mock;$(SolutionDir)\netebpfext;$(SolutionDir)external\catch2\src;$(SolutionDir)external\catch2\build\generated-includes;$(SolutionDir)external\bpftool;$(SolutionDir)include\user;$(SolutionDir)\netebpfext\user;$(WindowsSdkDir)Include\$(WindowsTargetPlatformVersion)\km;$(SolutionDir)external\ebpf-extension-common\include;%(AdditionalIncludeDirectories) + + + Console + true + mincore.lib;%(AdditionalDependencies) + $(SolutionDir)$(Platform)\$(ConfigurationName)\;%(Link.AdditionalLibraryDirectories) + + Level3 From 60bebfe8f89bbdb8f5b09fa48a54558a98203e43 Mon Sep 17 00:00:00 2001 From: Shankar Seal Date: Mon, 31 Aug 2026 18:57:22 -0700 Subject: [PATCH 2/3] copy fault injection log to TestLogs directory. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: ea587460-e416-414f-9687-d52ae0a34d8f --- .github/workflows/reusable-test.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/reusable-test.yml b/.github/workflows/reusable-test.yml index 77f07d49f0..d4ee9e1328 100644 --- a/.github/workflows/reusable-test.yml +++ b/.github/workflows/reusable-test.yml @@ -449,6 +449,23 @@ jobs: run: | copy ${{github.workspace}}\${{env.BUILD_PLATFORM}}\${{env.BUILD_CONFIGURATION}}\*.log ${{github.workspace}}\${{env.BUILD_PLATFORM}}\${{env.BUILD_CONFIGURATION}}\TestLogs + - name: Copy fault injection logs to TestLogs + if: always() && (inputs.fault_injection == true) && (steps.skip_check.outputs.should_skip != 'true') + shell: pwsh + run: | + $outputDirectory = "${{github.workspace}}\${{env.BUILD_PLATFORM}}\${{env.BUILD_CONFIGURATION}}" + [array]$faultInjectionLogs = + Get-ChildItem -LiteralPath $outputDirectory -File | + Where-Object { $_.Name -match '\.(fault|passed)\.log$' } + if ($faultInjectionLogs.Count -eq 0) { + Write-Warning "No fault injection logs were found in $outputDirectory" + return + } + + $testLogDirectory = Join-Path $outputDirectory "TestLogs" + New-Item -ItemType Directory -Path $testLogDirectory -Force | Out-Null + Copy-Item -LiteralPath $faultInjectionLogs.FullName -Destination $testLogDirectory + - name: Check for crash dumps # Check for crash dumps even if the workflow failed. if: always() && (steps.skip_check.outputs.should_skip != 'true') From c65040f2ec8583f7b92da6405a192dd5ea2bf68a Mon Sep 17 00:00:00 2001 From: Shankar Seal Date: Thu, 10 Sep 2026 20:02:11 -0700 Subject: [PATCH 3/3] PR Feedback. --- .azure/reusable-test.yml | 18 ++++++++++- ebpf-for-windows.sln | 10 +++--- tests/netebpfext_unit/netebpf_ext_helper.h | 6 ++-- tests/netebpfext_unit/netebpfext_unit.vcxproj | 32 +++---------------- 4 files changed, 31 insertions(+), 35 deletions(-) diff --git a/.azure/reusable-test.yml b/.azure/reusable-test.yml index e2c87a7a15..d8022206f3 100644 --- a/.azure/reusable-test.yml +++ b/.azure/reusable-test.yml @@ -283,6 +283,22 @@ jobs: condition: and(eq('${{parameters.name}}', 'bpf2c'), eq('${{parameters.capture_etw}}', 'true')) displayName: Copy any bpf2c test logs to TestLogs + - powershell: | + $outputDirectory = "$(Build.SourcesDirectory)\$(PROJECT_NAME)\$(BUILD_PLATFORM)\$(BUILD_CONFIGURATION)" + [array]$faultInjectionLogs = + Get-ChildItem -LiteralPath $outputDirectory -File | + Where-Object { $_.Name -match '\.(fault|passed)\.log$' } + if ($faultInjectionLogs.Count -eq 0) { + Write-Warning "No fault injection logs were found in $outputDirectory" + return + } + + $testLogDirectory = Join-Path $outputDirectory "TestLogs" + New-Item -ItemType Directory -Path $testLogDirectory -Force | Out-Null + Copy-Item -LiteralPath $faultInjectionLogs.FullName -Destination $testLogDirectory + condition: and(succeededOrFailed(), eq('${{parameters.fault_injection}}', 'true')) + displayName: Copy fault injection logs to TestLogs + - powershell: | $fileExists = Test-Path -Path "$(DUMP_PATH)\*.dmp" Write-Output "##vso[task.setvariable variable=FileExists;isOutput=true]$fileExists" @@ -298,7 +314,7 @@ jobs: - powershell: | $fileExists = Test-Path -Path "$(Build.SourcesDirectory)\$(PROJECT_NAME)\$(BUILD_PLATFORM)\$(BUILD_CONFIGURATION)\TestLogs\*" Write-Output "##vso[task.setvariable variable=FileExists;isOutput=true]$fileExists" - condition: and(succeededOrFailed(), eq('${{parameters.capture_etw}}', 'true')) + condition: and(succeededOrFailed(), or(eq('${{parameters.capture_etw}}', 'true'), eq('${{parameters.fault_injection}}', 'true'))) name: check_logs displayName: Check for TestLogs diff --git a/ebpf-for-windows.sln b/ebpf-for-windows.sln index 4749cb3d01..94bae83c01 100644 --- a/ebpf-for-windows.sln +++ b/ebpf-for-windows.sln @@ -2749,14 +2749,16 @@ Global {E619B985-44B3-4292-A585-5CD0C4315ED3}.MinSizeRel|x64.Build.0 = Debug|x64 {E619B985-44B3-4292-A585-5CD0C4315ED3}.MinSizeRel|x86.ActiveCfg = NativeOnlyDebug|x64 {E619B985-44B3-4292-A585-5CD0C4315ED3}.MinSizeRel|x86.Build.0 = NativeOnlyDebug|x64 - {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|ARM64.ActiveCfg = NativeOnlyDebug|ARM64 - {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|ARM64.Build.0 = NativeOnlyDebug|ARM64 - {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|x64.ActiveCfg = NativeOnlyDebug|x64 - {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|x64.Build.0 = NativeOnlyDebug|x64 + {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|ARM64.ActiveCfg = Debug|ARM64 + {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|ARM64.Build.0 = Debug|ARM64 + {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|x64.ActiveCfg = Debug|x64 + {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|x64.Build.0 = Debug|x64 {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|x86.ActiveCfg = NativeOnlyDebug|x64 {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyDebug|x86.Build.0 = NativeOnlyDebug|x64 {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyRelease|ARM64.ActiveCfg = Release|ARM64 + {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyRelease|ARM64.Build.0 = Release|ARM64 {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyRelease|x64.ActiveCfg = Release|x64 + {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyRelease|x64.Build.0 = Release|x64 {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyRelease|x86.ActiveCfg = NativeOnlyRelease|x64 {E619B985-44B3-4292-A585-5CD0C4315ED3}.NativeOnlyRelease|x86.Build.0 = NativeOnlyRelease|x64 {E619B985-44B3-4292-A585-5CD0C4315ED3}.Release|ARM64.ActiveCfg = Release|ARM64 diff --git a/tests/netebpfext_unit/netebpf_ext_helper.h b/tests/netebpfext_unit/netebpf_ext_helper.h index cb8d985e7b..3d84e779ea 100644 --- a/tests/netebpfext_unit/netebpf_ext_helper.h +++ b/tests/netebpfext_unit/netebpf_ext_helper.h @@ -209,14 +209,14 @@ typedef class _netebpf_ext_helper _nmr_client_registration( _In_ const NPI_CLIENT_CHARACTERISTICS* characteristics, _In_opt_ __drv_aliasesMem void* client_context) { - nmr_client_handle = INVALID_HANDLE_VALUE; + nmr_client_handle = nullptr; // Don't use REQUIRE in a constructor. (void)NmrRegisterClient(characteristics, client_context, &nmr_client_handle); } ~_nmr_client_registration() { - if (nmr_client_handle != INVALID_HANDLE_VALUE) { + if (nmr_client_handle != nullptr) { NTSTATUS status = NmrDeregisterClient(nmr_client_handle); if (status == STATUS_PENDING) { status = NmrWaitForClientDeregisterComplete(nmr_client_handle); @@ -231,7 +231,7 @@ typedef class _netebpf_ext_helper bool is_registered() const { - return nmr_client_handle != INVALID_HANDLE_VALUE; + return nmr_client_handle != nullptr; } HANDLE nmr_client_handle; diff --git a/tests/netebpfext_unit/netebpfext_unit.vcxproj b/tests/netebpfext_unit/netebpfext_unit.vcxproj index 2b377ebeff..dd3cd1eb13 100644 --- a/tests/netebpfext_unit/netebpfext_unit.vcxproj +++ b/tests/netebpfext_unit/netebpfext_unit.vcxproj @@ -18,12 +18,6 @@ $(EbpfPlatformToolset) Unicode - - Application - true - $(EbpfPlatformToolset) - Unicode - Application true @@ -44,9 +38,6 @@ - - - @@ -57,9 +48,6 @@ true - - true - true @@ -81,21 +69,6 @@ $(SolutionDir)$(Platform)\$(ConfigurationName)\;%(Link.AdditionalLibraryDirectories) - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - $(SolutionDir)libs\api_common;$(SolutionDir)include;$(SolutionDir)libs\api;$(SolutionDir)libs\ebpfnetsh;$(SolutionDir)tests\libs\util;$(SolutionDir)tests\libs\common;$(OutDir);$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)external\ebpf-verifier\external;$(SolutionDir)external\ebpf-verifier\build\shim;$(SolutionDir)libs\service;$(SolutionDir)rpc_interface;$(SolutionDir)libs\runtime;$(SolutionDir)libs\runtime\user;$(SolutionDir)libs\shared;$(SolutionDir)libs\shared\user;$(SolutionDir)external\usersim\inc;$(SolutionDir)external\usersim\src;$(SolutionDir)external\usersim\cxplat\inc;$(SolutionDir)external\usersim\cxplat\inc\winuser;$(SolutionDir)libs\execution_context;$(SolutionDir)tests\end_to_end;$(SolutionDir)tests\sample;$(SolutionDir)tests\sample\ext\inc;$(SolutionDir)\tests\xdp;$(SolutionDir)tools\export_program_info;$(SolutionDir)libs\thunk;$(SolutionDir)libs\thunk\mock;$(SolutionDir)\netebpfext;$(SolutionDir)external\catch2\src;$(SolutionDir)external\catch2\build\generated-includes;$(SolutionDir)external\bpftool;$(SolutionDir)include\user;$(SolutionDir)\netebpfext\user;$(WindowsSdkDir)Include\$(WindowsTargetPlatformVersion)\km;$(SolutionDir)external\ebpf-extension-common\include;%(AdditionalIncludeDirectories) - - - Console - true - mincore.lib;%(AdditionalDependencies) - $(SolutionDir)$(Platform)\$(ConfigurationName)\;%(Link.AdditionalLibraryDirectories) - - Level3 @@ -134,6 +107,11 @@ + + + %(AdditionalIncludeDirectories);$(SolutionDir)$(Platform)\NativeOnlyDebug;$(SolutionDir)$(Platform)\NativeOnlyRelease + + {8d538cbe-01bf-4a2e-a98a-6c368fdf13d7}