C Unit Test: stub a constant structure (gcc --wrap) - c

Hi All here is my specific case:
service.h:
typedef struct {
uint8_t (*function1)(void);
uint8_t (*function2)(void);
} const service_struct_t;
extern service_struct_t service_api ;
service.c:
#include "service.h"
static uint8_t foo(void){
return 13+6;
}
static uint8_t bar(void){
return 7*6;
}
service_struct_t service_api = {
.function1 = foo,
.function2 = bar,
};
I need to stub (to mock, to replace) these functions but I have no right to change that original code. I'm using gcc to compile the unit tests. I've failed to:
use the --wrap option of gcc straight on foo and bar since they are static to source.c :
#include "service.h"
#define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
uint8_t __real_foo(void);
uint8_t __wrap_foo(void){
if(ENABLE_STUB){
return 1;
}else{
return __real_foo();
}
}
/* same for bar */
use the --wrap option of gcc onto the service_api object symbol because it's not a function
#include "service.h"
#define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
uint8_t __real_service_api ;
uint8_t __wrap_service_api = {
.function1 = foo,
.function2 = bar,
}
static uint8_t foo(void){
if(ENABLE_STUB){
return 1;
}else{
return __real_service_api.function1();
}
}
/* same for bar */
simply reassign the service_api member functions since the structure is constant and already assigned.
#include "service.h"
#define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
service_struct_t backup_service_api = {
.function1 = service_api.function1;
.function2 = service_api.function2;
}
service_struct_t stub_service_api = {
.function1 = foo;
.function2 = bar;
}
uint8_t foo(void){
if(ENABLE_STUB){
return 1;
}else{
return __real_foo();
}
}/* same for bar */
void service_poke_stub(bool_t enable_stubs){
if(enable_stubs){
service_api.function1 = stub_service_api.function1
service_api.function2 = stub_service_api.function2
}else{
service_api.function1 = backup_service_api.function1
service_api.function2 = backup_service_api.function2
}
}
thanks already for your help

You can't mock the functions in the structure, as you already found out.
So it depends on what you like to test:
If you want to test whether the structure contains the correct functions, the module service.c is your module-under-test and should be used as is. You need to check the correctness by watching what is done by the functions.
If you want to test that the structure is used correctly, you will mock the whole module. Now you are free to put in it whatever you want.
If your source code does not allow this, the design is bad for testing. This is often the case when the architecture is not done with testability in mind.

Related

how it is that pointer to struct shows the wrong values?

I use ARM-M4 with GCC for ARM (10_2021.10)
I have a problem where a pointer to struct displays the wrong values.
__copy_table_start__ is define in the linker file, I see it's location in the map file and this is how I found it's true value (and the values make sense, they are correct)
Here is my code
#pragma GCC optimize("O0")
static void DataInit(void)
{
typedef struct {
uint32_t const* src;
uint32_t* dest;
uint32_t wlen;
} __copy_table_t;
extern const __copy_table_t __copy_table_start__;
extern const __copy_table_t __copy_table_end__;
extern const __zero_table_t __zero_table_start__;
extern const __zero_table_t __zero_table_end__;
static volatile __copy_table_t const* pTable;
pTable = &__copy_table_start__;
for (; pTable < &__copy_table_end__; ++pTable) {
for(uint32_t i=0u; i<pTable->wlen; ++i) {
pTable->dest[i] = pTable->src[i];
}
}
}
And what I see in the debugger, right after pTable = &__copy_table_start__; is that:
__copy_table_start__.src = 0x14A0D380
__copy_table_start__.dest = 0x00100000
__copy_table_start__.wlen = 0x38A
pTable->src = 0x14A0D380
pTable->dest = 0x14A0D380
pTable->wlen = 0x14A0D380
How can that be?
UPDATE:
I did another experiment, I created another struct variable and a pointer to that variable and get the same results. first time I see this kind of behavior.
const __copy_table_t mine = {(uint32_t const*)0x12345678, (uint32_t *)0x00004545, 0x89890000};
static volatile __copy_table_t const* my_ptr;
my_ptr = &mine;
The result is that my_ptr->src = my_ptr->dest = my_ptr->wlen = 0x12345678
Apparently the problem is with Keil (the IDE).
It displays the wrong values.
When I created 3 new parameters and loaded the data to them:
my_src = (uint32_t)pTable->src;
my_dest = (uint32_t)pTable->dest;
my_len = (uint32_t)pTable->wlen;
Those parameters got the correct values.
What threw me off was that doing a single step in debug skipped the entire for loop (the first one), as if the internal for loop didn't do anything. It actually did what it was supposed to do, but one parameter that was supposed to be reset after that didn't update in the IDE.

