1

I need to unit test a c file/module and the file contains:

/* Import the _x symbol from assem.S */
extern void _x;

The variable is later used in that file as:

#define WHAT_EVER (int)&_x

The deceleration in the assembler file is:

.global _x
.type _x, @function
_x:

I learned here that GCC is OK with this declaration. However I learned here I can't simply declare:

void _x;

as my stub, because that makes _x an incomplete type. Actually the linker will complain error: storage size of ‘_x’ isn’t known and the linker is right.

But if I declare:

int _x;

The compiler gives me error: conflicting types for ‘_x’ and that is also true.

The target of the software is not the same as the host I do my unit testing on so I can't include the assem.S file (it wouldn't compile and/or run on my host).

Does anyone know of a way to stub this variable _x?

GCC 5.3.1 ; std=gnu99 ; c code

Community
  • 1
  • 1
Robert
  • 37
  • 3
  • 1
    How is `x` defined in the assembler file? If it's a four-byte integer (using e.g. `dd`) then you can declare it as `extern int32_t _x` – Some programmer dude Mar 06 '16 at 16:09
  • @Joachim the declared in the assembler file is added to the question. – Robert Mar 06 '16 at 20:20
  • @Joachim `extern int32_t _x` doesn't work same result as `int _x` **conflicting types for _x** – Robert Mar 06 '16 at 20:27
  • More questions: a) How is the "WHAT_EVER" used, or, maybe more important, why do you have to 'stub' the value? Just to make it compile, or do you need control of the value in your tests? b) Do you have the option to modify the file you are about to test? – Dirk Herrmann Mar 06 '16 at 21:20
  • @Dirk WHAT_EVER is used as `struct.array[number] = WHAT_EVER;` it looks like some initialization of the processor. At the moment I'll be happy if I get it compiled but ideally I need to control the value. b) at the moment I'll say NO but if that means no unit test I'll have to re-evaluate my answer. – Robert Mar 06 '16 at 22:40
  • Then you declare/define `_x` in multiple places, and with different types. ***Read the error messages!*** They contain file-names and line-numbers, telling you exactly where the "conflicts" are. – Some programmer dude Mar 07 '16 at 02:47

1 Answers1

0

If you have the option to modify the file in which _x is referenced, you should extract the access to this symbol to a file of its own. First, I will explain how you can do it, and, second, why you should do it.

How to extract it? In the existing file under test, you can replace all accesses to the symbol by calls to access functions. That is, instead of using the value of macro WHAT_EVER for reading, you call get_what_ever(). If you use the symbol to modifiy the address, you call set_what_ever(value). These getter and setter functions are implemented in a separate file (let's call it, for example, interface_to_assembly.c). The declarations are put in a header file interface_to_assembly.h. Now, for your target system, you compile and link the modified file and interface_to_assembly.c. For your test executable, you create a substitute implementation for interface_to_assembly.c, maybe interface_to_assembly_double.c. These substitute implementations could be dummys, stubs, spys, mocks or whatever you need for your tests.

Why is this separation recommendable? First, it removes the tight coupling between the code you want to test from the assembly level, and, potentially, the hardware. Second, it replaces an access to a global variable with a much better controllable function interface. Note, however, that the tiny piece of software in file interface_to_assembly.c will still not be better testable than before (that is, it will be a candidate for integration testing on the target system). However, for the remaining code (which will likely be the majority), you have much improved testability: Extracting the variable access and replacing it by functions makes it possible to compile the code without any assembly level code. It allows to control every single value access. For example, it becomes possible to create a test setup such that consecutive calls to the getter deliver different values (which is important if you want to simulate concurrent activities of a hardware device).

Dirk Herrmann
  • 5,550
  • 1
  • 21
  • 47
  • Thanks. I was hoping to avoid changing the file under test due to the fact it is a hassle to get it changed (it's not my own). So if there is absolutely no other way I'll suggest your advice. – Robert Mar 07 '16 at 16:14