From e966f02c6f8c12c1418666acfa5bb586fb920ae7 Mon Sep 17 00:00:00 2001 From: Chad Condon Date: Tue, 31 Mar 2026 21:18:08 -0700 Subject: [PATCH 1/6] Add TEST_PROPERTY macro for JUnit per-test-case properties Adds TEST_PROPERTY(name, value) for C++ and TEST_PROPERTY_C(name, value) for C, allowing test bodies to attach key-value metadata that appears in JUnit XML output as elements inside blocks. Properties flow through the existing UtestShell -> TestResult -> TestOutput call chain, with JUnitTestOutput storing them on per-test-case result nodes and emitting them when writing XML. The block is only emitted when at least one property is present. Property names and values are XML-encoded. --- include/CppUTest/JUnitTestOutput.h | 1 + include/CppUTest/TestHarness_c.h | 4 + include/CppUTest/TestOutput.h | 2 + include/CppUTest/TestResult.h | 1 + include/CppUTest/Utest.h | 1 + include/CppUTest/UtestMacros.h | 3 + src/CppUTest/JUnitTestOutput.cpp | 49 +++++++++++- src/CppUTest/TestHarness_c.cpp | 5 ++ src/CppUTest/TestOutput.cpp | 10 +++ src/CppUTest/TestResult.cpp | 5 ++ src/CppUTest/Utest.cpp | 5 ++ tests/CppUTest/JUnitOutputTest.cpp | 117 ++++++++++++++++++++++++++++- 12 files changed, 201 insertions(+), 2 deletions(-) diff --git a/include/CppUTest/JUnitTestOutput.h b/include/CppUTest/JUnitTestOutput.h index 5e5746f56..79984570e 100644 --- a/include/CppUTest/JUnitTestOutput.h +++ b/include/CppUTest/JUnitTestOutput.h @@ -52,6 +52,7 @@ class JUnitTestOutput: public TestOutput virtual void print(long) CPPUTEST_OVERRIDE; virtual void print(size_t) CPPUTEST_OVERRIDE; virtual void printFailure(const TestFailure& failure) CPPUTEST_OVERRIDE; + virtual void printTestProperty(const char* name, const char* value) CPPUTEST_OVERRIDE; virtual void flush() CPPUTEST_OVERRIDE; diff --git a/include/CppUTest/TestHarness_c.h b/include/CppUTest/TestHarness_c.h index f3a64cf83..e449e61df 100644 --- a/include/CppUTest/TestHarness_c.h +++ b/include/CppUTest/TestHarness_c.h @@ -138,6 +138,9 @@ #define CHECK_C_TEXT(condition, text) \ CHECK_C_LOCATION(condition, #condition, text, __FILE__, __LINE__) +#define TEST_PROPERTY_C(name, value) \ + cpputest_add_test_property(name, value) + /****************************************************************************** * * TEST macros for in C. @@ -216,6 +219,7 @@ extern void CHECK_EQUAL_C_BITS_LOCATION(unsigned int expected, unsigned int actu extern void FAIL_TEXT_C_LOCATION(const char* text, const char* fileName, size_t lineNumber); extern void FAIL_C_LOCATION(const char* fileName, size_t lineNumber); extern void CHECK_C_LOCATION(int condition, const char* conditionString, const char* text, const char* fileName, size_t lineNumber); +extern void cpputest_add_test_property(const char* name, const char* value); extern void* cpputest_malloc(size_t size); extern char* cpputest_strdup(const char* str); diff --git a/include/CppUTest/TestOutput.h b/include/CppUTest/TestOutput.h index 47fbe02ea..e4572f6ce 100644 --- a/include/CppUTest/TestOutput.h +++ b/include/CppUTest/TestOutput.h @@ -71,6 +71,7 @@ class TestOutput virtual void setProgressIndicator(const char*); virtual void printVeryVerbose(const char*); + virtual void printTestProperty(const char* name, const char* value); virtual void flush()=0; @@ -199,6 +200,7 @@ class CompositeTestOutput : public TestOutput virtual void setProgressIndicator(const char*) CPPUTEST_OVERRIDE; virtual void printVeryVerbose(const char*) CPPUTEST_OVERRIDE; + virtual void printTestProperty(const char* name, const char* value) CPPUTEST_OVERRIDE; virtual void flush() CPPUTEST_OVERRIDE; diff --git a/include/CppUTest/TestResult.h b/include/CppUTest/TestResult.h index fc6e63fd6..68618c9d0 100644 --- a/include/CppUTest/TestResult.h +++ b/include/CppUTest/TestResult.h @@ -58,6 +58,7 @@ class TestResult virtual void countFilteredOut(); virtual void countIgnored(); virtual void addFailure(const TestFailure& failure); + virtual void addProperty(const char* name, const char* value); virtual void print(const char* text); virtual void printVeryVerbose(const char* text); diff --git a/include/CppUTest/Utest.h b/include/CppUTest/Utest.h index 02e865b76..1ba6321ba 100644 --- a/include/CppUTest/Utest.h +++ b/include/CppUTest/Utest.h @@ -152,6 +152,7 @@ class UtestShell virtual void print(const char *text, const char *fileName, size_t lineNumber); virtual void print(const SimpleString & text, const char *fileName, size_t lineNumber); virtual void printVeryVerbose(const char* text); + virtual void addTestProperty(const char* name, const char* value); void setFileName(const char *fileName); void setLineNumber(size_t lineNumber); diff --git a/include/CppUTest/UtestMacros.h b/include/CppUTest/UtestMacros.h index 743bf069e..3dbda3161 100644 --- a/include/CppUTest/UtestMacros.h +++ b/include/CppUTest/UtestMacros.h @@ -387,4 +387,7 @@ #define UT_CRASH() do { UtestShell::crash(); } while(0) #define RUN_ALL_TESTS(ac, av) CommandLineTestRunner::RunAllTests(ac, av) +#define TEST_PROPERTY(name, value) \ + do { UtestShell::getCurrent()->addTestProperty(name, value); } while(0) + #endif /*D_UTestMacros_h*/ diff --git a/src/CppUTest/JUnitTestOutput.cpp b/src/CppUTest/JUnitTestOutput.cpp index f509d9b72..8f1aec2b0 100644 --- a/src/CppUTest/JUnitTestOutput.cpp +++ b/src/CppUTest/JUnitTestOutput.cpp @@ -31,10 +31,19 @@ #include "CppUTest/TestFailure.h" #include "CppUTest/PlatformSpecificFunctions.h" +struct TestPropertyResultNode +{ + TestPropertyResultNode() : next_(NULLPTR) {} + SimpleString name_; + SimpleString value_; + TestPropertyResultNode* next_; +}; + struct JUnitTestCaseResultNode { JUnitTestCaseResultNode() : - execTime_(0), failure_(NULLPTR), ignored_(false), lineNumber_ (0), checkCount_ (0), next_(NULLPTR) + execTime_(0), failure_(NULLPTR), ignored_(false), lineNumber_ (0), checkCount_ (0), + properties_(NULLPTR), propertiesTail_(NULLPTR), next_(NULLPTR) { } @@ -45,6 +54,8 @@ struct JUnitTestCaseResultNode SimpleString file_; size_t lineNumber_; size_t checkCount_; + TestPropertyResultNode* properties_; + TestPropertyResultNode* propertiesTail_; JUnitTestCaseResultNode* next_; }; @@ -93,6 +104,12 @@ void JUnitTestOutput::resetTestGroupResult() while (cur) { JUnitTestCaseResultNode* tmp = cur->next_; delete cur->failure_; + TestPropertyResultNode* prop = cur->properties_; + while (prop) { + TestPropertyResultNode* tmpProp = prop->next_; + delete prop; + prop = tmpProp; + } delete cur; cur = tmp; } @@ -233,6 +250,20 @@ void JUnitTestOutput::writeTestCases() impl_->results_.totalCheckCount_ = cur->checkCount_; + if (cur->properties_) { + writeToFile("\n"); + TestPropertyResultNode* prop = cur->properties_; + while (prop) { + SimpleString propBuf = StringFromFormat( + "\n", + encodeXmlText(prop->name_).asCharString(), + encodeXmlText(prop->value_).asCharString()); + writeToFile(propBuf.asCharString()); + prop = prop->next_; + } + writeToFile("\n"); + } + if (cur->failure_) { writeFailure(cur); } @@ -309,6 +340,22 @@ void JUnitTestOutput::printFailure(const TestFailure& failure) } } +void JUnitTestOutput::printTestProperty(const char* name, const char* value) +{ + TestPropertyResultNode* node = new TestPropertyResultNode; + node->name_ = name; + node->value_ = value; + + if (impl_->results_.tail_->propertiesTail_ == NULLPTR) { + impl_->results_.tail_->properties_ = node; + impl_->results_.tail_->propertiesTail_ = node; + } + else { + impl_->results_.tail_->propertiesTail_->next_ = node; + impl_->results_.tail_->propertiesTail_ = node; + } +} + void JUnitTestOutput::openFileForWrite(const SimpleString& fileName) { impl_->file_ = PlatformSpecificFOpen(fileName.asCharString(), "w"); diff --git a/src/CppUTest/TestHarness_c.cpp b/src/CppUTest/TestHarness_c.cpp index 149c8fbb6..77f78c54c 100644 --- a/src/CppUTest/TestHarness_c.cpp +++ b/src/CppUTest/TestHarness_c.cpp @@ -124,6 +124,11 @@ void CHECK_C_LOCATION(int condition, const char* conditionString, const char* te UtestShell::getCurrent()->assertTrue(condition != 0, "CHECK_C", conditionString, text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions()); } +void cpputest_add_test_property(const char* name, const char* value) +{ + UtestShell::getCurrent()->addTestProperty(name, value); +} + enum { NO_COUNTDOWN = -1, OUT_OF_MEMORRY = 0 }; static int malloc_out_of_memory_counter = NO_COUNTDOWN; static int malloc_count = 0; diff --git a/src/CppUTest/TestOutput.cpp b/src/CppUTest/TestOutput.cpp index cb4ced54e..7c3e3946b 100644 --- a/src/CppUTest/TestOutput.cpp +++ b/src/CppUTest/TestOutput.cpp @@ -271,6 +271,10 @@ void TestOutput::printVeryVerbose(const char* str) printBuffer(str); } +void TestOutput::printTestProperty(const char*, const char*) +{ +} + void ConsoleTestOutput::printBuffer(const char* s) { @@ -406,6 +410,12 @@ void CompositeTestOutput::printVeryVerbose(const char* str) if (outputTwo_) outputTwo_->printVeryVerbose(str); } +void CompositeTestOutput::printTestProperty(const char* name, const char* value) +{ + if (outputOne_) outputOne_->printTestProperty(name, value); + if (outputTwo_) outputTwo_->printTestProperty(name, value); +} + void CompositeTestOutput::flush() { if (outputOne_) outputOne_->flush(); diff --git a/src/CppUTest/TestResult.cpp b/src/CppUTest/TestResult.cpp index 37ff57f84..b98e2985c 100644 --- a/src/CppUTest/TestResult.cpp +++ b/src/CppUTest/TestResult.cpp @@ -82,6 +82,11 @@ void TestResult::addFailure(const TestFailure& failure) failureCount_++; } +void TestResult::addProperty(const char* name, const char* value) +{ + output_.printTestProperty(name, value); +} + void TestResult::countTest() { testCount_++; diff --git a/src/CppUTest/Utest.cpp b/src/CppUTest/Utest.cpp index d74a87c79..ed5c7d662 100644 --- a/src/CppUTest/Utest.cpp +++ b/src/CppUTest/Utest.cpp @@ -576,6 +576,11 @@ void UtestShell::printVeryVerbose(const char* text) getTestResult()->printVeryVerbose(text); } +void UtestShell::addTestProperty(const char* name, const char* value) +{ + getTestResult()->addProperty(name, value); +} + TestResult* UtestShell::testResult_ = NULLPTR; UtestShell* UtestShell::currentTest_ = NULLPTR; diff --git a/tests/CppUTest/JUnitOutputTest.cpp b/tests/CppUTest/JUnitOutputTest.cpp index 32b5654d4..a96dded2f 100644 --- a/tests/CppUTest/JUnitOutputTest.cpp +++ b/tests/CppUTest/JUnitOutputTest.cpp @@ -149,6 +149,14 @@ extern "C" { } } +struct PendingProperty +{ + const char* name_; + const char* value_; + PendingProperty* next_; + PendingProperty(const char* n, const char* v, PendingProperty* nx) : name_(n), value_(v), next_(nx) {} +}; + class JUnitTestOutputTestRunner { TestResult result_; @@ -159,11 +167,13 @@ class JUnitTestOutputTestRunner unsigned int timeTheTestTakes_; unsigned int numberOfChecksInTest_; TestFailure* testFailure_; + PendingProperty* pendingProperties_; + PendingProperty* pendingPropertiesTail_; public: explicit JUnitTestOutputTestRunner(const TestResult& result) : - result_(result), currentGroupName_(NULLPTR), currentTest_(NULLPTR), firstTestInGroup_(true), timeTheTestTakes_(0), numberOfChecksInTest_(0), testFailure_(NULLPTR) + result_(result), currentGroupName_(NULLPTR), currentTest_(NULLPTR), firstTestInGroup_(true), timeTheTestTakes_(0), numberOfChecksInTest_(0), testFailure_(NULLPTR), pendingProperties_(NULLPTR), pendingPropertiesTail_(NULLPTR) { millisTime = 0; theTime = "1978-10-03T00:00:00"; @@ -264,6 +274,16 @@ class JUnitTestOutputTestRunner } numberOfChecksInTest_ = 0; + PendingProperty* prop = pendingProperties_; + pendingProperties_ = NULLPTR; + pendingPropertiesTail_ = NULLPTR; + while (prop) { + PendingProperty* next = prop->next_; + result_.addProperty(prop->name_, prop->value_); + delete prop; + prop = next; + } + if (testFailure_) { result_.addFailure(*testFailure_); delete testFailure_; @@ -308,6 +328,20 @@ class JUnitTestOutputTestRunner result_.print(output); return *this; } + + JUnitTestOutputTestRunner& withProperty(const char* name, const char* value) + { + PendingProperty* node = new PendingProperty(name, value, NULLPTR); + if (pendingPropertiesTail_ == NULLPTR) { + pendingProperties_ = node; + pendingPropertiesTail_ = node; + } + else { + pendingPropertiesTail_->next_ = node; + pendingPropertiesTail_ = node; + } + return *this; + } }; extern "C" { @@ -767,3 +801,84 @@ TEST(JUnitOutputTest, UTPRINTOutputInJUnitOutputWithSpecials) outputFile = fileSystem.file("cpputest_groupname.xml"); STRCMP_EQUAL("The <rain> in "Spain" Goes \\mainly\\ down the Dr&in \n", outputFile->lineFromTheBack(3)); } + +TEST(JUnitOutputTest, TestCaseWithOneProperty) +{ + testCaseRunner->start() + .withGroup("groupname").withTest("testname").withProperty("key", "val") + .end(); + + outputFile = fileSystem.file("cpputest_groupname.xml"); + STRCMP_EQUAL("\n", outputFile->line(5)); + STRCMP_EQUAL("\n", outputFile->line(6)); + STRCMP_EQUAL("\n", outputFile->line(7)); + STRCMP_EQUAL("\n", outputFile->line(8)); + STRCMP_EQUAL("\n", outputFile->line(9)); +} + +TEST(JUnitOutputTest, TestCaseWithMultiplePropertiesInInsertionOrder) +{ + testCaseRunner->start() + .withGroup("groupname").withTest("testname") + .withProperty("first", "one").withProperty("second", "two") + .end(); + + outputFile = fileSystem.file("cpputest_groupname.xml"); + STRCMP_EQUAL("\n", outputFile->line(7)); + STRCMP_EQUAL("\n", outputFile->line(8)); +} + +TEST(JUnitOutputTest, TestCaseWithNoPropertiesHasNoPropertiesBlock) +{ + testCaseRunner->start() + .withGroup("groupname").withTest("testname") + .end(); + + outputFile = fileSystem.file("cpputest_groupname.xml"); + STRCMP_EQUAL("\n", outputFile->line(5)); + STRCMP_EQUAL("\n", outputFile->line(6)); +} + +TEST(JUnitOutputTest, TestCasePropertyValuesAreXmlEncoded) +{ + testCaseRunner->start() + .withGroup("groupname").withTest("testname") + .withProperty("a&b", "") + .end(); + + outputFile = fileSystem.file("cpputest_groupname.xml"); + STRCMP_EQUAL("\n", outputFile->line(7)); +} + +TEST(JUnitOutputTest, PropertiesOnlyAppearOnCorrectTestInGroup) +{ + testCaseRunner->start() + .withGroup("groupname") + .withTest("firstTest") + .withTest("secondTest").withProperty("k", "v") + .end(); + + outputFile = fileSystem.file("cpputest_groupname.xml"); + // firstTest: lines 5-6 (no properties block) + STRCMP_EQUAL("\n", outputFile->line(5)); + STRCMP_EQUAL("\n", outputFile->line(6)); + // secondTest: lines 7-11 (with properties) + STRCMP_EQUAL("\n", outputFile->line(7)); + STRCMP_EQUAL("\n", outputFile->line(8)); + STRCMP_EQUAL("\n", outputFile->line(9)); + STRCMP_EQUAL("\n", outputFile->line(10)); + STRCMP_EQUAL("\n", outputFile->line(11)); +} + +TEST(JUnitOutputTest, PropertiesDontLeakAcrossGroups) +{ + testCaseRunner->start() + .withGroup("groupOne").withTest("testA").withProperty("x", "1") + .endGroupAndClearTest() + .withGroup("groupTwo").withTest("testB") + .end(); + + outputFile = fileSystem.file("cpputest_groupTwo.xml"); + STRCMP_EQUAL("\n", outputFile->line(5)); + STRCMP_EQUAL("\n", outputFile->line(6)); +} From d35e57b79463145229796b43d4f5e568d2b94f05 Mon Sep 17 00:00:00 2001 From: Chad Condon Date: Tue, 31 Mar 2026 21:29:03 -0700 Subject: [PATCH 2/6] Test TEST_PROPERTY and TEST_PROPERTY_C macros end-to-end Adds a PropertySpyOutput that captures printTestProperty calls, and two tests that drive the macros through ExecFunctionTestShell with a spy result to verify the full routing chain from macro invocation to output. Also adds the cpputest_test_property_c_caller helper in the C test file to exercise TEST_PROPERTY_C from actual C code. --- tests/CppUTest/TestHarness_cTest.cpp | 57 +++++++++++++++++++++++++ tests/CppUTest/TestHarness_cTestCFile.c | 5 +++ 2 files changed, 62 insertions(+) diff --git a/tests/CppUTest/TestHarness_cTest.cpp b/tests/CppUTest/TestHarness_cTest.cpp index fadc66f1d..61f1aba23 100644 --- a/tests/CppUTest/TestHarness_cTest.cpp +++ b/tests/CppUTest/TestHarness_cTest.cpp @@ -28,6 +28,7 @@ #include "CppUTest/TestHarness_c.h" #include "CppUTest/TestHarness.h" +#include "CppUTest/TestPlugin.h" #include "CppUTest/TestRegistry.h" #include "CppUTest/TestOutput.h" #include "CppUTest/TestTestingFixture.h" @@ -882,3 +883,59 @@ TEST(TestHarness_c, callocShouldReturnNULLWhenOutOfMemory) cpputest_malloc_set_not_out_of_memory(); } #endif + +class PropertySpyOutput : public StringBufferTestOutput +{ +public: + SimpleString lastPropertyName_; + SimpleString lastPropertyValue_; + int callCount_; + + PropertySpyOutput() : lastPropertyName_(""), lastPropertyValue_(""), callCount_(0) {} + + virtual void printTestProperty(const char* name, const char* value) CPPUTEST_OVERRIDE + { + lastPropertyName_ = name; + lastPropertyValue_ = value; + callCount_++; + } +}; + +static void callTestPropertyMacro_() +{ + TEST_PROPERTY("propname", "propval"); +} + +extern "C" void cpputest_test_property_c_caller(void); + +TEST(TestHarness_c, testPropertyMacroRoutesToOutput) +{ + PropertySpyOutput spy; + TestResult spyResult(spy); + ExecFunctionTestShell shell; + shell.testFunction_ = new ExecFunctionWithoutParameters(callTestPropertyMacro_); + NullTestPlugin plugin; + shell.runOneTestInCurrentProcess(&plugin, spyResult); + delete shell.testFunction_; + shell.testFunction_ = NULLPTR; + + LONGS_EQUAL(1, spy.callCount_); + STRCMP_EQUAL("propname", spy.lastPropertyName_.asCharString()); + STRCMP_EQUAL("propval", spy.lastPropertyValue_.asCharString()); +} + +TEST(TestHarness_c, testPropertyCMacroRoutesToOutput) +{ + PropertySpyOutput spy; + TestResult spyResult(spy); + ExecFunctionTestShell shell; + shell.testFunction_ = new ExecFunctionWithoutParameters(cpputest_test_property_c_caller); + NullTestPlugin plugin; + shell.runOneTestInCurrentProcess(&plugin, spyResult); + delete shell.testFunction_; + shell.testFunction_ = NULLPTR; + + LONGS_EQUAL(1, spy.callCount_); + STRCMP_EQUAL("ckey", spy.lastPropertyName_.asCharString()); + STRCMP_EQUAL("cval", spy.lastPropertyValue_.asCharString()); +} diff --git a/tests/CppUTest/TestHarness_cTestCFile.c b/tests/CppUTest/TestHarness_cTestCFile.c index bfc7d767f..67ee6669f 100644 --- a/tests/CppUTest/TestHarness_cTestCFile.c +++ b/tests/CppUTest/TestHarness_cTestCFile.c @@ -34,3 +34,8 @@ IGNORE_TEST_C(TestGroupInC, ignoreMacroForCFile) { test_was_called_in_test_group_in_C++; } + +void cpputest_test_property_c_caller(void) +{ + TEST_PROPERTY_C("ckey", "cval"); +} From 16035ba042e4b05f920106524c1754c9fbab4c01 Mon Sep 17 00:00:00 2001 From: Chad Condon Date: Tue, 31 Mar 2026 21:30:03 -0700 Subject: [PATCH 3/6] Document TEST_PROPERTY in README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 40c25df0e..770aaac9e 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ $ vcpkg install cpputest (More information: https://github.com/microsoft/vcpkg) * `TEST_SETUP()` - Declare a void setup method in a `TEST_GROUP` - this is the same as declaring void `setup()` * `TEST_TEARDOWN()` - Declare a void setup method in a `TEST_GROUP` * `IMPORT_TEST_GROUP(group)` - Export the name of a test group so it can be linked in from a library. Needs to be done in `main`. +* `TEST_PROPERTY(name, value)` - Attach a key-value string property to the current test. Properties appear as `` elements inside the `` block in JUnit XML output. For use in C files, use `TEST_PROPERTY_C(name, value)` instead. ## Set up and tear down support From 8527137f6592fa678ecf1b66cb8ee6b53d730a29 Mon Sep 17 00:00:00 2001 From: Chad Condon Date: Tue, 31 Mar 2026 21:47:16 -0700 Subject: [PATCH 4/6] Add missing prototype for cpputest_test_property_c_caller Fixes -Wmissing-prototypes error with clang-cl -Werror. --- tests/CppUTest/TestHarness_cTestCFile.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/CppUTest/TestHarness_cTestCFile.c b/tests/CppUTest/TestHarness_cTestCFile.c index 67ee6669f..7c59e9a1c 100644 --- a/tests/CppUTest/TestHarness_cTestCFile.c +++ b/tests/CppUTest/TestHarness_cTestCFile.c @@ -9,6 +9,13 @@ void functionWithUnusedParameter(void* PUNUSED(unlessParamater)) } +extern void cpputest_test_property_c_caller(void); + +void cpputest_test_property_c_caller(void) +{ + TEST_PROPERTY_C("ckey", "cval"); +} + /* Declared in the cpp file */ extern int setup_teardown_was_called_in_test_group_in_C; extern int test_was_called_in_test_group_in_C; @@ -34,8 +41,3 @@ IGNORE_TEST_C(TestGroupInC, ignoreMacroForCFile) { test_was_called_in_test_group_in_C++; } - -void cpputest_test_property_c_caller(void) -{ - TEST_PROPERTY_C("ckey", "cval"); -} From 85bb9a3f8a4b258ee8ddef9607ced1eff793ced3 Mon Sep 17 00:00:00 2001 From: Chad Condon Date: Tue, 31 Mar 2026 23:03:43 -0700 Subject: [PATCH 5/6] Test TestOutput::printTestProperty and CompositeTestOutput delegation --- tests/CppUTest/TestOutputTest.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/CppUTest/TestOutputTest.cpp b/tests/CppUTest/TestOutputTest.cpp index bde55df4f..f4e7f26e0 100644 --- a/tests/CppUTest/TestOutputTest.cpp +++ b/tests/CppUTest/TestOutputTest.cpp @@ -282,6 +282,12 @@ TEST(TestOutput, printTestsEndedWithNoTestsRunOrIgnored) mock->getOutput().asCharString()); } +TEST(TestOutput, printTestPropertyIsNoOp) +{ + printer->printTestProperty("key", "value"); + STRCMP_EQUAL("", mock->getOutput().asCharString()); +} + class CompositeTestOutputTestStringBufferTestOutput : public StringBufferTestOutput { public: @@ -478,3 +484,10 @@ TEST(CompositeTestOutput, printVeryVerbose) STRCMP_EQUAL("very-verbose", output1->getOutput().asCharString()); STRCMP_EQUAL("very-verbose", output2->getOutput().asCharString()); } + +TEST(CompositeTestOutput, printTestProperty) +{ + compositeOutput.printTestProperty("key", "value"); + STRCMP_EQUAL("", output1->getOutput().asCharString()); + STRCMP_EQUAL("", output2->getOutput().asCharString()); +} From 976c4b87ee3292baa140aa10f83dc0e335e05d8e Mon Sep 17 00:00:00 2001 From: Chad Condon Date: Sat, 4 Apr 2026 15:32:46 -0700 Subject: [PATCH 6/6] Eliminate unnecessary macro indirection We don't need a macro that just forwards to a function. --- include/CppUTest/TestHarness_c.h | 5 +---- src/CppUTest/TestHarness_c.cpp | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/include/CppUTest/TestHarness_c.h b/include/CppUTest/TestHarness_c.h index e449e61df..8ee962f0c 100644 --- a/include/CppUTest/TestHarness_c.h +++ b/include/CppUTest/TestHarness_c.h @@ -138,9 +138,6 @@ #define CHECK_C_TEXT(condition, text) \ CHECK_C_LOCATION(condition, #condition, text, __FILE__, __LINE__) -#define TEST_PROPERTY_C(name, value) \ - cpputest_add_test_property(name, value) - /****************************************************************************** * * TEST macros for in C. @@ -219,7 +216,7 @@ extern void CHECK_EQUAL_C_BITS_LOCATION(unsigned int expected, unsigned int actu extern void FAIL_TEXT_C_LOCATION(const char* text, const char* fileName, size_t lineNumber); extern void FAIL_C_LOCATION(const char* fileName, size_t lineNumber); extern void CHECK_C_LOCATION(int condition, const char* conditionString, const char* text, const char* fileName, size_t lineNumber); -extern void cpputest_add_test_property(const char* name, const char* value); +extern void TEST_PROPERTY_C(const char* name, const char* value); extern void* cpputest_malloc(size_t size); extern char* cpputest_strdup(const char* str); diff --git a/src/CppUTest/TestHarness_c.cpp b/src/CppUTest/TestHarness_c.cpp index 77f78c54c..7c972c89c 100644 --- a/src/CppUTest/TestHarness_c.cpp +++ b/src/CppUTest/TestHarness_c.cpp @@ -124,7 +124,7 @@ void CHECK_C_LOCATION(int condition, const char* conditionString, const char* te UtestShell::getCurrent()->assertTrue(condition != 0, "CHECK_C", conditionString, text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions()); } -void cpputest_add_test_property(const char* name, const char* value) +void TEST_PROPERTY_C(const char* name, const char* value) { UtestShell::getCurrent()->addTestProperty(name, value); }