Add dmod unit test framework: dmod_test.h, DMOD_TEST_STEP, dmod_add_test, Dmod_RunTests#306
Conversation
JohnAmadis
left a comment
There was a problem hiding this comment.
@copilot popraw to proszę i jeszcze dodaj jakiś krok na CI który weryfikuje przykładowy test - żeby potwierdzić że się on kompiluje I działa
| /* Obtain the footer via the module header. | ||
| * DMOD_Header == binary base address (ModuleHeader is at offset 0). | ||
| * After loading, Footer.Ptr is the relocated pointer to __footer_start. */ | ||
| Dmod_ModuleFooter_t* footer = (Dmod_ModuleFooter_t*)DMOD_Header->Footer.Ptr; |
There was a problem hiding this comment.
Nie rób tej magii tutaj, bo będzie śmietnik - zamiast tego dodaj ją tak jak inne są dodawane, do dmod
There was a problem hiding this comment.
Done. The footer/section pointer arithmetic is now in Dmod_Module_GetInputs() in dmod_module.c/dmod_module.h, consistent with how other module-side helpers live there. dmod_test_main.c now simply calls that function.
| /* Return 1 if sig starts with the test signature prefix, 0 otherwise. */ | ||
| static int IsTestSignature( const char* sig ) | ||
| { | ||
| const char prefix[] = DMOD_TEST_SIGNATURE_PREFIX; |
There was a problem hiding this comment.
Te funkcje też nie powinny być tutaj, tylko razem z innymi podobnymi
There was a problem hiding this comment.
Moved. IsTestSignature() is now Dmod_ApiSignature_IsTest() in dmod_common.c, declared in dmod.h alongside Dmod_ApiSignature_IsMal() and Dmod_ApiSignature_IsBuiltin(). GetTestName() was replaced by the existing Dmod_ApiSignature_GetName().
| int main( int argc, char* argv[] ) | ||
| { | ||
| (void)argc; | ||
| (void)argv; |
There was a problem hiding this comment.
Jakieś wsparcie dla filtrów z linii komend by się przydało, może np po nazwie kroku?
There was a problem hiding this comment.
Added. main() now accepts step names as positional arguments — any argument after argv[0] is treated as a step-name allowlist. With no arguments all steps run as before. Example: dmod_loader ./test_example.dmf arithmetic null_checks runs only those two steps.
| #include "dmod_test.h" | ||
|
|
||
| /* Optional: runs before every test step */ | ||
| /* void dmod_test_setup(void) {} */ |
There was a problem hiding this comment.
Setup I teardown też może być w szablonie
There was a problem hiding this comment.
Done. The template now includes real dmod_test_setup() / dmod_test_teardown() stubs (uncommented) so new test modules get fixture hooks out of the box.
…ample CI test - Add Dmod_ApiSignature_IsTest() to dmod_common.c / dmod.h alongside IsMal() and IsBuiltin() - Add Dmod_Module_GetInputs() to dmod_module.c / dmod_module.h to encapsulate footer/section pointer arithmetic - Rewrite dmod_test_main.c to use the new proper APIs instead of inline magic; remove IsTestSignature() / GetTestName() helpers; add command-line step-name filtering (argv[1..] as allowlist) - Add setup/teardown stubs (uncommented) to the test module template - Add examples/module/test_example/ as a self-contained dmod_add_test example with arithmetic, boolean, and null-check steps - Add CI step in .github/workflows/ci.yml to build and run the example test module via dmod_loader
All four review items addressed (see individual thread replies). A CI step was also added to |
JohnAmadis
left a comment
There was a problem hiding this comment.
@copilot popraw to proszę. Nie chce grzebania po wnętrzu poza dmod
|
|
||
| for( uint32_t i = 0; i < count; i++ ) | ||
| { | ||
| if( entries[i].Function == NULL ) { continue; } |
There was a problem hiding this comment.
@copilot nie masz tutaj grzebać po bebechach dmoda - sprawdź sobie jak dif jest zaimplementowany - tam mamy odpowiednie API do uzyskania kolejnych wpisów, tutaj też coś takiego chcemy
There was a problem hiding this comment.
Fixed in 0d5f5aa. dmod_test_main.c no longer accesses DMOD_Header or the footer — it simply calls Dmod_RunTests(Dmod_GetModuleContext(...), argc, argv). The inputs-section iteration now lives inside Dmod_RunTests in dmod_dmf_cb.c, using Dmod_Api_GetNumberOfEntries + Context->Inputs.InputSection->Entries exactly as Dmod_Irq does.
| @@ -93,6 +93,7 @@ extern bool Dmod_ApiSignature_ReadModuleVersion( const char* Signature, | |||
| extern bool Dmod_ApiSignature_AreCompatible( const char* Signature1, const char* Signature2 ); | |||
There was a problem hiding this comment.
Nie dodałeś wsparcia dla tej sygnatury do ApiSignature i nie ma szans by ten moduł ci ruszył
There was a problem hiding this comment.
Added in 0d5f5aa. Dmod_RunTests is now declared as DMOD_BUILTIN_API(Dmod, 1.0, int, _RunTests, (Dmod_Context_t* Context, int argc, char* argv[])) in inc/dmod.h. On the system side this registers the implementation in .dmod.inputs; on the module side it creates the output function-pointer slot that gets resolved at load time — same mechanism as every other builtin.
|
|
||
| Dmod_Module_GetInputs( &entries, &count ); | ||
|
|
||
| Dmod_Printf( "=== DMOD Test Runner ===\n" ); |
There was a problem hiding this comment.
Dodaj nowa funkcje w dmod.h i dmod_system.h : Dmod_RunTests oraz Dmoda_RunModuleTests - jedna powinna brać jako parametr po prostu kontekst (oraz argc i argv), a druga nazwę modułu do odpalenia testów (podobnie jak to z innymi interfejsami jest zrobione, zobaczysz o co chodzi. Ja to z pamięci pisze teraz) wtedy tutaj w main wystarczy odpalić tylko te jedna funkcje
There was a problem hiding this comment.
Done in commit 0d5f5aa. Dmod_RunTests(Dmod_Context_t* Context, int argc, char* argv[]) is now a DMOD_BUILTIN_API in dmod.h / implemented in dmod_dmf_cb.c following the Dmod_Irq pattern (iterates Context->Inputs.InputSection->Entries, no internals exposed). Dmod_RunModuleTests(const char* ModuleName, int argc, char* argv[]) is in dmod_system.h / dmod_system.c following Dmod_RunModule. main() in dmod_test_main.c is now just return Dmod_RunTests(Dmod_GetModuleContext(Dmod_GetCurrentModuleName()), argc, argv);.
… fixtures in .dmod.inputs
Fixed in |
Modules frequently need lightweight in-process testing without the overhead of linking gtest or similar. This adds a first-class dmod test framework: a
dmod_test.hheader with assertion macros, aDMOD_TEST_STEPregistration macro, and admod_add_testCMake function that injects a pre-builtmain()which auto-discovers and runs all registered steps.Mechanics
Test steps register themselves into the
.dmod.inputsELF section (same mechanism as IRQ handlers) using a\021DTST\022-prefixed signature. Three additional reserved entries are registered automatically bydmod_test_main.c:__setup__,__teardown__, and__step_failed__. The system-sideDmod_RunTests()iterates the inputs section (following theDmod_Irqpattern), discovers those fixture entries, and calls each test step in sequence — no manual registration list required.main()delegates entirely toDmod_RunTests().New API surface
DMOD_TEST_STEP(name)— defines and registers a test step functiondmod_test.h):DMOD_TEST_EXPECT_EQ,DMOD_TEST_EXPECT_NE,DMOD_TEST_EXPECT_TRUE,DMOD_TEST_EXPECT_FALSE,DMOD_TEST_EXPECT_NULL,DMOD_TEST_EXPECT_NOT_NULL,DMOD_TEST_FAIL,DMOD_TEST_FAIL_MSGdmod_test_setup()/dmod_test_teardown()— weak-symbol hooks called before/after each step; override with a strong definition to add fixturesdmod_add_test(name version sources...)— CMake function; behaves likedmod_add_executablebut appendsdmod_test_main.cautomaticallyDmod_ApiSignature_IsTest(signature)— public predicate indmod_common.c/dmod.h, alongsideDmod_ApiSignature_IsMal()andDmod_ApiSignature_IsBuiltin()Dmod_Module_GetInputs(outEntries, outCount)— module-side helper indmod_module.c/dmod_module.hthat encapsulates footer pointer arithmetic for accessing the.dmod.inputssectionDmod_RunTests(Context, argc, argv)—DMOD_BUILTIN_APIindmod.h; system-side implementation indmod_dmf_cb.cthat iterates the module's.dmod.inputssection, discovers fixture entries, applies optional step-name filtering fromargv, and returns the number of failed stepsDmod_RunModuleTests(ModuleName, argc, argv)— system-side convenience indmod_system.h/dmod_system.c; loads the named module and runs its tests viaDmod_Run, following theDmod_RunModulepatternDmod_RunTestsaccepts step names as positional arguments; only the named steps run (e.g.dmod_loader test.dmf arithmetic null_checks); no arguments runs all stepsUsage
Files changed
inc/dmod_defs.h—DMOD_TEST_SIGNATURE_PREFIX,DMOD_MAKE_TEST_SIGNATURE,DMOD_TEST_STEPmacroinc/dmod_test.h(new) — public test API headerinc/dmod_module.h— addedDmod_Module_GetInputs()declarationsrc/module/dmod_test_main.c(new) — registers__setup__,__teardown__,__step_failed__fixture entries in.dmod.inputs;main()callsDmod_RunTests(Dmod_GetModuleContext(...), argc, argv)src/module/dmod_module.c— addedDmod_Module_GetInputs()implementationsrc/common/dmod_common.c— addedDmod_ApiSignature_IsTest()and extendedDmod_ApiSignature_IsValidto accept test signaturesinc/dmod.h— declaredDmod_ApiSignature_IsTest()andDMOD_BUILTIN_APIforDmod_RunTestsinc/dmod_system.h— declaredDmod_RunTestsandDmod_RunModuleTestssrc/system/public/dmod_dmf_cb.c— implementedDmod_RunTests(followsDmod_Irqpattern)src/system/dmod_system.c— implementedDmod_RunModuleTests(followsDmod_RunModulepattern)scripts/CMakeLists.txt—dmod_add_testfunctiontemplates/module/test/(new) — module template for test modules, includingdmod_test_setup()/dmod_test_teardown()stubsexamples/module/test_example/(new) — example test module built withdmod_add_test; used by CI to verify the framework compiles and runs end-to-enddocs/cmake-functions.md—dmod_add_testdocumentation.github/workflows/ci.yml— CI step that loadstest_example.dmfviadmod_loaderand verifies all steps pass