From 853d82ef4841ef34f3a7e4dcc77a06f092f6931a Mon Sep 17 00:00:00 2001 From: Parth Aggarwal Date: Wed, 11 Feb 2026 16:11:56 -0800 Subject: [PATCH 1/4] Add timed test suite validation to build_test_folder Co-Authored-By: Claude Opus 4.6 --- build_functions/CMakeLists.txt | 31 +++ .../CMakeLists.txt | 122 +++++++++ .../has_violations/has_include_int.c | 16 ++ .../has_violations/has_include_int_expected.c | 16 ++ .../has_violations/multi_arg_int.c | 15 ++ .../has_violations/multi_arg_int_expected.c | 16 ++ .../has_violations/sample_module_int.c | 15 ++ .../sample_module_int_expected.c | 16 ++ .../no_violations/exempted_module_int.c | 15 ++ .../no_violations/no_init_int.c | 9 + .../no_violations/timed_module_int.c | 16 ++ build_functions/validate_timed_test_suite.ps1 | 254 ++++++++++++++++++ 12 files changed, 541 insertions(+) create mode 100644 build_functions/tests_validate_timed_test_suite/CMakeLists.txt create mode 100644 build_functions/tests_validate_timed_test_suite/has_violations/has_include_int.c create mode 100644 build_functions/tests_validate_timed_test_suite/has_violations/has_include_int_expected.c create mode 100644 build_functions/tests_validate_timed_test_suite/has_violations/multi_arg_int.c create mode 100644 build_functions/tests_validate_timed_test_suite/has_violations/multi_arg_int_expected.c create mode 100644 build_functions/tests_validate_timed_test_suite/has_violations/sample_module_int.c create mode 100644 build_functions/tests_validate_timed_test_suite/has_violations/sample_module_int_expected.c create mode 100644 build_functions/tests_validate_timed_test_suite/no_violations/exempted_module_int.c create mode 100644 build_functions/tests_validate_timed_test_suite/no_violations/no_init_int.c create mode 100644 build_functions/tests_validate_timed_test_suite/no_violations/timed_module_int.c create mode 100644 build_functions/validate_timed_test_suite.ps1 diff --git a/build_functions/CMakeLists.txt b/build_functions/CMakeLists.txt index 3bfa98a..d62fcde 100644 --- a/build_functions/CMakeLists.txt +++ b/build_functions/CMakeLists.txt @@ -344,6 +344,28 @@ function(build_exe whatIsBuilding solution_folder custom_main) endif() endfunction() +# Validates that *_int.c files in test_folder use TIMED_TEST_SUITE_INITIALIZE/CLEANUP. +# Skip specific folders: cmake -Dtimed_test_suite_skip_regex="module_a_int|module_b_int" +function(validate_timed_test_suite test_folder) + # Allow skipping via regex + if(DEFINED timed_test_suite_skip_regex AND NOT "${timed_test_suite_skip_regex}" STREQUAL "") + if("${test_folder}" MATCHES "${timed_test_suite_skip_regex}") + return() + endif() + endif() + + set(script_path "${trsw_internal_dir}/validate_timed_test_suite.ps1") + if(EXISTS "${script_path}") + add_custom_target(${test_folder}_timed_suite_check ALL + COMMAND powershell.exe -ExecutionPolicy Bypass + -File "${script_path}" + -RepoRoot "${CMAKE_CURRENT_SOURCE_DIR}/${test_folder}" + COMMENT "Validating timed test suite in ${test_folder}" + VERBATIM + ) + endif() +endfunction() + #drop in replacement for add_subdirectory :) #test_folder is the name of a folder that exists on the drive. For example "clds_hash_table_ut". It is not a complete path. function(build_test_folder test_folder) @@ -368,6 +390,11 @@ function(build_test_folder test_folder) set(building dll) add_subdirectory(${test_folder} ${test_folder}/${arg_BINARY_DIR}/${building}) endif() + + # Validate timed test suite for integration tests + if(WIN32 AND ("${test_folder}" MATCHES ".*int.*")) + validate_timed_test_suite(${test_folder}) + endif() else() #message("test_folder is ${test_folder} NOT BUILDING") endif() @@ -404,3 +431,7 @@ function(build_test_artifacts_with_custom_main whatIsBuilding solution_folder ) MESSAGE(FATAL_ERROR "not an expected value: building=${building} test_folder=${test_folder} ARGN=${ARGN}") endif() endfunction() + +if(${run_unittests}) + add_subdirectory(tests_validate_timed_test_suite) +endif() diff --git a/build_functions/tests_validate_timed_test_suite/CMakeLists.txt b/build_functions/tests_validate_timed_test_suite/CMakeLists.txt new file mode 100644 index 0000000..871b45b --- /dev/null +++ b/build_functions/tests_validate_timed_test_suite/CMakeLists.txt @@ -0,0 +1,122 @@ +# Copyright (c) Microsoft. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for full license information. + +# +# Timed Test Suite Validation Tests +# +# Tests the validate_timed_test_suite.ps1 script to ensure it correctly detects +# integration test files using non-timed TEST_SUITE_INITIALIZE/CLEANUP macros +# and validates the fix functionality works properly. +# + +set(POWERSHELL_EXECUTABLE "powershell.exe") +set(VALIDATE_TIMED_TEST_SUITE_SCRIPT "${trsw_internal_dir}/validate_timed_test_suite.ps1") + +# Test 1: Verify script detects non-timed macros in files that have them +add_custom_target(test_validate_timed_test_suite_detection + COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" + -RepoRoot "${CMAKE_CURRENT_SOURCE_DIR}/has_violations" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Testing timed test suite detection on files with non-timed macros" +) + +# Test 2: Verify script passes on files already using timed macros +add_custom_target(test_validate_timed_test_suite_clean + COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" + -RepoRoot "${CMAKE_CURRENT_SOURCE_DIR}/no_violations" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Testing timed test suite validation on clean files" +) + +# Test 3: Verify fix functionality works (copy test files to temp directory first) +add_custom_target(test_validate_timed_test_suite_fix + # Create a temporary directory and copy test files + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/temp_fix_test" + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_CURRENT_SOURCE_DIR}/has_violations" + "${CMAKE_CURRENT_BINARY_DIR}/temp_fix_test" + # Run the script with fix mode + COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" + -RepoRoot "${CMAKE_CURRENT_BINARY_DIR}/temp_fix_test" + -Fix + # Verify violations were fixed (script should pass now) + COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" + -RepoRoot "${CMAKE_CURRENT_BINARY_DIR}/temp_fix_test" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Testing timed test suite fix functionality" +) + +# Test 4: Verify fix correctly handles multi-arg macros +add_custom_target(test_validate_timed_test_suite_fix_multi_arg + # Create a temporary directory and copy the multi-arg test file + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/temp_multi_arg_test" + COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/has_violations/multi_arg_int.c" + "${CMAKE_CURRENT_BINARY_DIR}/temp_multi_arg_test/" + # Run the script with fix mode + COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" + -RepoRoot "${CMAKE_CURRENT_BINARY_DIR}/temp_multi_arg_test" + -Fix + # Compare the result with the expected file + COMMAND ${CMAKE_COMMAND} -E compare_files + "${CMAKE_CURRENT_BINARY_DIR}/temp_multi_arg_test/multi_arg_int.c" + "${CMAKE_CURRENT_SOURCE_DIR}/has_violations/multi_arg_int_expected.c" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Testing that multi-arg macros are fixed correctly" +) + +# Test 5: Verify fix correctly handles basic case (compare_files for sample_module_int) +add_custom_target(test_validate_timed_test_suite_fix_basic + # Create a temporary directory and copy the basic test file + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/temp_basic_test" + COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/has_violations/sample_module_int.c" + "${CMAKE_CURRENT_BINARY_DIR}/temp_basic_test/" + # Run the script with fix mode + COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" + -RepoRoot "${CMAKE_CURRENT_BINARY_DIR}/temp_basic_test" + -Fix + # Compare the result with the expected file + COMMAND ${CMAKE_COMMAND} -E compare_files + "${CMAKE_CURRENT_BINARY_DIR}/temp_basic_test/sample_module_int.c" + "${CMAKE_CURRENT_SOURCE_DIR}/has_violations/sample_module_int_expected.c" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Testing that basic macros are fixed correctly and include is added" +) + +# Test 6: Verify fix does not duplicate timed_test_suite.h include when already present +add_custom_target(test_validate_timed_test_suite_fix_no_duplicate_include + # Create a temporary directory and copy the file that already has the include + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/temp_no_dup_include_test" + COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/has_violations/has_include_int.c" + "${CMAKE_CURRENT_BINARY_DIR}/temp_no_dup_include_test/" + # Run the script with fix mode + COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" + -RepoRoot "${CMAKE_CURRENT_BINARY_DIR}/temp_no_dup_include_test" + -Fix + # Compare the result with the expected file (should NOT have duplicate include) + COMMAND ${CMAKE_COMMAND} -E compare_files + "${CMAKE_CURRENT_BINARY_DIR}/temp_no_dup_include_test/has_include_int.c" + "${CMAKE_CURRENT_SOURCE_DIR}/has_violations/has_include_int_expected.c" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Testing that fix does not duplicate timed_test_suite.h include" +) + +# Master target for all timed test suite validation tests +add_custom_target(test_validate_timed_test_suite + COMMENT "Running all timed test suite validation tests" +) + +# Add dependencies - detection test should fail (exit code 1), clean test should pass +add_dependencies(test_validate_timed_test_suite + test_validate_timed_test_suite_clean + test_validate_timed_test_suite_fix + test_validate_timed_test_suite_fix_multi_arg + test_validate_timed_test_suite_fix_basic + test_validate_timed_test_suite_fix_no_duplicate_include +) + +# Note: We don't add test_validate_timed_test_suite_detection as a dependency because +# it should fail with exit code 1 (which would fail the build). +# Instead, it's available to run manually to verify detection works. diff --git a/build_functions/tests_validate_timed_test_suite/has_violations/has_include_int.c b/build_functions/tests_validate_timed_test_suite/has_violations/has_include_int.c new file mode 100644 index 0000000..e16fc8f --- /dev/null +++ b/build_functions/tests_validate_timed_test_suite/has_violations/has_include_int.c @@ -0,0 +1,16 @@ +#include "testrunnerswitcher.h" +#include "c_pal/gballoc_hl.h" +#include "c_pal/timed_test_suite.h" + +BEGIN_TEST_SUITE(has_include_int) +TEST_SUITE_INITIALIZE(suite_init) +{ +} +TEST_SUITE_CLEANUP(suite_cleanup) +{ +} +TEST_FUNCTION(test1) +{ + ASSERT_IS_TRUE(1); +} +END_TEST_SUITE(has_include_int) diff --git a/build_functions/tests_validate_timed_test_suite/has_violations/has_include_int_expected.c b/build_functions/tests_validate_timed_test_suite/has_violations/has_include_int_expected.c new file mode 100644 index 0000000..1180f32 --- /dev/null +++ b/build_functions/tests_validate_timed_test_suite/has_violations/has_include_int_expected.c @@ -0,0 +1,16 @@ +#include "testrunnerswitcher.h" +#include "c_pal/gballoc_hl.h" +#include "c_pal/timed_test_suite.h" + +BEGIN_TEST_SUITE(has_include_int) +TIMED_TEST_SUITE_INITIALIZE(suite_init, TIMED_TEST_DEFAULT_TIMEOUT_MS) +{ +} +TIMED_TEST_SUITE_CLEANUP(suite_cleanup) +{ +} +TEST_FUNCTION(test1) +{ + ASSERT_IS_TRUE(1); +} +END_TEST_SUITE(has_include_int) diff --git a/build_functions/tests_validate_timed_test_suite/has_violations/multi_arg_int.c b/build_functions/tests_validate_timed_test_suite/has_violations/multi_arg_int.c new file mode 100644 index 0000000..c29ebaa --- /dev/null +++ b/build_functions/tests_validate_timed_test_suite/has_violations/multi_arg_int.c @@ -0,0 +1,15 @@ +#include "testrunnerswitcher.h" +#include "c_pal/gballoc_hl.h" + +BEGIN_TEST_SUITE(multi_arg_int) +TEST_SUITE_INITIALIZE(suite_init, setup_gballoc) +{ +} +TEST_SUITE_CLEANUP(suite_cleanup, cleanup_gballoc) +{ +} +TEST_FUNCTION(test1) +{ + ASSERT_IS_TRUE(1); +} +END_TEST_SUITE(multi_arg_int) diff --git a/build_functions/tests_validate_timed_test_suite/has_violations/multi_arg_int_expected.c b/build_functions/tests_validate_timed_test_suite/has_violations/multi_arg_int_expected.c new file mode 100644 index 0000000..875f4ae --- /dev/null +++ b/build_functions/tests_validate_timed_test_suite/has_violations/multi_arg_int_expected.c @@ -0,0 +1,16 @@ +#include "testrunnerswitcher.h" +#include "c_pal/gballoc_hl.h" +#include "c_pal/timed_test_suite.h" + +BEGIN_TEST_SUITE(multi_arg_int) +TIMED_TEST_SUITE_INITIALIZE(suite_init, TIMED_TEST_DEFAULT_TIMEOUT_MS, setup_gballoc) +{ +} +TIMED_TEST_SUITE_CLEANUP(suite_cleanup, cleanup_gballoc) +{ +} +TEST_FUNCTION(test1) +{ + ASSERT_IS_TRUE(1); +} +END_TEST_SUITE(multi_arg_int) diff --git a/build_functions/tests_validate_timed_test_suite/has_violations/sample_module_int.c b/build_functions/tests_validate_timed_test_suite/has_violations/sample_module_int.c new file mode 100644 index 0000000..4c25391 --- /dev/null +++ b/build_functions/tests_validate_timed_test_suite/has_violations/sample_module_int.c @@ -0,0 +1,15 @@ +#include "testrunnerswitcher.h" +#include "c_pal/gballoc_hl.h" + +BEGIN_TEST_SUITE(sample_module_int) +TEST_SUITE_INITIALIZE(suite_init) +{ +} +TEST_SUITE_CLEANUP(suite_cleanup) +{ +} +TEST_FUNCTION(test1) +{ + ASSERT_IS_TRUE(1); +} +END_TEST_SUITE(sample_module_int) diff --git a/build_functions/tests_validate_timed_test_suite/has_violations/sample_module_int_expected.c b/build_functions/tests_validate_timed_test_suite/has_violations/sample_module_int_expected.c new file mode 100644 index 0000000..f6ca245 --- /dev/null +++ b/build_functions/tests_validate_timed_test_suite/has_violations/sample_module_int_expected.c @@ -0,0 +1,16 @@ +#include "testrunnerswitcher.h" +#include "c_pal/gballoc_hl.h" +#include "c_pal/timed_test_suite.h" + +BEGIN_TEST_SUITE(sample_module_int) +TIMED_TEST_SUITE_INITIALIZE(suite_init, TIMED_TEST_DEFAULT_TIMEOUT_MS) +{ +} +TIMED_TEST_SUITE_CLEANUP(suite_cleanup) +{ +} +TEST_FUNCTION(test1) +{ + ASSERT_IS_TRUE(1); +} +END_TEST_SUITE(sample_module_int) diff --git a/build_functions/tests_validate_timed_test_suite/no_violations/exempted_module_int.c b/build_functions/tests_validate_timed_test_suite/no_violations/exempted_module_int.c new file mode 100644 index 0000000..8e7a398 --- /dev/null +++ b/build_functions/tests_validate_timed_test_suite/no_violations/exempted_module_int.c @@ -0,0 +1,15 @@ +#include "testrunnerswitcher.h" +#include "c_pal/gballoc_hl.h" + +BEGIN_TEST_SUITE(exempted_module_int) +TEST_SUITE_INITIALIZE(suite_init) // no-timed-test-suite +{ +} +TEST_SUITE_CLEANUP(suite_cleanup) +{ +} +TEST_FUNCTION(test1) +{ + ASSERT_IS_TRUE(1); +} +END_TEST_SUITE(exempted_module_int) diff --git a/build_functions/tests_validate_timed_test_suite/no_violations/no_init_int.c b/build_functions/tests_validate_timed_test_suite/no_violations/no_init_int.c new file mode 100644 index 0000000..f7007ea --- /dev/null +++ b/build_functions/tests_validate_timed_test_suite/no_violations/no_init_int.c @@ -0,0 +1,9 @@ +#include "testrunnerswitcher.h" +#include "c_pal/gballoc_hl.h" + +BEGIN_TEST_SUITE(no_init_int) +TEST_FUNCTION(test1) +{ + ASSERT_IS_TRUE(1); +} +END_TEST_SUITE(no_init_int) diff --git a/build_functions/tests_validate_timed_test_suite/no_violations/timed_module_int.c b/build_functions/tests_validate_timed_test_suite/no_violations/timed_module_int.c new file mode 100644 index 0000000..0671d81 --- /dev/null +++ b/build_functions/tests_validate_timed_test_suite/no_violations/timed_module_int.c @@ -0,0 +1,16 @@ +#include "testrunnerswitcher.h" +#include "c_pal/gballoc_hl.h" +#include "c_pal/timed_test_suite.h" + +BEGIN_TEST_SUITE(timed_module_int) +TIMED_TEST_SUITE_INITIALIZE(suite_init, TIMED_TEST_DEFAULT_TIMEOUT_MS) +{ +} +TIMED_TEST_SUITE_CLEANUP(suite_cleanup) +{ +} +TEST_FUNCTION(test1) +{ + ASSERT_IS_TRUE(1); +} +END_TEST_SUITE(timed_module_int) diff --git a/build_functions/validate_timed_test_suite.ps1 b/build_functions/validate_timed_test_suite.ps1 new file mode 100644 index 0000000..fe987da --- /dev/null +++ b/build_functions/validate_timed_test_suite.ps1 @@ -0,0 +1,254 @@ +# Copyright (c) Microsoft. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for full license information. + +<# +.SYNOPSIS + Validates that integration test files use TIMED_TEST_SUITE_INITIALIZE/CLEANUP macros. + +.DESCRIPTION + This script checks all integration test files (*_int.c) to ensure they use the timed + versions of TEST_SUITE_INITIALIZE and TEST_SUITE_CLEANUP macros. The timed macros + (TIMED_TEST_SUITE_INITIALIZE / TIMED_TEST_SUITE_CLEANUP) wrap the vanilla versions + with a process watchdog that crashes the process and produces a dump on timeout, + allowing dumps to be collected if the test hangs. + + The script automatically excludes dependency directories to avoid modifying third-party code. + + When the -Fix switch is provided, the script will automatically replace the vanilla + macros with their timed equivalents and add the required include if not present. + +.PARAMETER RepoRoot + The root directory of the repository to validate. + +.PARAMETER ExcludeFolders + Comma-separated list of additional folders to exclude from validation. + +.PARAMETER Fix + If specified, automatically replace TEST_SUITE_INITIALIZE/CLEANUP with timed versions. + +.EXAMPLE + .\validate_timed_test_suite.ps1 -RepoRoot "C:\repo" + + Validates all integration test files and reports files using non-timed macros. + +.EXAMPLE + .\validate_timed_test_suite.ps1 -RepoRoot "C:\repo" -Fix + + Validates and automatically replaces non-timed macros with timed versions. + +.NOTES + Returns exit code 0 if all files are valid (or were fixed), 1 if validation fails. + Dependencies in deps/ and dependencies/ directories are automatically excluded. +#> + +param( + [Parameter(Mandatory=$true)] + [string]$RepoRoot, + + [Parameter(Mandatory=$false)] + [string]$ExcludeFolders = "deps,cmake", + + [Parameter(Mandatory=$false)] + [switch]$Fix +) + +# Set error action preference +$ErrorActionPreference = "Stop" + +Write-Host "========================================" -ForegroundColor Cyan +Write-Host "Timed Test Suite Validation" -ForegroundColor Cyan +Write-Host "========================================" -ForegroundColor Cyan +Write-Host "Repository Root: $RepoRoot" -ForegroundColor White +Write-Host "Fix Mode: $($Fix.IsPresent)" -ForegroundColor White +Write-Host "" + +# Parse excluded directories (default: deps, cmake) +$excludeDirs = $ExcludeFolders -split "," | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" } + +Write-Host "Excluded directories: $($excludeDirs -join ', ')" -ForegroundColor White +Write-Host "" + +# Initialize counters +$totalFiles = 0 +$filesWithViolations = @() +$fixedFiles = @() +$skippedFiles = 0 + +# Get all integration test files in the repository +Write-Host "Searching for integration test files (*_int.c)..." -ForegroundColor White +$allFiles = @(Get-ChildItem -Path $RepoRoot -Recurse -Filter "*_int.c" -ErrorAction SilentlyContinue) + +Write-Host "Found $($allFiles.Count) integration test files to check" -ForegroundColor White +Write-Host "" + +# Pattern to match non-timed TEST_SUITE_INITIALIZE/CLEANUP +# Uses negative lookbehind to exclude lines that already have TIMED_ prefix +$initPattern = '(? TIMED_TEST_SUITE_INITIALIZE(name, TIMED_TEST_DEFAULT_TIMEOUT_MS + if ($currentLine -match $initPattern) { + # Match: TEST_SUITE_INITIALIZE( name [, extra_args...] ) + # We need to insert TIMED_TEST_DEFAULT_TIMEOUT_MS as 2nd arg after the first arg + $currentLine = $currentLine -replace '(? TIMED_TEST_SUITE_CLEANUP( + if ($currentLine -match $cleanupPattern) { + $currentLine = $currentLine -replace '(? Date: Wed, 11 Feb 2026 17:24:29 -0800 Subject: [PATCH 2/4] Address PR comments: rename param, remove exemption logic Co-Authored-By: Claude Opus 4.6 --- build_functions/CMakeLists.txt | 2 +- .../CMakeLists.txt | 14 ++-- .../no_violations/exempted_module_int.c | 15 ---- build_functions/validate_timed_test_suite.ps1 | 78 ++++--------------- 4 files changed, 22 insertions(+), 87 deletions(-) delete mode 100644 build_functions/tests_validate_timed_test_suite/no_violations/exempted_module_int.c diff --git a/build_functions/CMakeLists.txt b/build_functions/CMakeLists.txt index d62fcde..ed5416a 100644 --- a/build_functions/CMakeLists.txt +++ b/build_functions/CMakeLists.txt @@ -359,7 +359,7 @@ function(validate_timed_test_suite test_folder) add_custom_target(${test_folder}_timed_suite_check ALL COMMAND powershell.exe -ExecutionPolicy Bypass -File "${script_path}" - -RepoRoot "${CMAKE_CURRENT_SOURCE_DIR}/${test_folder}" + -TestFolder "${CMAKE_CURRENT_SOURCE_DIR}/${test_folder}" COMMENT "Validating timed test suite in ${test_folder}" VERBATIM ) diff --git a/build_functions/tests_validate_timed_test_suite/CMakeLists.txt b/build_functions/tests_validate_timed_test_suite/CMakeLists.txt index 871b45b..e539dcc 100644 --- a/build_functions/tests_validate_timed_test_suite/CMakeLists.txt +++ b/build_functions/tests_validate_timed_test_suite/CMakeLists.txt @@ -15,7 +15,7 @@ set(VALIDATE_TIMED_TEST_SUITE_SCRIPT "${trsw_internal_dir}/validate_timed_test_s # Test 1: Verify script detects non-timed macros in files that have them add_custom_target(test_validate_timed_test_suite_detection COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" - -RepoRoot "${CMAKE_CURRENT_SOURCE_DIR}/has_violations" + -TestFolder "${CMAKE_CURRENT_SOURCE_DIR}/has_violations" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Testing timed test suite detection on files with non-timed macros" ) @@ -23,7 +23,7 @@ add_custom_target(test_validate_timed_test_suite_detection # Test 2: Verify script passes on files already using timed macros add_custom_target(test_validate_timed_test_suite_clean COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" - -RepoRoot "${CMAKE_CURRENT_SOURCE_DIR}/no_violations" + -TestFolder "${CMAKE_CURRENT_SOURCE_DIR}/no_violations" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Testing timed test suite validation on clean files" ) @@ -37,11 +37,11 @@ add_custom_target(test_validate_timed_test_suite_fix "${CMAKE_CURRENT_BINARY_DIR}/temp_fix_test" # Run the script with fix mode COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" - -RepoRoot "${CMAKE_CURRENT_BINARY_DIR}/temp_fix_test" + -TestFolder "${CMAKE_CURRENT_BINARY_DIR}/temp_fix_test" -Fix # Verify violations were fixed (script should pass now) COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" - -RepoRoot "${CMAKE_CURRENT_BINARY_DIR}/temp_fix_test" + -TestFolder "${CMAKE_CURRENT_BINARY_DIR}/temp_fix_test" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Testing timed test suite fix functionality" ) @@ -55,7 +55,7 @@ add_custom_target(test_validate_timed_test_suite_fix_multi_arg "${CMAKE_CURRENT_BINARY_DIR}/temp_multi_arg_test/" # Run the script with fix mode COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" - -RepoRoot "${CMAKE_CURRENT_BINARY_DIR}/temp_multi_arg_test" + -TestFolder "${CMAKE_CURRENT_BINARY_DIR}/temp_multi_arg_test" -Fix # Compare the result with the expected file COMMAND ${CMAKE_COMMAND} -E compare_files @@ -74,7 +74,7 @@ add_custom_target(test_validate_timed_test_suite_fix_basic "${CMAKE_CURRENT_BINARY_DIR}/temp_basic_test/" # Run the script with fix mode COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" - -RepoRoot "${CMAKE_CURRENT_BINARY_DIR}/temp_basic_test" + -TestFolder "${CMAKE_CURRENT_BINARY_DIR}/temp_basic_test" -Fix # Compare the result with the expected file COMMAND ${CMAKE_COMMAND} -E compare_files @@ -93,7 +93,7 @@ add_custom_target(test_validate_timed_test_suite_fix_no_duplicate_include "${CMAKE_CURRENT_BINARY_DIR}/temp_no_dup_include_test/" # Run the script with fix mode COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" - -RepoRoot "${CMAKE_CURRENT_BINARY_DIR}/temp_no_dup_include_test" + -TestFolder "${CMAKE_CURRENT_BINARY_DIR}/temp_no_dup_include_test" -Fix # Compare the result with the expected file (should NOT have duplicate include) COMMAND ${CMAKE_COMMAND} -E compare_files diff --git a/build_functions/tests_validate_timed_test_suite/no_violations/exempted_module_int.c b/build_functions/tests_validate_timed_test_suite/no_violations/exempted_module_int.c deleted file mode 100644 index 8e7a398..0000000 --- a/build_functions/tests_validate_timed_test_suite/no_violations/exempted_module_int.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "testrunnerswitcher.h" -#include "c_pal/gballoc_hl.h" - -BEGIN_TEST_SUITE(exempted_module_int) -TEST_SUITE_INITIALIZE(suite_init) // no-timed-test-suite -{ -} -TEST_SUITE_CLEANUP(suite_cleanup) -{ -} -TEST_FUNCTION(test1) -{ - ASSERT_IS_TRUE(1); -} -END_TEST_SUITE(exempted_module_int) diff --git a/build_functions/validate_timed_test_suite.ps1 b/build_functions/validate_timed_test_suite.ps1 index fe987da..821a40e 100644 --- a/build_functions/validate_timed_test_suite.ps1 +++ b/build_functions/validate_timed_test_suite.ps1 @@ -6,47 +6,38 @@ Validates that integration test files use TIMED_TEST_SUITE_INITIALIZE/CLEANUP macros. .DESCRIPTION - This script checks all integration test files (*_int.c) to ensure they use the timed - versions of TEST_SUITE_INITIALIZE and TEST_SUITE_CLEANUP macros. The timed macros - (TIMED_TEST_SUITE_INITIALIZE / TIMED_TEST_SUITE_CLEANUP) wrap the vanilla versions - with a process watchdog that crashes the process and produces a dump on timeout, - allowing dumps to be collected if the test hangs. - - The script automatically excludes dependency directories to avoid modifying third-party code. + This script checks integration test files (*_int.c) in a given test folder to ensure + they use the timed versions of TEST_SUITE_INITIALIZE and TEST_SUITE_CLEANUP macros. + The timed macros (TIMED_TEST_SUITE_INITIALIZE / TIMED_TEST_SUITE_CLEANUP) wrap the + vanilla versions with a process watchdog that crashes the process and produces a dump + on timeout, allowing dumps to be collected if the test hangs. When the -Fix switch is provided, the script will automatically replace the vanilla macros with their timed equivalents and add the required include if not present. -.PARAMETER RepoRoot - The root directory of the repository to validate. - -.PARAMETER ExcludeFolders - Comma-separated list of additional folders to exclude from validation. +.PARAMETER TestFolder + The path to the test folder to validate. .PARAMETER Fix If specified, automatically replace TEST_SUITE_INITIALIZE/CLEANUP with timed versions. .EXAMPLE - .\validate_timed_test_suite.ps1 -RepoRoot "C:\repo" + .\validate_timed_test_suite.ps1 -TestFolder "C:\repo\tests\my_module_int" - Validates all integration test files and reports files using non-timed macros. + Validates integration test files in the folder and reports files using non-timed macros. .EXAMPLE - .\validate_timed_test_suite.ps1 -RepoRoot "C:\repo" -Fix + .\validate_timed_test_suite.ps1 -TestFolder "C:\repo\tests\my_module_int" -Fix Validates and automatically replaces non-timed macros with timed versions. .NOTES Returns exit code 0 if all files are valid (or were fixed), 1 if validation fails. - Dependencies in deps/ and dependencies/ directories are automatically excluded. #> param( [Parameter(Mandatory=$true)] - [string]$RepoRoot, - - [Parameter(Mandatory=$false)] - [string]$ExcludeFolders = "deps,cmake", + [string]$TestFolder, [Parameter(Mandatory=$false)] [switch]$Fix @@ -58,25 +49,18 @@ $ErrorActionPreference = "Stop" Write-Host "========================================" -ForegroundColor Cyan Write-Host "Timed Test Suite Validation" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan -Write-Host "Repository Root: $RepoRoot" -ForegroundColor White +Write-Host "Test Folder: $TestFolder" -ForegroundColor White Write-Host "Fix Mode: $($Fix.IsPresent)" -ForegroundColor White Write-Host "" -# Parse excluded directories (default: deps, cmake) -$excludeDirs = $ExcludeFolders -split "," | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" } - -Write-Host "Excluded directories: $($excludeDirs -join ', ')" -ForegroundColor White -Write-Host "" - # Initialize counters $totalFiles = 0 $filesWithViolations = @() $fixedFiles = @() -$skippedFiles = 0 -# Get all integration test files in the repository +# Get all integration test files in the folder Write-Host "Searching for integration test files (*_int.c)..." -ForegroundColor White -$allFiles = @(Get-ChildItem -Path $RepoRoot -Recurse -Filter "*_int.c" -ErrorAction SilentlyContinue) +$allFiles = @(Get-ChildItem -Path $TestFolder -Recurse -Filter "*_int.c" -ErrorAction SilentlyContinue) Write-Host "Found $($allFiles.Count) integration test files to check" -ForegroundColor White Write-Host "" @@ -86,27 +70,7 @@ Write-Host "" $initPattern = '(? TIMED_TEST_SUITE_INITIALIZE(name, TIMED_TEST_DEFAULT_TIMEOUT_MS if ($currentLine -match $initPattern) { - # Match: TEST_SUITE_INITIALIZE( name [, extra_args...] ) - # We need to insert TIMED_TEST_DEFAULT_TIMEOUT_MS as 2nd arg after the first arg $currentLine = $currentLine -replace '(? Date: Wed, 11 Feb 2026 17:59:59 -0800 Subject: [PATCH 3/4] Remove -Fix logic, move script to scripts/ and tests to tests/ Co-Authored-By: Claude Opus 4.6 --- build_functions/CMakeLists.txt | 4 +- .../validate_timed_test_suite.ps1 | 101 ++------------- .../validate_timed_test_suite/CMakeLists.txt | 41 ++++++ .../has_violations/has_include_int.c | 0 .../has_violations/multi_arg_int.c | 0 .../has_violations/sample_module_int.c | 0 .../no_violations/no_init_int.c | 0 .../no_violations/timed_module_int.c | 0 .../CMakeLists.txt | 122 ------------------ .../has_violations/has_include_int_expected.c | 16 --- .../has_violations/multi_arg_int_expected.c | 16 --- .../sample_module_int_expected.c | 16 --- 12 files changed, 52 insertions(+), 264 deletions(-) rename build_functions/{ => scripts}/validate_timed_test_suite.ps1 (53%) create mode 100644 build_functions/tests/validate_timed_test_suite/CMakeLists.txt rename build_functions/{tests_validate_timed_test_suite => tests/validate_timed_test_suite}/has_violations/has_include_int.c (100%) rename build_functions/{tests_validate_timed_test_suite => tests/validate_timed_test_suite}/has_violations/multi_arg_int.c (100%) rename build_functions/{tests_validate_timed_test_suite => tests/validate_timed_test_suite}/has_violations/sample_module_int.c (100%) rename build_functions/{tests_validate_timed_test_suite => tests/validate_timed_test_suite}/no_violations/no_init_int.c (100%) rename build_functions/{tests_validate_timed_test_suite => tests/validate_timed_test_suite}/no_violations/timed_module_int.c (100%) delete mode 100644 build_functions/tests_validate_timed_test_suite/CMakeLists.txt delete mode 100644 build_functions/tests_validate_timed_test_suite/has_violations/has_include_int_expected.c delete mode 100644 build_functions/tests_validate_timed_test_suite/has_violations/multi_arg_int_expected.c delete mode 100644 build_functions/tests_validate_timed_test_suite/has_violations/sample_module_int_expected.c diff --git a/build_functions/CMakeLists.txt b/build_functions/CMakeLists.txt index ed5416a..5d54fce 100644 --- a/build_functions/CMakeLists.txt +++ b/build_functions/CMakeLists.txt @@ -354,7 +354,7 @@ function(validate_timed_test_suite test_folder) endif() endif() - set(script_path "${trsw_internal_dir}/validate_timed_test_suite.ps1") + set(script_path "${trsw_internal_dir}/scripts/validate_timed_test_suite.ps1") if(EXISTS "${script_path}") add_custom_target(${test_folder}_timed_suite_check ALL COMMAND powershell.exe -ExecutionPolicy Bypass @@ -433,5 +433,5 @@ function(build_test_artifacts_with_custom_main whatIsBuilding solution_folder ) endfunction() if(${run_unittests}) - add_subdirectory(tests_validate_timed_test_suite) + add_subdirectory(tests/validate_timed_test_suite) endif() diff --git a/build_functions/validate_timed_test_suite.ps1 b/build_functions/scripts/validate_timed_test_suite.ps1 similarity index 53% rename from build_functions/validate_timed_test_suite.ps1 rename to build_functions/scripts/validate_timed_test_suite.ps1 index 821a40e..fd71555 100644 --- a/build_functions/validate_timed_test_suite.ps1 +++ b/build_functions/scripts/validate_timed_test_suite.ps1 @@ -12,35 +12,21 @@ vanilla versions with a process watchdog that crashes the process and produces a dump on timeout, allowing dumps to be collected if the test hangs. - When the -Fix switch is provided, the script will automatically replace the vanilla - macros with their timed equivalents and add the required include if not present. - .PARAMETER TestFolder The path to the test folder to validate. -.PARAMETER Fix - If specified, automatically replace TEST_SUITE_INITIALIZE/CLEANUP with timed versions. - .EXAMPLE .\validate_timed_test_suite.ps1 -TestFolder "C:\repo\tests\my_module_int" Validates integration test files in the folder and reports files using non-timed macros. -.EXAMPLE - .\validate_timed_test_suite.ps1 -TestFolder "C:\repo\tests\my_module_int" -Fix - - Validates and automatically replaces non-timed macros with timed versions. - .NOTES - Returns exit code 0 if all files are valid (or were fixed), 1 if validation fails. + Returns exit code 0 if all files are valid, 1 if validation fails. #> param( [Parameter(Mandatory=$true)] - [string]$TestFolder, - - [Parameter(Mandatory=$false)] - [switch]$Fix + [string]$TestFolder ) # Set error action preference @@ -50,14 +36,8 @@ Write-Host "========================================" -ForegroundColor Cyan Write-Host "Timed Test Suite Validation" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan Write-Host "Test Folder: $TestFolder" -ForegroundColor White -Write-Host "Fix Mode: $($Fix.IsPresent)" -ForegroundColor White Write-Host "" -# Initialize counters -$totalFiles = 0 -$filesWithViolations = @() -$fixedFiles = @() - # Get all integration test files in the folder Write-Host "Searching for integration test files (*_int.c)..." -ForegroundColor White $allFiles = @(Get-ChildItem -Path $TestFolder -Recurse -Filter "*_int.c" -ErrorAction SilentlyContinue) @@ -70,6 +50,9 @@ Write-Host "" $initPattern = '(? TIMED_TEST_SUITE_INITIALIZE(name, TIMED_TEST_DEFAULT_TIMEOUT_MS - if ($currentLine -match $initPattern) { - $currentLine = $currentLine -replace '(? TIMED_TEST_SUITE_CLEANUP( - if ($currentLine -match $cleanupPattern) { - $currentLine = $currentLine -replace '(? Date: Wed, 11 Feb 2026 22:09:54 -0800 Subject: [PATCH 4/4] Add NumExpectedViolations flag, use CMake function in tests, add skip regex test Co-Authored-By: Claude Opus 4.6 --- build_functions/CMakeLists.txt | 11 ++++++ .../scripts/validate_timed_test_suite.ps1 | 25 ++++++++++--- .../validate_timed_test_suite/CMakeLists.txt | 37 +++++++------------ 3 files changed, 44 insertions(+), 29 deletions(-) diff --git a/build_functions/CMakeLists.txt b/build_functions/CMakeLists.txt index 5d54fce..34b170d 100644 --- a/build_functions/CMakeLists.txt +++ b/build_functions/CMakeLists.txt @@ -346,7 +346,17 @@ endfunction() # Validates that *_int.c files in test_folder use TIMED_TEST_SUITE_INITIALIZE/CLEANUP. # Skip specific folders: cmake -Dtimed_test_suite_skip_regex="module_a_int|module_b_int" +# Optional: NUM_EXPECTED_VIOLATIONS - expected number of files with violations (default 0) function(validate_timed_test_suite test_folder) + set(options) + set(oneValueArgs NUM_EXPECTED_VIOLATIONS) + set(multiValueArgs) + cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT DEFINED arg_NUM_EXPECTED_VIOLATIONS) + set(arg_NUM_EXPECTED_VIOLATIONS 0) + endif() + # Allow skipping via regex if(DEFINED timed_test_suite_skip_regex AND NOT "${timed_test_suite_skip_regex}" STREQUAL "") if("${test_folder}" MATCHES "${timed_test_suite_skip_regex}") @@ -360,6 +370,7 @@ function(validate_timed_test_suite test_folder) COMMAND powershell.exe -ExecutionPolicy Bypass -File "${script_path}" -TestFolder "${CMAKE_CURRENT_SOURCE_DIR}/${test_folder}" + -NumExpectedViolations ${arg_NUM_EXPECTED_VIOLATIONS} COMMENT "Validating timed test suite in ${test_folder}" VERBATIM ) diff --git a/build_functions/scripts/validate_timed_test_suite.ps1 b/build_functions/scripts/validate_timed_test_suite.ps1 index fd71555..19bc808 100644 --- a/build_functions/scripts/validate_timed_test_suite.ps1 +++ b/build_functions/scripts/validate_timed_test_suite.ps1 @@ -15,18 +15,25 @@ .PARAMETER TestFolder The path to the test folder to validate. +.PARAMETER NumExpectedViolations + The number of files expected to have violations. When the actual violation count matches + this value, the script exits with code 0. Default is 0 (no violations expected). + .EXAMPLE .\validate_timed_test_suite.ps1 -TestFolder "C:\repo\tests\my_module_int" Validates integration test files in the folder and reports files using non-timed macros. .NOTES - Returns exit code 0 if all files are valid, 1 if validation fails. + Returns exit code 0 if violation count matches NumExpectedViolations, 1 otherwise. #> param( [Parameter(Mandatory=$true)] - [string]$TestFolder + [string]$TestFolder, + + [Parameter(Mandatory=$false)] + [int]$NumExpectedViolations = 0 ) # Set error action preference @@ -36,6 +43,9 @@ Write-Host "========================================" -ForegroundColor Cyan Write-Host "Timed Test Suite Validation" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan Write-Host "Test Folder: $TestFolder" -ForegroundColor White +if ($NumExpectedViolations -gt 0) { + Write-Host "Expected Violations: $NumExpectedViolations" -ForegroundColor White +} Write-Host "" # Get all integration test files in the folder @@ -113,9 +123,12 @@ if ($filesWithViolations.Count -gt 0) { Write-Host "TIMED_TEST_SUITE_CLEANUP from c_pal/timed_test_suite.h to allow" -ForegroundColor Cyan Write-Host "dumps to be collected if the test hangs." -ForegroundColor Cyan Write-Host "" - Write-Host "[VALIDATION FAILED]" -ForegroundColor Red - exit 1 } -Write-Host "[VALIDATION PASSED]" -ForegroundColor Green -exit 0 +if ($filesWithViolations.Count -eq $NumExpectedViolations) { + Write-Host "[VALIDATION PASSED]" -ForegroundColor Green + exit 0 +} else { + Write-Host "[VALIDATION FAILED] Expected $NumExpectedViolations violation(s), found $($filesWithViolations.Count)" -ForegroundColor Red + exit 1 +} diff --git a/build_functions/tests/validate_timed_test_suite/CMakeLists.txt b/build_functions/tests/validate_timed_test_suite/CMakeLists.txt index 8d6136b..1b4f866 100644 --- a/build_functions/tests/validate_timed_test_suite/CMakeLists.txt +++ b/build_functions/tests/validate_timed_test_suite/CMakeLists.txt @@ -4,28 +4,22 @@ # # Timed Test Suite Validation Tests # -# Tests the validate_timed_test_suite.ps1 script to ensure it correctly detects -# integration test files using non-timed TEST_SUITE_INITIALIZE/CLEANUP macros. +# Tests the validate_timed_test_suite CMake function and underlying script. # -set(POWERSHELL_EXECUTABLE "powershell.exe") -set(VALIDATE_TIMED_TEST_SUITE_SCRIPT "${trsw_internal_dir}/scripts/validate_timed_test_suite.ps1") +# Test 1: Clean files pass validation (0 expected violations) +validate_timed_test_suite(no_violations) -# Test 1: Verify script detects non-timed macros in files that have them -add_custom_target(test_validate_timed_test_suite_detection - COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" - -TestFolder "${CMAKE_CURRENT_SOURCE_DIR}/has_violations" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Testing timed test suite detection on files with non-timed macros" -) +# Test 2: Detection of violations (3 files with violations expected) +validate_timed_test_suite(has_violations NUM_EXPECTED_VIOLATIONS 3) -# Test 2: Verify script passes on files already using timed macros -add_custom_target(test_validate_timed_test_suite_clean - COMMAND ${POWERSHELL_EXECUTABLE} -ExecutionPolicy Bypass -File "${VALIDATE_TIMED_TEST_SUITE_SCRIPT}" - -TestFolder "${CMAKE_CURRENT_SOURCE_DIR}/no_violations" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Testing timed test suite validation on clean files" -) +# Test 3: Skip regex causes check to be skipped +set(timed_test_suite_skip_regex "skipped_folder_int") +validate_timed_test_suite(skipped_folder_int) +if(TARGET skipped_folder_int_timed_suite_check) + message(FATAL_ERROR "skipped_folder_int should have been skipped by regex but target was created") +endif() +unset(timed_test_suite_skip_regex) # Master target for all timed test suite validation tests add_custom_target(test_validate_timed_test_suite @@ -33,9 +27,6 @@ add_custom_target(test_validate_timed_test_suite ) add_dependencies(test_validate_timed_test_suite - test_validate_timed_test_suite_clean + no_violations_timed_suite_check + has_violations_timed_suite_check ) - -# Note: We don't add test_validate_timed_test_suite_detection as a dependency because -# it should fail with exit code 1 (which would fail the build). -# Instead, it's available to run manually to verify detection works.