Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions inc/testrunnerswitcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ typedef void* TEST_MUTEX_HANDLE;
#define RUN_TEST_SUITE(...) CTEST_RUN_TEST_SUITE(__VA_ARGS__)
#define RUN_TEST_SUITE_WITH_LEAK_CHECK_RETRIES(...) CTEST_RUN_TEST_SUITE_WITH_LEAK_CHECK_RETRIES(__VA_ARGS__)

#define PARAMETERIZED_TEST_FUNCTION CTEST_PARAMETERIZED_TEST_FUNCTION

#define TEST_MUTEX_CREATE() (TEST_MUTEX_HANDLE)1
// the strlen check is simply to shut the compiler up and not create a hell of #pragma warning suppress
#define TEST_MUTEX_ACQUIRE(mutex) (strlen("a") == 0)
Expand Down Expand Up @@ -183,6 +185,23 @@ extern "C" void CPPUNITTEST_SYMBOL(void) {}
#define RUN_TEST_SUITE(...)
#define RUN_TEST_SUITE_WITH_LEAK_CHECK_RETRIES(...)

/* Parameterized tests for pure CPP_UNITTEST: wrappers using TEST_METHOD, reusing CTEST_PARAMETERIZED_TEST_ helpers from ctest.h */
#define PARAMETERIZED_TEST_CALL_TEST_METHOD(funcName) TEST_METHOD(funcName)

#define PARAMETERIZED_TEST_WRAPPER_IMPL(base_name, values, suffix) \
PARAMETERIZED_TEST_CALL_TEST_METHOD(MU_C3(base_name, _, suffix)) \
{ \
MU_C2(base_name, _impl)(CTEST_PARAMETERIZED_TEST_STRIP_PARENS values); \
}

#define PARAMETERIZED_TEST_WRAPPER_CALL(base_name, ...) PARAMETERIZED_TEST_WRAPPER_IMPL(base_name, __VA_ARGS__)
#define PARAMETERIZED_TEST_WRAPPER(base_name, case_item) PARAMETERIZED_TEST_WRAPPER_CALL(base_name, MU_C2B(CTEST_PARAMETERIZED_TEST_EXPAND_CASE_, case_item))

#define PARAMETERIZED_TEST_FUNCTION(base_name, args, ...) \
static void MU_C2(base_name, _impl)(CTEST_PARAMETERIZED_TEST_ARGS_DECL(args)); \
MU_FOR_EACH_1_KEEP_1(PARAMETERIZED_TEST_WRAPPER, base_name, __VA_ARGS__) \
static void MU_C2(base_name, _impl)(CTEST_PARAMETERIZED_TEST_ARGS_DECL(args))

#define TEST_MUTEX_CREATE() testmutex_create()
#define TEST_MUTEX_ACQUIRE(mutex) testmutex_acquire(mutex)
#define TEST_MUTEX_RELEASE(mutex) testmutex_release(mutex)
Expand Down
1 change: 1 addition & 0 deletions test_projects/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ build_test_folder(test_project_e2e)
build_test_folder(test_project_perf)
build_test_folder(test_project_with_custom_main_ut)
build_test_folder(ctest_2_cppunittest_ut)
build_test_folder(parameterized_tests_ut)
16 changes: 16 additions & 0 deletions test_projects/parameterized_tests_ut/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#Copyright (c) Microsoft. All rights reserved.
#Licensed under the MIT license. See LICENSE file in the project root for full license information.

set(theseTestsName parameterized_tests_ut)

set(${theseTestsName}_test_files
${theseTestsName}.c
)

set(${theseTestsName}_c_files
)

set(${theseTestsName}_h_files
)

build_test_artifacts(${theseTestsName} "tests/c_testrunnerswitcher")
127 changes: 127 additions & 0 deletions test_projects/parameterized_tests_ut/parameterized_tests_ut.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#ifdef CPPUNITTEST_SYMBOL
#ifdef __cplusplus
extern "C" {
#endif
void CPPUNITTEST_SYMBOL(void) {}

#ifdef __cplusplus
}
#endif
#endif /*CPPUNITTEST_SYMBOL*/

