Usage
Command line
Before we integrate it into the build chain of your choice it is a good idea to call it on the command line in order to gather more understanding what it does and what it needs.
Let’s call hammocking without any arguments:
$ python -m hammocking
usage: hammocking [-h] (--symbols SYMBOLS [SYMBOLS ...] | --plink PLINK) --outdir OUTDIR --sources SOURCES [SOURCES ...] [--except EXCLUDES ...]
hammocking: error: the following arguments are required: --outdir/-o, --sources
hammocking needs …
–sources: The list of paths to source files which represent your item-under test. (In classic unittest it is just one)
- Either …
–symbols*: comma seperated list of symbol names which are to mock or
–plink: path to the object file which contains the unresolved symbols to mock
–outdir: An existing directory where to write code files containing mockup code.
–except: if a symbol is found in a header of these directories, it will not be mocked. Use this to exclude symbols from mocking that will be provided by libraries in the linking process. (Defaults to
/usr/includefor system headers)
One compilation unit
We show this scenario for explanation purpose only. The next chapter shows the common way and covers the one compilation unit as well.
In a simple scenario your
Make
1 .SUFFIXES: 2 3 CC := gcc -c 4 LD := gcc 5 6 CC_OPTS := -g 7 LD_OPTS := 8 9 .PHONY: a_test 10 a_test: a_test.exe 11 ./a_test.exe 12 13 a_test.exe: a.c.obj a_test.c.obj mockup.c.obj 14 $(LD) $(LD_OPTS) $(CC_OPTS) -o $@ $^ 15 16 17 -include $(patsubst %.c,%.c.d,$(wildcard *.c)) 18 %.c.obj: %.c 19 $(CC) $(CC_OPTS) -MMD -o $@ $< 20 21 22 23 24 a_test.c.obj: mockup.c 25 26 mockup.c: a.c.obj 27 python -m hammocking --source a.c --plink a.c.obj --style plain_c --outdir . $(CC_OPTS) 28 29 .PHONY: clean 30 clean: 31 rm -rf a_test.exe *.obj *.d mockup.c mockup.h 32
CMake
One or more compilation units
Make
1 .SUFFIXES: 2 3 CC := gcc -c 4 LD := gcc 5 6 CC_OPTS := -g 7 LD_OPTS := 8 9 .PHONY: a_test 10 a_test: a_test.exe 11 ./a_test.exe 12 13 a_test.exe: a_1.c.obj a_2.c.obj a_test.c.obj mockup.c.obj 14 $(LD) $(LD_OPTS) $(CC_OPTS) -o $@ $^ 15 16 17 -include $(patsubst %.c,%.c.d,$(wildcard *.c)) 18 %.c.obj: %.c 19 $(CC) $(CC_OPTS) -MMD -o $@ $< 20 21 a.obj: a_1.c.obj a_2.c.obj 22 $(LD) $(LD_OPTS) -r -nostdlib -o $@ $^ 23 24 a_test.c.obj: mockup.c 25 26 mockup.c: a.obj 27 python -m hammocking --source a_1.c a_2.c --plink a.obj --style plain_c --outdir . $(CC_OPTS) 28 29 .PHONY: clean 30 clean: 31 rm -rf a_test.exe *.obj *.d mockup.c mockup.h 32
CMake
Usage with GoogleTest and GoogleMocks
https://google.github.io/googletest/reference/mocking.html
1 # cmake project definition 2 cmake_minimum_required(VERSION 3.20.0) 3 4 set(CMAKE_C_COMPILER clang CACHE STRING "C Compiler") 5 set(CMAKE_CXX_COMPILER clang++ CACHE STRING "C++ Compiler") 6 set(CMAKE_C_COMPILER clang CACHE STRING "C Compiler") 7 set(CMAKE_CXX_COMPILER clang++ CACHE STRING "C++ Compiler") 8 project(mini_c) 9 10 # GTEST + GMOCK STUFF #################################### 11 # GoogleTest requires at least C++14 12 set(CMAKE_CXX_STANDARD 14) 13 14 include(FetchContent) 15 FetchContent_Declare( 16 googletest 17 GIT_REPOSITORY https://github.com/google/googletest.git 18 GIT_TAG release-1.12.1 19 ) 20 21 if(WIN32) 22 # Prevent overriding the parent project's compiler/linker 23 # settings on Windows 24 set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 25 endif() 26 27 FetchContent_MakeAvailable(googletest) 28 29 include(GoogleTest) 30 31 find_package(Threads REQUIRED) 32 33 enable_testing() 34 # END OF GTEST + GMOCK STUFF ############################# 35 36 set(PROD_SRC b.c) 37 set(MOCK_SRC mockup.cc) 38 set(TEST_SRC b_test.cc) 39 set(PROD_PARTIAL_LINK prod.obj) 40 41 include_directories("includes") 42 43 # One command to mock them all! 44 set(HAMMOCK_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../hammocking) 45 add_custom_command( 46 OUTPUT ${MOCK_SRC} 47 BYPRODUCTS mockup.h 48 WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} 49 COMMAND_EXPAND_LISTS 50 COMMAND python ${HAMMOCK_DIR}/hammocking.py --sources ${PROD_SRC} --plink ${CMAKE_CURRENT_BINARY_DIR}/${PROD_PARTIAL_LINK} --outdir ${CMAKE_CURRENT_BINARY_DIR} "-I$<JOIN:$<TARGET_PROPERTY:prodlib,INCLUDE_DIRECTORIES>,;-I>" 51 DEPENDS 52 ${HAMMOCK_DIR}/hammocking.py 53 ${PROD_PARTIAL_LINK} 54 ) 55 56 add_library(prodlib OBJECT ${PROD_SRC}) 57 58 add_custom_command( 59 OUTPUT ${PROD_PARTIAL_LINK} 60 COMMAND ${CMAKE_CXX_COMPILER} -r -nostdlib -o ${PROD_PARTIAL_LINK} $<TARGET_OBJECTS:prodlib> 61 COMMAND_EXPAND_LISTS 62 VERBATIM 63 DEPENDS $<TARGET_OBJECTS:prodlib> 64 ) 65 66 add_executable( 67 ${PROJECT_NAME} 68 ${MOCK_SRC} 69 ${TEST_SRC} 70 ) 71 72 target_include_directories( 73 ${PROJECT_NAME} 74 PRIVATE 75 ${CMAKE_CURRENT_BINARY_DIR} 76 ${CMAKE_CURRENT_LIST_DIR} 77 ) 78 79 target_link_libraries( 80 ${PROJECT_NAME} 81 prodlib 82 GTest::gtest_main 83 GTest::gmock_main 84 Threads::Threads 85 ) 86 87 gtest_discover_tests(${PROJECT_NAME}) 88 89 add_custom_command( 90 TARGET ${PROJECT_NAME} 91 POST_BUILD 92 COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure 93 )