diff --git a/CMakeLists.txt b/CMakeLists.txt index f65266481..71a5f9b01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -410,12 +410,50 @@ if (ENABLE_UNIT_TESTS) enable_testing() + # Set the output paths + set(DEFAULT_LD_FULL_PATH "${CMAKE_CURRENT_BINARY_DIR}/default_full.ld") + set(DEFAULT_LD_PATH "${CMAKE_CURRENT_BINARY_DIR}/default.ld") + set(DEFAULT_LD_PATH_ESCAPED "${DEFAULT_LD_PATH}") + string(REPLACE "\\" "/" DEFAULT_LD_PATH_ESCAPED "${DEFAULT_LD_PATH_ESCAPED}") + set(DEFAULT_LD_PATH_ESCAPED "${DEFAULT_LD_PATH_ESCAPED}") + + # Add a custom command to generate the default linker script + add_custom_command( + OUTPUT ${DEFAULT_LD_PATH} + COMMAND ${CMAKE_LINKER} --verbose > ${DEFAULT_LD_FULL_PATH} + COMMAND ${CMAKE_COMMAND} -DDEFAULT_LD_FULL_PATH=${DEFAULT_LD_FULL_PATH} -DDEFAULT_LD_PATH=${DEFAULT_LD_PATH} -P ${CMAKE_SOURCE_DIR}/ut_assert/extract_linker_script.cmake + COMMENT "Generating default linker script (default.ld)" + ) + + + # Configure the custom linker script + configure_file( + ${CMAKE_SOURCE_DIR}/ut_assert/utest_linker.ld.in + ${CMAKE_BINARY_DIR}/utest_linker.ld + @ONLY + ) + + add_custom_target( + generate_linker_scripts + DEPENDS ${DEFAULT_LD_PATH} ${CMAKE_BINARY_DIR}/utest_linker.ld + ) + # Generic function for consistent definition of a unit testing target # This is defined here in the top-level OSAL CMakeLists so it can be used # in both the "tests" and "unit-tests" subdirectories. function(add_osal_ut_exe TGTNAME) add_executable(${TGTNAME} ${ARGN}) + add_dependencies(${TGTNAME} generate_linker_scripts) + + # Specify the path to your custom linker script + set(LINKER_SCRIPT "${CMAKE_BINARY_DIR}/utest_linker.ld") + + # Pass the linker script to the linker via linker flags + target_link_options(${TGTNAME} PRIVATE + "-Wl,-T${LINKER_SCRIPT}" + ) + target_link_libraries(${TGTNAME} PUBLIC ut_assert osal) add_test(${TGTNAME} ${TGTNAME}) foreach(TGT ${INSTALL_TARGET_LIST}) diff --git a/src/tests/bin-sem-test/bin-sem-test.c b/src/tests/bin-sem-test/bin-sem-test.c index e02de461c..200ecd7c5 100644 --- a/src/tests/bin-sem-test/bin-sem-test.c +++ b/src/tests/bin-sem-test/bin-sem-test.c @@ -69,7 +69,8 @@ void Test_BinSem_Task2(void) } } -void Test_BinSem(void) +//void Test_BinSem(void) +UTEST(BinSem, Test) { osal_id_t sem_id[2]; @@ -214,6 +215,16 @@ void Test_BinSem(void) UtAssert_INT32_EQ(OS_BinSemDelete(sem_id[1]), OS_SUCCESS); } +UTEST(BinSem, Test2) +{ + printf("A"); +} + +UTEST(BinSem, Test3) +{ + printf("B"); +} + void UtTest_Setup(void) { if (OS_API_Init() != OS_SUCCESS) @@ -227,5 +238,5 @@ void UtTest_Setup(void) /* * Register the test setup and check routines in UT assert */ - UtTest_Add(Test_BinSem, NULL, NULL, "Test_BinSem"); + //UtTest_Add(Test_BinSem, NULL, NULL, "Test_BinSem"); } diff --git a/ut_assert/extract_linker_script.cmake b/ut_assert/extract_linker_script.cmake new file mode 100644 index 000000000..d607301f2 --- /dev/null +++ b/ut_assert/extract_linker_script.cmake @@ -0,0 +1,10 @@ +# extract_linker_script.cmake + +# Read the full linker output +file(READ "${DEFAULT_LD_FULL_PATH}" LD_OUTPUT) + +# Use a simple regex to extract the default linker script between '====' lines +string(REGEX REPLACE ".*=+\n(.*)\n=+.*" "\\1" LD_SCRIPT_CONTENTS "${LD_OUTPUT}") + +# Write the extracted linker script to default.ld +file(WRITE "${DEFAULT_LD_PATH}" "${LD_SCRIPT_CONTENTS}") \ No newline at end of file diff --git a/ut_assert/inc/uttest.h b/ut_assert/inc/uttest.h index aae42c468..0d48f736f 100644 --- a/ut_assert/inc/uttest.h +++ b/ut_assert/inc/uttest.h @@ -117,4 +117,32 @@ void UtTest_Run(void); */ void UtTest_Setup(void); + +typedef void (*UTTestFunction)(void); + +typedef struct UtTestRecord{ + int marker; + const char * testSuite; + const char * functionName; + const char * fileName; + const char * testName; + int lineNumber; + UTTestFunction functionPointer; + int padding; /* Size needs to be 64 bytes long for some reason */ +}UtTestRecord; + +#define UTEST(suiteName, uTtestName) \ + static void suiteName##_##uTtestName(void); \ + static UtTestRecord Record_##suiteName##_##uTtestName \ + __attribute__((section(".utest_records"), used)) = { \ + .marker = 0xDeadBeaf, \ + .testSuite = #suiteName, \ + .functionName = #uTtestName, \ + .testName = #suiteName #uTtestName, \ + .fileName = __FILE__, \ + .lineNumber = __LINE__, \ + .functionPointer = suiteName##_##uTtestName \ + }; \ + static void suiteName##_##uTtestName(void) + #endif /* UTTEST_H */ diff --git a/ut_assert/src/utbsp.c b/ut_assert/src/utbsp.c index 6a929e8ce..080ff001c 100644 --- a/ut_assert/src/utbsp.c +++ b/ut_assert/src/utbsp.c @@ -230,6 +230,10 @@ void OS_Application_Run(void) UtTest_Run(); } +/* Defined in linker script */ +extern UtTestRecord __start_utest_records; +extern UtTestRecord __stop_utest_records; + /* * Entry point from the BSP. * When linking with UT-Assert, the test framework (this library) serves @@ -242,11 +246,24 @@ void OS_Application_Startup(void) UtTest_EarlyInit(); UT_BSP_Setup(); + /* * Wrap the UtTest_Setup() function in a UT segment called "SETUP" * This allows any assert calls to be used and recorded during setup */ UtAssert_BeginTest("SETUP"); + + /* TODO PROBALBY a better spot for this */ + UtTestRecord *test = &__start_utest_records; + // printf("Size of record is %d\n", sizeof(*test)); + int num_records = (&__stop_utest_records - &__start_utest_records)/ sizeof(*test); + // printf("Num records is %d \n",num_records); + while (test < &__stop_utest_records) { + // printf(" Adding test %s\n", test->functionName); + UtTest_Add(test->functionPointer, NULL, NULL, test->functionName); + test++; + } + UtTest_Setup(); UtAssert_EndTest(); } diff --git a/ut_assert/utest_linker.ld.in b/ut_assert/utest_linker.ld.in new file mode 100644 index 000000000..2de9d81d8 --- /dev/null +++ b/ut_assert/utest_linker.ld.in @@ -0,0 +1,16 @@ +/* Include the default linker script */ +INCLUDE "@DEFAULT_LD_PATH@" + + +SECTIONS +{ + + /* Define the .utest_records section */ + .utest_records : + { + __start_utest_records = .; + KEEP(*(.utest_records)); + __stop_utest_records = .; + } +} +