Is this a way of defining "global variables" in C?

Is this way of defining a "global variable" valid / a good approach?
While I would like this variable to be used whenever the header file is included to store program states.
/* global.h */
...
typedef struct {
int some_count;
....
} ProgramState;
ProgramState *GetProgramState()
...
/* global.c */
...
#include "global.h"
ProgramState *GetProgramState()
{
static ProgramState *prog_state = NULL;
if (!prog_state) {
prog_state = (ProgramState *) malloc(sizeof(ProgamState));
*prog_state = (ProgamState) {
.some_count = 1
};
}
return prog_state;
}
...
/* main.c */
#include "global.h"
int main(void)
{
GetProgramState()->some_count++;
printf("%d\n", GetProgramState()->some_count);
return 0;
}
While I know this way induced some overheads (while calling the method?), and there are ways like extern (using the extern way requires a specific initialize function).
Please let me know if there are other alternatives, thanks!
This is effectively an accessor. An accessor gives control over how a variable is accessed, allowing checks (e.g. validation) to be performed, and allowing the specific implementation of the variable to be changed. Using accessors is a common and perfectly acceptable programming paradigm.
As you mentioned, the alternative would be to access the variable directly. And while you could initialize it (contrary to what you said), it can only be initialized using a constant expression (e.g. NULL, but not malloc(sizeof(ProgamState))).

How to modify a output pointer for debug purpose?

