From adb20e696aae9dc9e4bb877b6ab2d7fecf0b24a8 Mon Sep 17 00:00:00 2001 From: Enzo Evers Date: Wed, 4 Dec 2024 20:57:36 +0100 Subject: [PATCH 1/2] feat: Create RaiiStringAppend(...) and RAII_STRING macro - It turns out that on MacOs, the gcc command is actually an alias for clang... --- Benchmark/BenchmarkDeflateInflateTextFile.c | 34 +- CoDeLib/RaiiString/src/RaiiString.c | 70 +++- CoDeLib/Test/Utility/FileUtils.c | 30 +- CoDeLib/Test/src/TestDeflateInflateZlib.c | 25 +- CoDeLib/Test/src/TestRaiiString.c | 304 +++++++++++++----- CoDeLib/Test/src/main.c | 3 +- .../include/CoDeLib/RaiiString/RaiiString.h | 14 +- .../include/CoDeLib/Test/Utility/FileUtils.h | 5 +- 8 files changed, 344 insertions(+), 141 deletions(-) diff --git a/Benchmark/BenchmarkDeflateInflateTextFile.c b/Benchmark/BenchmarkDeflateInflateTextFile.c index 4b17cadd..a2553df4 100644 --- a/Benchmark/BenchmarkDeflateInflateTextFile.c +++ b/Benchmark/BenchmarkDeflateInflateTextFile.c @@ -14,10 +14,19 @@ B63_BENCHMARK(Deflate_zlib_SmallTextFile, n) { FILE *pOutCompressedFile = NULL; B63_SUSPEND { - OpenFile(&pInFile, g_pFullPathToBenchmarkTestFiles, - "SmallBasicTextFile.txt", "r"); - OpenFile(&pOutCompressedFile, g_pFullPathToBenchmarkTestFiles, - "SmallBasicTextFile.compressed.txt", "w"); + RAII_STRING pathToSmallBasicTextFile = + RaiiStringCreateFromCString(g_pFullPathToBenchmarkTestFiles); + RaiiStringAppend_cString(&pathToSmallBasicTextFile, + "SmallBasicTextFile.txt"); + + RAII_STRING pathToSmallBasicTextFileCompressedFile = + RaiiStringCreateFromCString(g_pFullPathToBenchmarkTestFiles); + RaiiStringAppend_cString(&pathToSmallBasicTextFileCompressedFile, + "SmallBasicTextFile.compressed.txt"); + + OpenFile(&pInFile, &pathToSmallBasicTextFile, "r"); + OpenFile(&pOutCompressedFile, &pathToSmallBasicTextFileCompressedFile, + "w"); } const DEFLATE_RETURN_CODES statusDeflate = @@ -40,10 +49,19 @@ B63_BENCHMARK(Inflate_zlib_SmallTextFile, n) { FILE *pOutDecompressedFile = NULL; B63_SUSPEND { - OpenFile(&pCompressedFile, g_pFullPathToBenchmarkTestFiles, - "SmallBasicTextFileCompressed.txt", "r"); - OpenFile(&pOutDecompressedFile, g_pFullPathToBenchmarkTestFiles, - "SmallBasicTextFile.decompressed.txt", "w+"); + RAII_STRING pathToSmallBasicTextFileCompressed = + RaiiStringCreateFromCString(g_pFullPathToBenchmarkTestFiles); + RaiiStringAppend_cString(&pathToSmallBasicTextFileCompressed, + "SmallBasicTextFileCompressed.txt"); + + RAII_STRING pathToSmallBasicTextFileDecompressedFile = + RaiiStringCreateFromCString(g_pFullPathToBenchmarkTestFiles); + RaiiStringAppend_cString(&pathToSmallBasicTextFileDecompressedFile, + "SmallBasicTextFile.decompressed.txt"); + + OpenFile(&pCompressedFile, &pathToSmallBasicTextFileCompressed, "r"); + OpenFile(&pOutDecompressedFile, + &pathToSmallBasicTextFileDecompressedFile, "w"); } const INFLATE_RETURN_CODES statusInflate = diff --git a/CoDeLib/RaiiString/src/RaiiString.c b/CoDeLib/RaiiString/src/RaiiString.c index 89636471..aabc9a0a 100644 --- a/CoDeLib/RaiiString/src/RaiiString.c +++ b/CoDeLib/RaiiString/src/RaiiString.c @@ -3,36 +3,32 @@ #include #include -RaiiString RaiiStringCreate(size_t lengthWithTermination) { +RaiiString RaiiStringCreateFromCString(const char *pCString) { + const size_t lengthWithoutTermination = + strnlen(pCString, MAX_CSTRING_INCLUDING_TERMINATION_LENGTH); + RaiiString newRaiistring = {NULL, 0}; - if (lengthWithTermination == 0 || - lengthWithTermination >= MAX_CSTRING_INCLUDING_TERMINATION_LENGTH) { + if (lengthWithoutTermination == 0 || + lengthWithoutTermination == MAX_CSTRING_INCLUDING_TERMINATION_LENGTH) { return newRaiistring; } + const size_t lengthWithTermination = lengthWithoutTermination + 1; + newRaiistring.lengthWithTermination = lengthWithTermination; newRaiistring.pString = (char *)calloc(lengthWithTermination, sizeof(char)); + if (newRaiistring.pString == NULL) { newRaiistring.lengthWithTermination = 0; printf("Failed to allocate memory for RaiiString\n"); exit(1); } - return newRaiistring; -} - -RaiiString RaiiStringCreateFromCString(const char *pCString) { - const size_t length = - strnlen(pCString, MAX_CSTRING_INCLUDING_TERMINATION_LENGTH); - RaiiString newRaiistring = RaiiStringCreate(length + 1); - - if (newRaiistring.pString == NULL) { - return newRaiistring; - } strncpy(newRaiistring.pString, pCString, newRaiistring.lengthWithTermination - 1); newRaiistring.pString[newRaiistring.lengthWithTermination - 1] = '\0'; + return newRaiistring; } @@ -43,3 +39,49 @@ void RaiiStringClean(RaiiString *pThis) { } pThis->lengthWithTermination = 0; } + +bool RaiiStringAppend_RaiiString(RaiiString *pThis, + const RaiiString *pStringToAppend) { + const bool pointersAreValid = + (pThis != NULL && pThis->pString != NULL) && + (pStringToAppend != NULL && pStringToAppend->pString != NULL); + + if (!pointersAreValid) { + return false; + } + + // Subtract one to account for the redundant null-terminator + const size_t newLengthWithTermination = + pThis->lengthWithTermination - 1 + + pStringToAppend->lengthWithTermination; + + if (newLengthWithTermination > MAX_CSTRING_INCLUDING_TERMINATION_LENGTH) { + return false; + } + + char *pNewString = (char *)realloc(pThis->pString, + newLengthWithTermination * sizeof(char)); + if (pNewString == NULL) { + return false; + } + + // This method takes into account that the strings are appended to + // themselves. + memmove(&pNewString[pThis->lengthWithTermination - 1], + pStringToAppend->pString, + (pStringToAppend->lengthWithTermination - 1) * sizeof(char)); + pNewString[newLengthWithTermination - 1] = '\0'; + + pThis->pString = pNewString; + pThis->lengthWithTermination = newLengthWithTermination; + + return true; +} + +bool RaiiStringAppend_cString(RaiiString *pThis, const char *pOther) { + RAII_STRING other = RaiiStringCreateFromCString(pOther); + if (other.pString == NULL) { + return false; + } + return RaiiStringAppend_RaiiString(pThis, &other); +} diff --git a/CoDeLib/Test/Utility/FileUtils.c b/CoDeLib/Test/Utility/FileUtils.c index d2e90b4c..f255cb02 100644 --- a/CoDeLib/Test/Utility/FileUtils.c +++ b/CoDeLib/Test/Utility/FileUtils.c @@ -3,34 +3,10 @@ #include #include -void CreateFullPathToFile(const RaiiString *pFullPath, - const size_t maxFullPathStringSize, - const char *pBasePath, const char *pFileName) { - assert(pFullPath != NULL); - assert(pBasePath != NULL); - assert(pFileName != NULL); - assert(pFullPath->pString != NULL); - assert(pFullPath->lengthWithTermination >= maxFullPathStringSize); - - const int charsWritten = snprintf(pFullPath->pString, maxFullPathStringSize, - "%s%s", pBasePath, pFileName); - - if (charsWritten < 0) { - printf("Failed to write to string\n"); - exit(1); - } -} - -void OpenFile(FILE **pInFile, char *basePath, char *pFilename, - char *pOpenMode) { - const size_t lengthPath = strlen(basePath) + strlen(pFilename) + 1; - RaiiString fullPathString __attribute__((cleanup(RaiiStringClean))); - fullPathString = RaiiStringCreate(lengthPath); - CreateFullPathToFile(&fullPathString, lengthPath, basePath, pFilename); - - *pInFile = fopen(fullPathString.pString, pOpenMode); +void OpenFile(FILE **pInFile, RaiiString *pFullPath, char *pOpenMode) { + *pInFile = fopen(pFullPath->pString, pOpenMode); if (*pInFile == NULL) { - printf("Failed to open file: %s\n", fullPathString.pString); + printf("Failed to open file: %s\n", pFullPath->pString); exit(1); } } diff --git a/CoDeLib/Test/src/TestDeflateInflateZlib.c b/CoDeLib/Test/src/TestDeflateInflateZlib.c index fe902e59..f5b50084 100644 --- a/CoDeLib/Test/src/TestDeflateInflateZlib.c +++ b/CoDeLib/Test/src/TestDeflateInflateZlib.c @@ -28,12 +28,25 @@ TEST(TestDeflateInflateZlib, test_InflateZlibWorkWithDeflateZlib) { FILE *pOutCompressedFile = NULL; FILE *pOutDecompressedFile = NULL; - OpenFile(&pInFile, g_pFullPathToBenchmarkTestFiles, - "SmallBasicTextFile.txt", "r"); - OpenFile(&pOutCompressedFile, g_pFullPathToBenchmarkTestFiles, - "SmallBasicTextFile.compressed.txt", "w+"); - OpenFile(&pOutDecompressedFile, g_pFullPathToBenchmarkTestFiles, - "SmallBasicTextFile.decompressed.txt", "w+"); + RAII_STRING pathToSmallBasicTextFile = + RaiiStringCreateFromCString(g_pFullPathToBenchmarkTestFiles); + RaiiStringAppend_cString(&pathToSmallBasicTextFile, + "SmallBasicTextFile.txt"); + + RAII_STRING pathToSmallBasicTextFileCompressed = + RaiiStringCreateFromCString(g_pFullPathToBenchmarkTestFiles); + RaiiStringAppend_cString(&pathToSmallBasicTextFileCompressed, + "SmallBasicTextFile.compressed.txt"); + + RAII_STRING pathToSmallBasicTextFileDecompressed = + RaiiStringCreateFromCString(g_pFullPathToBenchmarkTestFiles); + RaiiStringAppend_cString(&pathToSmallBasicTextFileDecompressed, + "SmallBasicTextFile.decompressed.txt"); + + OpenFile(&pInFile, &pathToSmallBasicTextFile, "r"); + OpenFile(&pOutCompressedFile, &pathToSmallBasicTextFileCompressed, "w+"); + OpenFile(&pOutDecompressedFile, &pathToSmallBasicTextFileDecompressed, + "w+"); const DEFLATE_RETURN_CODES statusDeflate = deflate_zlib.Deflate(pInFile, pOutCompressedFile, NULL); diff --git a/CoDeLib/Test/src/TestRaiiString.c b/CoDeLib/Test/src/TestRaiiString.c index dc717949..64e1ebd7 100644 --- a/CoDeLib/Test/src/TestRaiiString.c +++ b/CoDeLib/Test/src/TestRaiiString.c @@ -12,59 +12,9 @@ TEST_SETUP(TestRaiiString) {} TEST_TEAR_DOWN(TestRaiiString) { RaiiStringClean(&raiiString); } //============================== -// RaiiStringCreate() +// RaiiStringCreateFromCString(...) //============================== -TEST(TestRaiiString, test_RaiiStringCreate_SetsCorrectsLengthInReturnedObject) { - const size_t length = 10; - raiiString = RaiiStringCreate(length); - TEST_ASSERT_EQUAL(length, raiiString.lengthWithTermination); -} - -TEST(TestRaiiString, test_RaiiStringCreate_SetsNonNullPointerInReturnedObject) { - const size_t length = 10; - raiiString = RaiiStringCreate(length); - TEST_ASSERT_NOT_NULL(raiiString.pString); -} - -TEST(TestRaiiString, - test_RaiiStringCreate_SetsNullptrAndLengthZeroIfGivenLengthIsZero) { - const size_t length = 0; - raiiString = RaiiStringCreate(length); - TEST_ASSERT_NULL(raiiString.pString); - TEST_ASSERT_EQUAL(0, raiiString.lengthWithTermination); -} - -TEST(TestRaiiString, - test_RaiiStringCreate_SetsZeroLengthAndNullptrIfLengthIsMaxLength) { - const size_t length = MAX_CSTRING_INCLUDING_TERMINATION_LENGTH; - raiiString = RaiiStringCreate(length); - TEST_ASSERT_NULL(raiiString.pString); - TEST_ASSERT_EQUAL(0, raiiString.lengthWithTermination); -} - -TEST( - TestRaiiString, - test_RaiiStringCreate_SetsZeroLengthAndNullptrIfLengthIsGreaterThanMaxLength) { - const size_t length = MAX_CSTRING_INCLUDING_TERMINATION_LENGTH + 1; - raiiString = RaiiStringCreate(length); - TEST_ASSERT_NULL(raiiString.pString); - TEST_ASSERT_EQUAL(0, raiiString.lengthWithTermination); -} - -//============================== -// RaiiStringCreateFromCString() -//============================== - -TEST( - TestRaiiString, - test_RaiiStringCreateFromCString_SetsLengthOfOneAndNonNullptrIfProvidedEmptyString) { - const char *pCString = ""; - raiiString = RaiiStringCreateFromCString(pCString); - TEST_ASSERT_NOT_NULL(raiiString.pString); - TEST_ASSERT_EQUAL(1, raiiString.lengthWithTermination); -} - TEST( TestRaiiString, test_RaiiStringCreateFromCString_SetsExecptedLengthAndNonNullptrIfProvidedNormalString) { @@ -83,29 +33,50 @@ TEST(TestRaiiString, test_RaiiStringCreateFromCString_SetsExecptedString) { TEST( TestRaiiString, test_RaiiStringCreateFromCString_DoesNotUseProvidedPointerInReturnedObject) { - const char *pCString = ""; + const char *pCString = "a"; raiiString = RaiiStringCreateFromCString(pCString); TEST_ASSERT_NOT_EQUAL(pCString, raiiString.pString); } TEST( TestRaiiString, - test_RaiiStringCreateFromCString_SetsZeroLengthAndNullptrIfLengthIsMaxLength) { + test_RaiiStringCreateFromCString_SetsExpectedLengthAndPtrIfLengthTotalIsMaxTotalLength) { + const size_t lengthWithNullTermination = + MAX_CSTRING_INCLUDING_TERMINATION_LENGTH; + char *pCString = (char *)malloc(lengthWithNullTermination * sizeof(char)); + assert(pCString != NULL && "Failed to allocate memory for pCString"); + memset(pCString, 'a', lengthWithNullTermination - 1); + pCString[lengthWithNullTermination - 1] = '\0'; + + raiiString = RaiiStringCreateFromCString(pCString); + TEST_ASSERT_NOT_NULL(raiiString.pString); + TEST_ASSERT_EQUAL_STRING(pCString, raiiString.pString); + TEST_ASSERT_EQUAL(lengthWithNullTermination, + raiiString.lengthWithTermination); + + free(pCString); +} + +TEST( + TestRaiiString, + test_RaiiStringCreateFromCString_SetsZeroLengthAndNullptrIfStringLengthIsMaxTotalLength) { const size_t lengthWithNullTermination = MAX_CSTRING_INCLUDING_TERMINATION_LENGTH + 1; char *pCString = (char *)malloc(lengthWithNullTermination * sizeof(char)); assert(pCString != NULL && "Failed to allocate memory for pCString"); memset(pCString, 'a', lengthWithNullTermination - 1); - pCString[MAX_CSTRING_INCLUDING_TERMINATION_LENGTH] = '\0'; + pCString[lengthWithNullTermination - 1] = '\0'; raiiString = RaiiStringCreateFromCString(pCString); TEST_ASSERT_NULL(raiiString.pString); TEST_ASSERT_EQUAL(0, raiiString.lengthWithTermination); + + free(pCString); } TEST( TestRaiiString, - test_RaiiStringCreateFromCString_SetsZeroLengthAndNullptrIfLengthIsGreaterThanMaxLength) { + test_RaiiStringCreateFromCString_SetsZeroLengthAndNullptrIfStringLengthIsGreaterThanMaxTotalLength) { const size_t lengthWithNullTermination = MAX_CSTRING_INCLUDING_TERMINATION_LENGTH + 2; char *pCString = (char *)malloc(lengthWithNullTermination * sizeof(char)); @@ -116,60 +87,239 @@ TEST( raiiString = RaiiStringCreateFromCString(pCString); TEST_ASSERT_NULL(raiiString.pString); TEST_ASSERT_EQUAL(0, raiiString.lengthWithTermination); + + free(pCString); +} + +TEST( + TestRaiiString, + test_RaiiStringCreateFromCString_SetsLengthOfZeroAndNullptrIfProvidedEmptyString) { + const char *pCString = ""; + raiiString = RaiiStringCreateFromCString(pCString); + TEST_ASSERT_NULL(raiiString.pString); + TEST_ASSERT_EQUAL(0, raiiString.lengthWithTermination); } //============================== -// RaiiStringClean() +// RaiiStringClean(...) //============================== TEST(TestRaiiString, test_RaiiStringClean_SetsNullptrInObject) { - raiiString = RaiiStringCreate(10); + raiiString = RaiiStringCreateFromCString("Hello, world!"); RaiiStringClean(&raiiString); TEST_ASSERT_NULL(raiiString.pString); } TEST(TestRaiiString, test_RaiiStringClean_SetsLengthZeroInObject) { - raiiString = RaiiStringCreate(10); + raiiString = RaiiStringCreateFromCString("Hello, world!"); RaiiStringClean(&raiiString); TEST_ASSERT_EQUAL(0, raiiString.lengthWithTermination); } +//============================== +// RAII_STRING +//============================== + +// Do no optimize to avoid -Werror=dangling-pointer= +#if defined(__GNUC__) && !defined(__clang__) +__attribute__((optimize("O0"))) +#elif defined(__clang__) +__attribute__((optnone)) +#endif +TEST(TestRaiiString, test_RAII_STRING_MacroWorksInScope) { + char **pointerToScopedRaiiStringString = NULL; + *pointerToScopedRaiiStringString = NULL; + { + RAII_STRING myString = RaiiStringCreateFromCString("Hello, world!"); + pointerToScopedRaiiStringString = &myString.pString; + + TEST_ASSERT_NOT_NULL(*pointerToScopedRaiiStringString); + TEST_ASSERT_EQUAL_STRING("Hello, world!", + *pointerToScopedRaiiStringString); + } + + if (pointerToScopedRaiiStringString != NULL) { + TEST_ASSERT_NULL(*pointerToScopedRaiiStringString); + } else { + TEST_FAIL_MESSAGE("pointerToScopedRaiiStringString is NULL"); + } +} + +//============================== +// RaiiStringAppend_RaiiString(...) +//============================== + +TEST(TestRaiiString, + test_RaiiStringAppend_RaiiString_ReturnsFalseIfDstStringIsNull) { + raiiString = RaiiStringCreateFromCString("Hello, world!"); + bool appended = RaiiStringAppend_RaiiString(NULL, &raiiString); + TEST_ASSERT_FALSE(appended); +} + +TEST(TestRaiiString, + test_RaiiStringAppend_RaiiString_ReturnsFalseIfInternalStringOfDstIsNull) { + raiiString = RaiiStringCreateFromCString("Hello, "); + RAII_STRING stringToAppend = RaiiStringCreateFromCString("world!"); + raiiString.pString = NULL; + + bool appended = RaiiStringAppend_RaiiString(&raiiString, &stringToAppend); + + TEST_ASSERT_FALSE(appended); +} + +TEST( + TestRaiiString, + test_RaiiStringAppend_RaiiString_ReturnsFalseIfInternalStringOfStringToAppendIsNull) { + raiiString = RaiiStringCreateFromCString("Hello, "); + RAII_STRING stringToAppend = RaiiStringCreateFromCString("world!"); + stringToAppend.pString = NULL; + + bool appended = RaiiStringAppend_RaiiString(&raiiString, &stringToAppend); + + TEST_ASSERT_FALSE(appended); +} + +TEST(TestRaiiString, + test_RaiiStringAppend_RaiiString_ReturnsFalseIfStringToAppendIsNull) { + raiiString = RaiiStringCreateFromCString("Hello, world!"); + bool appended = RaiiStringAppend_RaiiString(&raiiString, NULL); + TEST_ASSERT_FALSE(appended); +} + +TEST(TestRaiiString, test_RaiiStringAppend_RaiiString_AppendsStringToDst) { + raiiString = RaiiStringCreateFromCString("Hello, "); + RAII_STRING stringToAppend = RaiiStringCreateFromCString("world!"); + + bool appended = RaiiStringAppend_RaiiString(&raiiString, &stringToAppend); + + TEST_ASSERT_TRUE(appended); + TEST_ASSERT_EQUAL_STRING("Hello, world!", raiiString.pString); + TEST_ASSERT_EQUAL(14, raiiString.lengthWithTermination); +} + +TEST(TestRaiiString, + test_RaiiStringAppend_RaiiString_HandlesAppendingToSelfCorrectly) { + raiiString = RaiiStringCreateFromCString("Hello"); + + bool appended = RaiiStringAppend_RaiiString(&raiiString, &raiiString); + + TEST_ASSERT_TRUE(appended); + TEST_ASSERT_EQUAL_STRING("HelloHello", raiiString.pString); + TEST_ASSERT_EQUAL(11, raiiString.lengthWithTermination); +} + +TEST(TestRaiiString, + test_RaiiStringAppend_RaiiString_StringToAppendIsUnchanged) { + raiiString = RaiiStringCreateFromCString("Hello, "); + RAII_STRING stringToAppend = RaiiStringCreateFromCString("world!"); + + RaiiStringAppend_RaiiString(&raiiString, &stringToAppend); + + TEST_ASSERT_EQUAL_STRING("world!", stringToAppend.pString); + TEST_ASSERT_EQUAL(7, stringToAppend.lengthWithTermination); +} + +TEST( + TestRaiiString, + test_RaiiStringAppend_RaiiString_ReturnsFalseAndDoesntChangeStringsIfTotalLengthIsGreaterThanMaxLengthWithTermination) { + + // Base string + const size_t lengthWithNullTermination_baseString = + MAX_CSTRING_INCLUDING_TERMINATION_LENGTH - 10; + char *pCString_baseString = + (char *)malloc(lengthWithNullTermination_baseString * sizeof(char)); + assert(pCString_baseString != NULL && + "Failed to allocate memory for pCString_baseString"); + memset(pCString_baseString, 'a', lengthWithNullTermination_baseString - 1); + pCString_baseString[lengthWithNullTermination_baseString - 1] = '\0'; + raiiString = RaiiStringCreateFromCString(pCString_baseString); + + // String to append + const size_t lengthWithNullTermination_appendString = 12; + char *pCString_appendString = + (char *)malloc(lengthWithNullTermination_appendString * sizeof(char)); + assert(pCString_appendString != NULL && + "Failed to allocate memory for pCString_appendString"); + memset(pCString_appendString, 'a', + lengthWithNullTermination_appendString - 1); + pCString_appendString[lengthWithNullTermination_appendString - 1] = '\0'; + RAII_STRING appendRaiiString = + RaiiStringCreateFromCString(pCString_appendString); + + // The test + bool appendStatus = + RaiiStringAppend_RaiiString(&raiiString, &appendRaiiString); + + TEST_ASSERT_FALSE(appendStatus); + TEST_ASSERT_EQUAL_STRING(pCString_baseString, raiiString.pString); + TEST_ASSERT_EQUAL(lengthWithNullTermination_baseString, + raiiString.lengthWithTermination); + TEST_ASSERT_EQUAL_STRING(pCString_appendString, appendRaiiString.pString); + TEST_ASSERT_EQUAL(lengthWithNullTermination_appendString, + appendRaiiString.lengthWithTermination); + + free(pCString_baseString); + free(pCString_appendString); +} + +//============================== +// RaiiStringAppend_cString(...) +//============================== + +// Currently, this function only uses already tested functions for RaiiString. + +//============================== +// TEST_GROUP_RUNNER +//============================== + TEST_GROUP_RUNNER(TestRaiiString) { - // RaiiStringCreate() - RUN_TEST_CASE(TestRaiiString, - test_RaiiStringCreate_SetsCorrectsLengthInReturnedObject); + // RaiiStringCreateFromCString() + RUN_TEST_CASE( + TestRaiiString, + test_RaiiStringCreateFromCString_SetsExecptedLengthAndNonNullptrIfProvidedNormalString); RUN_TEST_CASE(TestRaiiString, - test_RaiiStringCreate_SetsNonNullPointerInReturnedObject); + test_RaiiStringCreateFromCString_SetsExecptedString); + RUN_TEST_CASE( + TestRaiiString, + test_RaiiStringCreateFromCString_DoesNotUseProvidedPointerInReturnedObject); + RUN_TEST_CASE( + TestRaiiString, + test_RaiiStringCreateFromCString_SetsExpectedLengthAndPtrIfLengthTotalIsMaxTotalLength); RUN_TEST_CASE( TestRaiiString, - test_RaiiStringCreate_SetsNullptrAndLengthZeroIfGivenLengthIsZero); + test_RaiiStringCreateFromCString_SetsZeroLengthAndNullptrIfStringLengthIsMaxTotalLength); RUN_TEST_CASE( TestRaiiString, - test_RaiiStringCreate_SetsZeroLengthAndNullptrIfLengthIsMaxLength); + test_RaiiStringCreateFromCString_SetsZeroLengthAndNullptrIfStringLengthIsGreaterThanMaxTotalLength); RUN_TEST_CASE( TestRaiiString, - test_RaiiStringCreate_SetsZeroLengthAndNullptrIfLengthIsGreaterThanMaxLength); + test_RaiiStringCreateFromCString_SetsLengthOfZeroAndNullptrIfProvidedEmptyString); - // RaiiStringCreateFromCString() + // RaiiStringClean() + RUN_TEST_CASE(TestRaiiString, test_RaiiStringClean_SetsNullptrInObject); + RUN_TEST_CASE(TestRaiiString, test_RaiiStringClean_SetsLengthZeroInObject); + + // RaiiStringAppend() RUN_TEST_CASE( TestRaiiString, - test_RaiiStringCreateFromCString_SetsLengthOfOneAndNonNullptrIfProvidedEmptyString); + test_RaiiStringAppend_RaiiString_ReturnsFalseIfDstStringIsNull); RUN_TEST_CASE( TestRaiiString, - test_RaiiStringCreateFromCString_SetsExecptedLengthAndNonNullptrIfProvidedNormalString); - RUN_TEST_CASE(TestRaiiString, - test_RaiiStringCreateFromCString_SetsExecptedString); + test_RaiiStringAppend_RaiiString_ReturnsFalseIfStringToAppendIsNull); RUN_TEST_CASE( TestRaiiString, - test_RaiiStringCreateFromCString_DoesNotUseProvidedPointerInReturnedObject); + test_RaiiStringAppend_RaiiString_ReturnsFalseIfInternalStringOfDstIsNull); RUN_TEST_CASE( TestRaiiString, - test_RaiiStringCreateFromCString_SetsZeroLengthAndNullptrIfLengthIsMaxLength); + test_RaiiStringAppend_RaiiString_ReturnsFalseIfInternalStringOfStringToAppendIsNull); + RUN_TEST_CASE(TestRaiiString, + test_RaiiStringAppend_RaiiString_AppendsStringToDst); RUN_TEST_CASE( TestRaiiString, - test_RaiiStringCreateFromCString_SetsZeroLengthAndNullptrIfLengthIsGreaterThanMaxLength); - - // RaiiStringClean() - RUN_TEST_CASE(TestRaiiString, test_RaiiStringClean_SetsNullptrInObject); - RUN_TEST_CASE(TestRaiiString, test_RaiiStringClean_SetsLengthZeroInObject); + test_RaiiStringAppend_RaiiString_HandlesAppendingToSelfCorrectly); + RUN_TEST_CASE(TestRaiiString, + test_RaiiStringAppend_RaiiString_StringToAppendIsUnchanged); + RUN_TEST_CASE( + TestRaiiString, + test_RaiiStringAppend_RaiiString_ReturnsFalseAndDoesntChangeStringsIfTotalLengthIsGreaterThanMaxLengthWithTermination); } diff --git a/CoDeLib/Test/src/main.c b/CoDeLib/Test/src/main.c index 79fc7503..c5068e81 100644 --- a/CoDeLib/Test/src/main.c +++ b/CoDeLib/Test/src/main.c @@ -9,8 +9,7 @@ static void RunAllTests(void) { } int main(int argc, const char **argv) { - RaiiString fullPathToBenchmarkTestFiles - __attribute__((cleanup(RaiiStringClean))); + RAII_STRING fullPathToBenchmarkTestFiles; // TODO: use getopt(...) if (argc == 1) { diff --git a/CoDeLib/include/CoDeLib/RaiiString/RaiiString.h b/CoDeLib/include/CoDeLib/RaiiString/RaiiString.h index 481ccf4f..17b00bc4 100644 --- a/CoDeLib/include/CoDeLib/RaiiString/RaiiString.h +++ b/CoDeLib/include/CoDeLib/RaiiString/RaiiString.h @@ -1,14 +1,16 @@ #pragma once +#include #include /*! Usage: - RaiiString myString __attribute__((cleanup(RaiiStringClean))); - myString = RaiiStringCreate(lengthPath); + RAII_STRING myString = RaiiStringCreateFromCString("Hello, world!"); */ +#define RAII_STRING RaiiString __attribute__((cleanup(RaiiStringClean))) + typedef struct { char *pString; @@ -19,6 +21,12 @@ typedef struct { // Maximum length of a C string (including the null terminator) static const size_t MAX_CSTRING_INCLUDING_TERMINATION_LENGTH = 1024; -RaiiString RaiiStringCreate(size_t length); +/*! +@brief Creates a RaiiString object from a C string. The provided C string is +copied and not altered. +*/ RaiiString RaiiStringCreateFromCString(const char *pCString); void RaiiStringClean(RaiiString *pThis); + +bool RaiiStringAppend_RaiiString(RaiiString *pThis, const RaiiString *pOther); +bool RaiiStringAppend_cString(RaiiString *pThis, const char *pOther); diff --git a/CoDeLib/include/CoDeLib/Test/Utility/FileUtils.h b/CoDeLib/include/CoDeLib/Test/Utility/FileUtils.h index 6044b9a5..4e0758ac 100644 --- a/CoDeLib/include/CoDeLib/Test/Utility/FileUtils.h +++ b/CoDeLib/include/CoDeLib/Test/Utility/FileUtils.h @@ -4,9 +4,6 @@ #include #include -void CreateFullPathToFile(const RaiiString *pFullPath, - const size_t maxFullPathStringSize, - const char *pBasePath, const char *pFileName); -void OpenFile(FILE **pInFile, char *basePath, char *pFilename, char *pOpenMode); +void OpenFile(FILE **pInFile, RaiiString *pFullPath, char *pOpenMode); size_t GetFileSizeInBytes(FILE *pFile); bool FilesAreEqual(FILE *pFile1, FILE *pFile2); From db01287617895aa64911102c3861fd88080711e6 Mon Sep 17 00:00:00 2001 From: Enzo Evers Date: Wed, 4 Dec 2024 20:58:02 +0100 Subject: [PATCH 2/2] infra: enable verbose unit tests --- Scripts/RunTest.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Scripts/RunTest.py b/Scripts/RunTest.py index f9e96b11..20104009 100644 --- a/Scripts/RunTest.py +++ b/Scripts/RunTest.py @@ -112,7 +112,7 @@ def RunTests( TestExecutablePath.chmod(TestExecutablePath.stat().st_mode | stat.S_IEXEC) - TestOptions = '"' + str(BenchmarkTestFilesPath) + '/"' + TestOptions = '"' + str(BenchmarkTestFilesPath) + '/"' + " -v" TestCommand = str(TestExecutablePath) + " " + TestOptions RawTestResultsFileNames.append(GetTestResultsFileRawName(buildConfig, testName)) @@ -124,11 +124,17 @@ def RunTests( shell=True, check=False, stdout=TestResultsFileRaw, + stderr=subprocess.STDOUT, ) PrependTestHeaderInRawResultsFile(testHeader, RawTestResultsFileNames[-1]) TestResultsFileRaw.close() if result.returncode != 0: + print(testHeader) + print("Failed\n") + print("Called command:\n") + print(TestCommand) + print("\n") success = False return (success, RawTestResultsFileNames)