#include "testrunnerswitcher.h"

static int add_numbers(int a, int b)
{
return a + b;
}

static int multiply_numbers(int a, int b)
{
return a * b;
}

/* Global state to verify parameterized test cases are actually executed with correct parameters */
static int g_call_count;
static int g_accumulated_sum;

BEGIN_TEST_SUITE(parameterized_tests_ut)

TEST_SUITE_INITIALIZE(suite_init)
{
}

TEST_SUITE_CLEANUP(suite_cleanup)
{
/* assert - verify that the parameterized test cases for test_verify_calls were all executed */
/* 4 cases: (1,10), (2,20), (3,30), (4,40) => call_count=4, accumulated_sum = 11+22+33+44 = 110 */
ASSERT_ARE_EQUAL(int, 4, g_call_count, "Expected 4 parameterized test cases to execute, but got %d", g_call_count);
ASSERT_ARE_EQUAL(int, 110, g_accumulated_sum, "Expected accumulated sum of 110, but got %d", g_accumulated_sum);
}

TEST_FUNCTION_INITIALIZE(test_init)
{
}

TEST_FUNCTION_CLEANUP(test_cleanup)
{
}

/*
* Verification test: records global state to prove each CASE is executed with correct parameters.
* TEST_SUITE_CLEANUP validates that all 4 cases ran and produced the expected accumulated sum.
*/
PARAMETERIZED_TEST_FUNCTION(test_verify_calls, // no-srs
ARGS(int, a, int, b),
CASE((1, 10), case_1_10),
CASE((2, 20), case_2_20),
CASE((3, 30), case_3_30),
CASE((4, 40), case_4_40))
Comment thread
mattdurak marked this conversation as resolved.
{
// arrange
// (parameters a and b are set by the CASE macro)

// act
g_call_count++;
g_accumulated_sum += a + b;

// assert
ASSERT_IS_TRUE(a >= 1, "Expected a >= 1, got %d", a);
ASSERT_IS_TRUE(b >= 10, "Expected b >= 10, got %d", b);
}

PARAMETERIZED_TEST_FUNCTION(test_addition, // no-srs
ARGS(int, a, int, b, int, expected),
CASE((0, 0, 0), with_zeros),
CASE((1, 2, 3), with_small_positive_numbers),
CASE((-1, 1, 0), with_negative_and_positive),
CASE((100, 200, 300), with_larger_numbers))
{
// arrange
// (parameters a, b, expected are set by the CASE macro)

// act
int result = add_numbers(a, b);

// assert
ASSERT_ARE_EQUAL(int, expected, result, "Expected %d + %d = %d, but got %d", a, b, expected, result);
}

PARAMETERIZED_TEST_FUNCTION(test_multiplication, // no-srs
ARGS(int, x, int, y, int, expected_product),
CASE((0, 5, 0), with_zero),
CASE((1, 1, 1), with_ones),
CASE((2, 3, 6), with_small_numbers),
CASE((-2, 3, -6), with_negative_factor))
{
// arrange
// (parameters x, y, expected_product are set by the CASE macro)

// act
int result = multiply_numbers(x, y);

// assert
ASSERT_ARE_EQUAL(int, expected_product, result);
}

PARAMETERIZED_TEST_FUNCTION(test_is_positive, // no-srs
ARGS(int, value, int, expected_is_positive),
CASE((1, 1), for_positive_one),
CASE((100, 1), for_hundred),
CASE((0, 0), for_zero),
CASE((-1, 0), for_negative_one))
{
// arrange
// (parameters value, expected_is_positive are set by the CASE macro)

// act
int result = (value > 0) ? 1 : 0;

// assert
ASSERT_ARE_EQUAL(int, expected_is_positive, result);
}

END_TEST_SUITE(parameterized_tests_ut)