I have a function like:
typedef struct
{
bool x;
bool y;
bool z;
} myStruct;
static void myFunction(const myStruct *pTomystruct_out)
{
if (pTomystruct_out->x == TRUE)
{
/*Do Something*/
}
}
Now for some debug purpose I want to add debug code to set the pointer parameter always to TRUE.
Within the function before the if statement I want to do something like:
pTomystruct_out.x = TRUE /*This is not the correct way*/
How to do this in the right way?
Thanks!
pTomystruct_out is a pointer, so you have to dereference that for manipulating what is pointed.
You can use * opetator to dereference:
(*pTomystruct_out).x = TRUE;
Also you can use -> operator where A->B means (*A).B:
pTomystruct_out->x = TRUE;
Also, this is not enough because the pointer pTomystruct_out is marked as const.
You can use a cast to non-const pointer for having it allow modifications.
((myStruct*)pTomystruct_out)->x = TRUE;
This is syntactically collect, but it may be dangerous to modify the object that is thought not to be modified. Creating a copy of the object and modifying the copy is safer.
typedef struct
{
bool x;
bool y;
bool z;
} myStruct;
#if 1 /* debug mode */
static void myFunction(const myStruct *pTomystruct_out_arg) /* change argument name */
{
myStruct pTomystruct_debug_temp = *pTomystruct_out_arg; /* make a copy */
myStruct *pTomystruct_out = &pTomystruct_debug_temp; /* declare a variable with original argument name */
pTomystruct_out->x = TRUE; /* modify the copy */
#else
static void myFunction(const myStruct *pTomystruct_out)
{
#endif
if (pTomystruct_out->x == TRUE)
{
/*Do Something*/
}
}
As mentioned in previous answer, the parameter is const, disabling modifications to that parameter. You probably don't want it to be const.
To add debug code, you can make use of macros. You can have a header file contain macros, like seen below:
#define DEBUG
Or:
#define DEBUG 1
Included a header with this macro allows you to write your function as follows:
static void myFunction(const myStruct *pTomystruct_out)
{
#ifdef DEBUG
pTomystruct_out.x = TRUE
#endif
}
If you used the latter macro, #define DEBUG 1 (which I recommend), you can use an if-statement instead:
static void myFunction(const myStruct *pTomystruct_out)
{
#if DEBUG
pTomystruct_out.x = TRUE
#endif
}
I recommend using #define DEBUG 1, because then you don't have to comment out the macro whenever you don't want it. You can just set it to 0.
If you don't want a header file, you can use the -D flag using gcc, like gcc <INPUTFILE> -DDEBUG.

Accessing label address outside of function

I'm writing "threaded interpreter" using computed goto. How do I initialize address lookup table to be visible from different functions without additional runtime cost?
Label address is only visible at same function and static lookup table is initialized by compiler in data section without runtime cost at each call. But it's visible only in same function and I want to have another function to have access to it, for example to cache addresses and save lookups in main interpreter code. I can take pointer to this table and store it somewhere, but it will happen every time function is called, and it will get called frequently. Yes, it's just only one mov, but is there another way?
#include <stdio.h>
static void** table_ptr;
// how do i declare static variable and init it later once?
// Tried this. Generates runtime assigns at each call. Not unexpected
// static void** jumps_addr;
int main()
{
// labels are visible only inside the function
// generates runtime assigns at each call
// jumps_addr = (void* [10]){
// this initializes it in static data section, but name is only visible inside this function
static void* jumps_addr[10] = {
[1] = &&operation_print,
};
// want another way instead of this
table_ptr = jumps_addr;
// not optimize this
volatile int opcode = 1;
goto *jumps_addr[opcode];
return 0;
operation_print:;
printf("hello\n");
return 0;
}
void do_some_preprocessing_work(void){
// want access to jumps_addr table here
// without having to store it somewhere
// [do something with table_ptr]
// this is to prevent optimization to explore what compiler does on godbolt.org
// because it will optimize away table_ptr entirely if not used
volatile i = 1;
i += table_ptr[i];
//actual code here will store labbel addrs into opcode struct to save table lookup at runtime
}
The solution might sound unorthodox, but how about not to use any functions, but only goto.
Like so:
#include <stdio.h>
int main()
{
volatile int opcode;
static void* jumps_addr[10] = {
[0] = &&do_some_preprocessing_work,
[1] = &&operation_print
};
opcode = 0;
goto *jumps_addr[opcode];
return 1;
operation_print:
printf("hello\n");
return 0;
do_some_preprocessing_work:
printf("jumps_addr[%i]\n", ++opcode);
goto *jumps_addr[opcode];
return 1;
}

Value of multiple struct variables is same unintentionally

I have a code that does OOP like Java.
I have separated the interface and the implementation in separate files names demo.h and demo.c.
demo.h
#ifndef DEMO_H
#define DEMO_H
typedef struct {
/*
This is the variable that will be set by setter method
and its value will be extracted by getter method.
This variable must not be directly accessible by the programmer.
*/
int num;
void (* setNum)(int); // This function will set the value of variable "num".
int (* getNum)(); // This function will return the value of variable "num".
} *Demo; // As objects in java are always called by reference.
Demo newDemo(); // This function will create an instance of class(struct here) Demo and return.
/* This is equivalent to:
Demo obj = new Demo();
int java.
I want my users to create instance of this class(struct here) like this:
Demo obj = newDemo();
here in this code.
*/
#endif
And the implementation:
demo.c
#include <stdlib.h>
#include "demo.h"
Demo demo; /* I have created a global variable so that it is accessible
in setNum and getNum functions. */
void setNum(int num) {
demo->num = num; // This is where the global demo is accessed.
}
int getNum(Demo obj) {
return demo->num; // This is where the global demo is accessed.
}
Demo newDemo() {
Demo obj; // This will be the returned object.
obj = (Demo)malloc(sizeof(*obj)); /* Allocating separate memory to
obj each time this function is called. */
/* Setting the function pointer. */
obj->setNum = setNum;
obj->getNum = getNum;
/* As obj is at different memory location every time this function is called,
I am assigning that new location the the global demo variable. So that each variable
of the Demo class(struct here) must have a different object at different memory
location. */
demo = obj;
return obj; // Finally returning the object.
}
This is how I have implemented the main function:
main.c
#include "demo.h"
#include <stdio.h>
int main() {
void displayData(Demo);
Demo obj1 = newDemo();
Demo obj2 = newDemo();
Demo obj3 = newDemo();
obj1->setNum(5);
obj2->setNum(4);
obj3->setNum(12);
displayData(obj1);
displayData(obj2);
displayData(obj3);
return 0;
}
void displayData(Demo obj) {
int num = obj->getNum();
fprintf(stdout, "%d\n", num);
}
On compilation and execution on my mac book pro:
> gcc -c demo.c
> gcc main.c demo.o -o Demo
> ./Demo
The output is:
12
12
12
But the desired output is:
5
4
12
What am I doing wrong?
Please help.
I don't want my users to pass the struct pointer as an argument as:
Demo obj = newDemo();
obj->setName(obj, "Aditya R.Singh"); /* Creating the program this way was successful as my
header file had the declaration as:
typedef struct demo {
int num;
void (* setNum)(struct demo, int); // This is what I don't desire.
void (* getNum)(struct demo); // This is what I don't desire.
} *Demo;
I want to keep it like the way it is in my current
demo.h*/
/* I don't want to pass obj as an argument. All I want to do this is this way. */
obj->setName("Aditya R.Singh");
Is there any way possible to do this and get the desired output?
Please help, thanks!
I have absolutely no idea of c++, but in your code, I think, demo = obj; is the problem. demo is global, right? It will get overwritten with evety call to newDemo().
Side effect : Memory leak.

Resources