exploding fake generator

194 views
Skip to first unread message

James Grenning

unread,
Sep 5, 2019, 12:11:15 AM9/5/19
to cpputest

Hi All


You may find my script helpful if you need to add tests to legacy C and C++. It generates exploding fakes from C and C++ linker errors. An exploding fake is a test stub, that if executed, fails the test run. It is helpful to quickly resolve linker errors so you can incrementally write more meaningful tests.


https://github.com/jwgrenning/gen-xfakes


The generated C fakes come ready to compile. The generated C++ fakes will require some editing but should be a time saver.



If any of you could try it, I'd appreciate any feedback.  Right now it only supports gcc/g++.  I plan on adding clang and VS.


Cheers, James


Dean Ter Haar

unread,
Jan 10, 2020, 12:31:30 PM1/10/20
to cpputest
Hi James,
  I tried the gen-xfakes script on the following output from gcc/g++ :

DeanTerhaar@GRR-DEAN-TH-W10 /c/MyProducts/SAM4S/firmware/test/CppUTest
$ gcc --version
gcc.exe (MinGW.org GCC-6.3.0-1) 6.3.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

DeanTerhaar@GRR-DEAN-TH-W10 /c/MyProducts/SAM4S/firmware/test/CppUTest
$ make all
compiling AllTests.cpp
compiling App_MainTest.cpp
compiling BoardTest.cpp
compiling App_Main.c
compiling main.c
compiling board.c
compiling piod.c
Building archive test-lib/libsam4.a
a - test-obj/1/2/../../dev/code/app/App_Main.o
a - test-obj/1/2/../../dev/code/app/main.o
a - test-obj/1/2/../../dev/code/board/board.o
a - test-obj/1/2/../../dev/code/device/devd/piod.o
Linking sam4_tests
test-lib/libsam4.a(piod.o): In function `piod_read':
c:\MyProducts\SAM4S\firmware\test\CppUTest/../../dev/code/device/devd/piod.c:189: undefined reference to `piop_read'
test-lib/libsam4.a(piod.o): In function `piod_write':
c:\MyProducts\SAM4S\firmware\test\CppUTest/../../dev/code/device/devd/piod.c:244: undefined reference to `piop_write'
c:\MyProducts\SAM4S\firmware\test\CppUTest/../../dev/code/device/devd/piod.c:251: undefined reference to `piop_write'
c:\MyProducts\SAM4S\firmware\test\CppUTest/../../dev/code/device/devd/piod.c:252: undefined reference to `piop_write'
collect2.exe: error: ld returned 1 exit status
make: *** [sam4_tests] Error 1

Then, using

DeanTerhaar@GRR-DEAN-TH-W10 /c/MyProducts/SAM4S/firmware/test/CppUTest
$ make all 2>build-output.txt
Linking sam4_tests
DeanTerhaar@GRR-DEAN-TH-W10 /c/MyProducts/SAM4S/firmware/test/CppUTest
$ gen-xfakes.sh build-output.txt piop


It produced the following stub file:

/*
    File: piop-c.c From: build-output.txt

    Generated file to help to quickly stub C-linkage unresolved external references

    * When EXPLODING_FAKE_FOR is executed, a message is printed and the test run is existed
    * You could customize EXPLODING_FAKE_FOR to only fail the test
    * Add this file to your test build.
    * Do not include the header files for the referenced functions. The C-linker does not care.

    Note: a EXPLODING_FAKE_FOR() is generated for global variables too.
    * They will explode upon write :-)
    * You might want to resolve these a different way.

*/

#include <stdio.h>
#include <stdlib.h>

#define BOOM_MESSAGE printf("BOOM! time to write a better fake for %s\n", __func__)
#define EXPLODING_FAKE_FOR(f) void f(void); void f(void) { BOOM_MESSAGE; exit(1); }
#define NULL_VOID_FAKE_FOR(f) void f(void); void f(void) {}
#define NULL_VALUE_FAKE_FOR(value_type, f, result) value_type f(void); value_type f(void) { return result; }


EXPLODING_FAKE_FOR(c:\MyProducts\SAM4S\firmware\test\CppUTest/../../dev/code/device/devd/piod.c:189: undefined reference to `piop_read)
EXPLODING_FAKE_FOR(c:\MyProducts\SAM4S\firmware\test\CppUTest/../../dev/code/device/devd/piod.c:244: undefined reference to `piop_write)
EXPLODING_FAKE_FOR(c:\MyProducts\SAM4S\firmware\test\CppUTest/../../dev/code/device/devd/piod.c:251: undefined reference to `piop_write)
EXPLODING_FAKE_FOR(c:\MyProducts\SAM4S\firmware\test\CppUTest/../../dev/code/device/devd/piod.c:252: undefined reference to `piop_write)

The prototypes for piop_read and piop_write are as follows:

ssize_t piop_read   (void *pPort, uint32_t *Value, bool_t bReadPins);
ssize_t piop_write  (void *pPort, uint32_t Value, bool_t bSetPins);

So I modified EXPLODING_FAKE_FOR and created EXPLODING_FAKE2_FOR to satisfy the linker:


/*
    File: piop-c.c From: build-output.txt

    Generated file to help to quickly stub C-linkage unresolved external references

    * When EXPLODING_FAKE_FOR is executed, a message is printed and the test run is existed
    * You could customize EXPLODING_FAKE_FOR to only fail the test
    * Add this file to your test build.
    * Do not include the header files for the referenced functions. The C-linker does not care.

    Note: a EXPLODING_FAKE_FOR() is generated for global variables too.
    * They will explode upon write :-)
    * You might want to resolve these a different way.

*/

#include <stdio.h>
#include <stdlib.h>

#define BOOM_MESSAGE printf("BOOM! time to write a better fake for %s\n", __func__)
#define EXPLODING_FAKE_FOR(f) ssize_t f(void *, uint32_t *, bool_t); ssize_t f(void *p1, uint32_t *p2, bool_t p3) { BOOM_MESSAGE; exit(1); }
#define EXPLODING_FAKE2_FOR(f) ssize_t f(void *, uint32_t, bool_t); ssize_t f(void *p1, uint32_t p2, bool_t p3) { BOOM_MESSAGE; exit(1); }
#define NULL_VOID_FAKE_FOR(f) void f(void); void f(void) {}
#define NULL_VALUE_FAKE_FOR(value_type, f, result) value_type f(void); value_type f(void) { return result; }

EXPLODING_FAKE_FOR(piop_read)
EXPLODING_FAKE2_FOR(piop_write)

I then included piop-c.c into my test file (BoardTest.cpp).

It did compile, link, and run:

$ make all
compiling BoardTest.cpp
Linking sam4_tests
Running sam4_tests
Hello World!
..
OK (2 tests, 2 ran, 1 checks, 0 ignored, 0 filtered out, 0 ms)

But I'm thinking that I'm probably not using the script quite as you had intended.  Comments? Advice?

Thanks,
-dean

James Grenning

unread,
Jan 11, 2020, 9:53:45 AM1/11/20
to cpputest

Hi Dean

Thanks for the report. Look like I need to modify the regex to handle that linker output. Thanks for the details!

James


James Grenning - Author of TDD for Embedded C - wingman-sw.com/tddec
wingman-sw.com
wingman-sw.com/blog
twitter.com/jwgrenning
facebook.com/wingman.sw
wingman software

--
You received this message because you are subscribed to the Google Groups "cpputest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cpputest+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cpputest/4481c30e-1e0a-441e-a04c-dce2fb3b2c54%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages