0

I'm trying to use cmocka to test a private function in a module. The method under testing also calls other private methods in that same module.

/** @file foo.c */
void foo_private();

void foo_under_test() {
    foo_private();
}

void foo_private() {
printf("REAL FOO_PRIVATE\n");
}

That module is archived into a library, eg libMyFoo.a, used by the cmocka tests.

The normal mechanism to test a method is to wrap the sub methods with a replacement method using the --wrap=foo_private flag in the test linker, and then writing a wrapped method replacement in the unit test.

void __wrap_foo_private() {
printf("WRAPPED FOO_PRIVATE\n");
}

However because both methods are in the same module, this is giving me difficulties. For the purpose of testing, I can change how I compile, archive and link both the library and the tests, but I am not at liberty to change the source code under test.

I have tried to weaken the foo_private symbol objcopy foo.o -W _foo_private foo-weak.o and, when that didn't work I tried to remove the symbol entirely using objcopy foo.o -N _foo_private foo-removed.o.

I can see the symbol in the original version,

$ nm foo.o | grep foo_private
00000138 d ___gcov_.foo_private
00000048 b ___gcov0.foo_private
00001413 T _foo_private

I can see that the symbol is weekend in the weak version:

$ nm foo-weak.o | grep foo_private
00000138 d __gcov_.foo_private
00000048 b __gcov0.foo_private
00001413 W _foo_private

and missing in the removed version:

$ nm foo-removed.o | grep foo_private
00000138 d ___gcov_.foo_private
00000048 b ___gcov0.foo_private

However, no matter which one I use, my test execution always outputs.

REAL FOO_PRIVATE

When testing the removed object, I created a local (to the unit test) version of foo_private.

Is there something I am missing with objcopy? Wrong symbol name? Is foo_private() being statically compiled into foo_under_test()? I have optimization set to none (-O0).

For completeness, I originally tried doing this against the archived library, with similar effects, eg objcopy libMyFoo.a -N _foo_private libMyFoo-removed.a. When that didn't work, I went down to the module level, attempting to weaken and remove the symbols there, before adding it back into a library containing just the module in question.

Yes, this question is similar to the links below, but as you can see I've tried using objcopy to weaken and even remove the symbol in question, but the original foo_private() method is still being called.

GNU gcc/ld - wrapping a call to symbol with caller and callee defined in the same object file

Limiting the scope of global symbols from linked objects

gnac
  • 1,573
  • 15
  • 17
  • Note that I also checked the compiled unit test executable for the foo_private symbol. For the unit test compiled against the weakened foo_private library, it showed as weak. The symbol wasn't there, as expected, in the executable compiled against the removed library. – gnac Oct 27 '21 at 22:24
  • Please don't add new information in a comment, [edit] your question instead. -- It is generally difficult to impossible to mock a private function, because compilers resolve a caller's reference immediately. -- A unit test should never be based on mocks of private functions. Look at the unit-to-test as a black box, you only use its public interface. -- Did you look into the generated assembly/object code to make sure that the call is not resolved at compile time? – the busybee Oct 28 '21 at 06:40
  • Some tests with MinGW-w64 8.1.0 revealed that the compiler already resolves the call, even with -O0. I see no way to intercept such a call. – the busybee Oct 29 '21 at 13:21

0 Answers0