0

To have full access to all static variables and functions from inside the unittest i do include the c-file in the unittest c-file.

I use gcc-11.2.1 and the target is a small microcontroller stm32L0

Now i have same strange behaviour where i have two instances of the static object my and therefore also from my.var

However in this small example everything works like expected and there is only one instance of the object my and the unittest passes with no errors, but in my much bigger development project i have debugged that the compiler uses two different instances. Unfortunatly i cannot upload my development project so i tried to minimize the sourcecode to the relevant part for this question.

source of buildingblock.h

#ifndef __BUILDINGBLOCK_H
#define __BUILDINGBLOCK_H

#include <stdint.h>

uint8_t pub_getVar();

#endif

source of buildingblock.c

#include "buildingblock.h"

typedef struct{
    uint8_t var;
}my_t;

static my_t my = {
    .var = 0
};

static uint8_t getVar(){
  return my.var;
}

#ifndef YES_TESTCODE

uint8_t pub_getVar(){
    return my.var;
}

#endif

source of unittest.h

#ifndef __UNITTEST_H
#define __UNITTEST_H


// This define can be used to handle special handling for the test code.
// E.g. public variables/functions cannot be defined in the unit test, otherwise the linker generates an error message because of a duplicate function definition.
#define YES_TESTCODE

void ut_run();

#endif

source of unittest.c

// I use lib-unity see https://github.com/ThrowTheSwitch
#include "unity.h" // lib-unit header
#include "unittest.h"
#include "buildingblock.c"


// increment of a static variable
static void test(){

  my.var++;
  uint8_t ret = getVar();

  TEST_ASSERT_EQUAL_UINT8(1,ret);
}

// calls this from your main
void ut_run()
{
    pub_getVar();
    UNITY_BEGIN();
    RUN_TEST(test);
    UNITY_END();
}

For my development-project i have to exclude buildingblock.c from the build and only include the c-file. Than i have ony one instance of the object my and i can test as expected.

Does anybody know why i have two instances in my more complex development project ? I understand that the compiler could have problems with the scope but i also get no errors or warnings but the buggy result.

MaxM.
  • 71
  • 4
  • 2
    Can't reproduce. Please update your question to include a [mcve]. – dbush Jun 23 '23 at 12:48
  • Yes this should work as long as you don't compile buildingblock.c, includes in C is just copy pasting the contents of the included file at the location of the include. – Fredrik Jun 23 '23 at 12:50
  • Did you show us the whole code? – Nabuchodonozor Jun 23 '23 at 12:57
  • Including C files is a bad idea. – 0___________ Jun 23 '23 at 13:06
  • _Any risks...?_. Including a `.c` file into another `.c` is legal, but not common. From a maintainability perspective (where someone else will be expected to come in cold and make sense of what the code is doing) I think there would be increased chances for decisions being made that are incongruous with the original intent of the code. – ryyker Jun 23 '23 at 13:06
  • @0___________ it's common practice when doing a "unity" build – Fredrik Jun 23 '23 at 13:15
  • See [How to test a `static` function?](https://stackoverflow.com/q/593414/15168) for circumstances where it may be legitimate to include a C source file inside another. There are limits to what that can do — it is an extraordinary scenario, not something to practice routinely. Most notably, if both the including file and the included file try to define the same `static` variable or function, there will be conflicts with the combo that would be absent if the files were compiled separately. This is somewhat tangential to the OP's question. – Jonathan Leffler Jun 23 '23 at 17:26
  • With the code as shown, the optimizer would (legitimately) omit the call to `getVar()` because calling it cannot affect the state of the computation. If you printed the returned value, or modified the `test()` function to return it, you might see different results. If compiled without optimization and run in a debugger, you might be able to see `ret` containing `1` after the call, but make sure you are looking after the call, not before. Maybe your minimization was a bit too thorough. – Jonathan Leffler Jun 23 '23 at 17:29
  • Can someone please reopen this question ? I edited it and included new source-code. – MaxM. Jul 06 '23 at 12:54

0 Answers0