Hey There,
Ceedling is a really cool test framework, and we're trying to get started with it. Unfortunately, our particular use-case is causing headaches here and I was hoping someone might be able to advise. It seems like this should be a simple issue to work around, but due to the given constraints I wonder if this falls outside of Ceedling's scope. We're new to Ceedling so were wondering what some experienced devs made of the situation. So here goes:
Due to the nature of our use-case we are working with the following constraints:
- Functions we make should avoid using parameters and return values is possible
- Global variables we use are directly addressed in memory and start life as a uint representing the physical address
What this looks like architecturally is that we have a bunch of <void function()> type functions that use directly addressed global variables to pass data around. A header file containing our addresses and defines is included by everything that needs them, which happens to be almost all of our other files. We were able to get tests working well enough by creating a test header file that replaces the addresses with properly typed pointers. This worked fine up until our most recent refactor. Because our variables are directly addressed in this way, an obnoxious amount of casting has to be done before we can do meaningful work with them, making the readability and maintainability of the code suffer.
To fix this, we decided to make a set of inline functions that are effectively getters and setters for each datatype. These just do the casting for us and clean up the code in the process. They are also naturally included by just about everything else in the codebase. Unfortunately, this wreaked havoc on our Ceedling tests.
The initial problem without any changes is that the those inline function included by the functions under test throw undefined reference errors when linking under Ceedling. The ideal solution, if it exists, is to totally ignore these inline functions in a way which just allows them to run as normal without failing tests. Preferably, this would be done in a way that limits the amount of extra code we'd need to maintain.
Things I've Tried So Far:
- Including the file in different places. The test itself, the test globals file, the project.yaml includes tag.
-> No change in the undefined references issue
- Explicitly defining the "exclude" tag for inline functions
-> No change in the undefined references issue
- Splitting the function declarations and definitions by creating a .c file to go with the header.
-> This allowed Ceedling to see the functions, but it would oddly still not find their definitions when declared as inline. If we take inline out of the declaration, it treats them as regular included functions. Tests run, but are failed due to expects.
- Do the above, create a set of stubs that duplicate the functionality of the functions, set these up as callbacks for the function mocks, and then ignore them all
-> This probably crosses the line in terms of the amount of extra code we'd want to maintain for this relatively small application, but was worth a shot anyways. Again, tests ran but failed due to a lack of expects. Tried putting these calls in different orders so that it might pick up the ignores, but had the same issue.
One of these functions looks like this:
inline void set_extern_uint(unsigned int extern_ptr, unsigned int extern_val)
{
*(unsigned int*)extern_ptr = extern_val;
}
Any ideas? Am I misunderstanding something fundamental here? Is this something we can't work around with Ceedling?