Skip to content

Commit

Permalink
Aligned cmake built system with recommendations in googletest docs (#415
Browse files Browse the repository at this point in the history
)

* Aligned cmake built system with recommendations in googletest docs

* Copied etc/vzlogger.conf to build directory for testing. Path in test is relative to build dir

* Changed working directory of test to build dir

* Added cmake command to copy missing images for OCR Test to build dir

* Added constructor accepting a std::string as value to class Options

* * Made tests independent from working directory upon execution
* Fixed some 'dirty hacks' by moving object dependencies from test
sources to cmake script

* Changed design to collect all variable path names in a single header
file in tests/include

* Added missing source file

* Fixed some build errors caused by missing source files.

* * Fixed missing path delimiter in path generator for OCR sample files
* renamed test helper pathTo to ocrTestImage

* Fixed coding style with clang-format

* Beautified CMakeLists files (with tabs\!)
  • Loading branch information
claashk authored and mbehr1 committed Jan 18, 2020
1 parent 8e9d00b commit 8d06176
Show file tree
Hide file tree
Showing 13 changed files with 222 additions and 213 deletions.
38 changes: 36 additions & 2 deletions CMakeLists.txt
Expand Up @@ -209,14 +209,48 @@ include(CTest)
enable_testing()

if(GIT_FOUND AND ENABLE_GOOGLEMOCK)
add_subdirectory(gmock)
#add_subdirectory(gmock)

# Download and unpack googletest at configure time
configure_file(gtest/CMakeLists.txt.in gtest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/gtest-download )
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/gtest-download )
if(result)
message(FATAL_ERROR "Build step for googletest failed: ${result}")
endif()

# Prevent overriding the parent project's compiler/linker
# settings on Windows
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)

# Add googletest directly to our build. This defines
# the gtest and gtest_main targets.
add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/gtest-src
${CMAKE_CURRENT_BINARY_DIR}/gtest-build
EXCLUDE_FROM_ALL)

# The gtest/gtest_main targets carry header search path
# dependencies automatically when using CMake 2.8.11 or
# later. Otherwise we have to add them here ourselves.
if (CMAKE_VERSION VERSION_LESS 2.8.11)
include_directories("${gtest_SOURCE_DIR}/include")
include_directories("${gmock_SOURCE_DIR}/include")
endif()

add_subdirectory(tests)
else()
if (ENABLE_GOOGLEMOCK)
message(WARNING "googletest based unit tests disabled due to missing git. Please install git.")
endif(ENABLE_GOOGLEMOCK)
endif()
add_test(NAME vzlogger_unit_tests COMMAND vzlogger_unit_tests WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
add_test(NAME vzlogger_unit_tests COMMAND vzlogger_unit_tests)

### print some output for the user
message("")
Expand Down
24 changes: 0 additions & 24 deletions gmock/CMakeLists.txt

This file was deleted.

21 changes: 0 additions & 21 deletions gtest/CMakeLists.txt

This file was deleted.

15 changes: 15 additions & 0 deletions gtest/CMakeLists.txt.in
@@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 2.8.2)

project(gtest-download NONE)

include(ExternalProject)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG master
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/gtest-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/gtest-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
1 change: 1 addition & 0 deletions include/Options.hpp
Expand Up @@ -21,6 +21,7 @@ class Option {

Option(const char *key, struct json_object *jso);
Option(const char *key, const char *value);
Option(const char *pKey, const std::string &pValue);
Option(const char *key, int value);
Option(const char *key, double value);
Option(const char *key, bool value);
Expand Down
3 changes: 3 additions & 0 deletions src/Options.cpp
Expand Up @@ -80,6 +80,9 @@ Option::Option(const Option &o) : _key(o._key), _type(o._type), _value_string(o.
Option::Option(const char *pKey, const char *pValue)
: _key(pKey), _type(type_string), _value_string(pValue) {}

Option::Option(const char *pKey, const std::string &pValue)
: _key(pKey), _type(type_string), _value_string(pValue) {}

Option::Option(const char *pKey, int pValue) : _key(pKey) {
value.integer = pValue;
_type = type_int;
Expand Down
174 changes: 88 additions & 86 deletions tests/CMakeLists.txt
@@ -1,106 +1,108 @@
include_directories(
${GMOCK_INCLUDE_DIRS}
${GTEST_INCLUDE_DIRS}
)

# all *.cpp files here will be used.
file(GLOB test_sources *.cpp)
if(NOT SML_FOUND)
list(REMOVE_ITEM test_sources ${CMAKE_CURRENT_SOURCE_DIR}/MeterSML.cpp)
endif(NOT SML_FOUND)

# remove meterOCR.cpp if not defined
if( NOT OCR_SUPPORT )
list(REMOVE_ITEM test_sources ${CMAKE_CURRENT_SOURCE_DIR}/ut_MeterOCR.cpp)
endif( NOT OCR_SUPPORT)

if( NOT OCR_TESSERACT_SUPPORT )
list(REMOVE_ITEM test_sources ${CMAKE_CURRENT_SOURCE_DIR}/ut_MeterOCRTesseract.cpp)
endif( NOT OCR_TESSERACT_SUPPORT)


if( NOT ENABLE_SML )
list(REMOVE_ITEM test_sources ${CMAKE_CURRENT_SOURCE_DIR}/MeterSML.cpp)
endif( NOT ENABLE_SML)

if(ENABLE_MQTT)
set(MQTT_SOURCES ../src/mqtt.cpp)
else(ENABLE_MQTT)
set(MQTT_SOURCES "")
endif(ENABLE_MQTT)

if( OMS_SUPPORT )
set(oms_sources ../src/protocols/MeterOMS.cpp)
elseif( OMS_SUPPORT )
set(oms_sources "")
endif( OMS_SUPPORT )

add_executable(vzlogger_unit_tests ${test_sources} ../src/CurlSessionProvider.cpp ../src/protocols/MeterW1therm.cpp ${oms_sources} ${MQTT_SOURCES})

add_dependencies(vzlogger_unit_tests googlemock)
# add required source files
list(APPEND test_sources
../src/Buffer.cpp
../src/Channel.cpp
../src/Config_Options.cpp
../src/api/Volkszaehler.cpp
../src/CurlSessionProvider.cpp
../src/protocols/MeterW1therm.cpp
)

target_link_libraries(vzlogger_unit_tests
${GTEST_LIBS_DIR}/libgtest.a
${GMOCK_LIBS_DIR}/libgmock.a
set(test_libraries
gtest
gmock
${JSON_LIBRARY}
${LIBUUID}
dl
pthread)
target_link_libraries(vzlogger_unit_tests ${CURL_STATIC_LIBRARIES} ${CURL_LIBRARIES} unistring ${GNUTLS_LIBRARIES} ${OCR_LIBRARIES})

if( OMS_SUPPORT )
target_link_libraries(vzlogger_unit_tests ${MBUS_LIBRARY} ${OPENSSL_LIBRARIES})
endif( OMS_SUPPORT )
pthread
${CURL_STATIC_LIBRARIES}
${CURL_LIBRARIES}
unistring
${GNUTLS_LIBRARIES}
${OCR_LIBRARIES}
)

if(SML_FOUND)
target_link_libraries(vzlogger_unit_tests ${SML_LIBRARY})
endif(SML_FOUND)
if(SML_FOUND AND ENABLE_SML)
list(APPEND test_sources ../src/protocols/MeterSML.cpp)
list(APPEND test_libraries ${SML_LIBRARY})
else(SML_FOUND AND ENABLE_SML)
list(REMOVE_ITEM test_sources ${CMAKE_CURRENT_SOURCE_DIR}/MeterSML.cpp)
endif(SML_FOUND AND ENABLE_SML)

if(OCR_SUPPORT)
list(APPEND test_sources ../src/protocols/MeterOCR.cpp)
else(OCR_SUPPORT)
list(REMOVE_ITEM test_sources ${CMAKE_CURRENT_SOURCE_DIR}/ut_MeterOCR.cpp)
endif(OCR_SUPPORT)

if(OCR_TESSERACT_SUPPORT)
list(APPEND test_sources ../src/protocols/MeterOCR.cpp)
else(OCR_TESSERACT_SUPPORT)
list(REMOVE_ITEM test_sources
${CMAKE_CURRENT_SOURCE_DIR}/ut_MeterOCRTesseract.cpp)
endif(OCR_TESSERACT_SUPPORT)

if(ENABLE_MQTT)
target_link_libraries(vzlogger_unit_tests ${MQTT_LIBRARY})
list(APPEND test_sources ../src/mqtt.cpp)
list(APPEND test_libraries ${MQTT_LIBRARY})
endif(ENABLE_MQTT)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")

add_subdirectory(mocks)

FIND_PROGRAM( GCOV_PATH gcov )
FIND_PROGRAM( LCOV_PATH lcov )
FIND_PROGRAM( GENHTML_PATH genhtml )

IF(GCOV_PATH AND LCOV_PATH AND GENHTML_PATH)
MESSAGE("gcov found. Adding target test_coverage ...")
if(OMS_SUPPORT)
list(APPEND test_sources ../src/protocols/MeterOMS.cpp)
list(APPEND test_libraries ${MBUS_LIBRARY} ${OPENSSL_LIBRARIES})
endif(OMS_SUPPORT)

# Setup target for coverage
# we need to add each single test binary into the command list
add_executable(vzlogger_unit_tests ${test_sources})
target_link_libraries(vzlogger_unit_tests ${test_libraries})

ADD_CUSTOM_TARGET(test_coverage

# Cleanup lcov
${LCOV_PATH} --rc lcov_branch_coverage=1 --directory . --zerocounters

# Run tests
COMMAND vzlogger_unit_tests
COMMAND mock_metermap
COMMAND mock_MeterW1therm
COMMAND mock_MeterOMS
COMMAND mock_MeterS0
configure_file(include/test_config.hpp.in include/test_config.hpp)
target_include_directories(vzlogger_unit_tests
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include
)

# Capturing lcov counters and generating report
COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --directory . --capture --output-file coverage.info
COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --remove coverage.info 'tests/*' '/usr/*' --output-file coverage.info.cleaned
COMMAND ${GENHTML_PATH} --rc lcov_branch_coverage=1 -o coverage coverage.info.cleaned
COMMAND ${CMAKE_COMMAND} -E remove coverage.info coverage.info.cleaned

WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")

# Show info where to find the report
ADD_CUSTOM_COMMAND(TARGET test_coverage POST_BUILD
COMMAND ;
COMMENT "Open ./coverage/index.html in your browser to view the coverage report."
)
add_subdirectory(mocks)

ENDIF() # NOT GCOV_PATH
FIND_PROGRAM(GCOV_PATH gcov)
FIND_PROGRAM(LCOV_PATH lcov)
FIND_PROGRAM(GENHTML_PATH genhtml)

IF(GCOV_PATH AND LCOV_PATH AND GENHTML_PATH)
MESSAGE("gcov found. Adding target test_coverage ...")

# Setup target for coverage
# we need to add each single test binary into the command list

ADD_CUSTOM_TARGET(test_coverage
# Cleanup lcov
${LCOV_PATH} --rc lcov_branch_coverage=1 --directory . --zerocounters
# Run tests
COMMAND vzlogger_unit_tests
COMMAND mock_metermap
COMMAND mock_MeterW1therm
COMMAND mock_MeterOMS
COMMAND mock_MeterS0

# Capturing lcov counters and generating report
COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --directory . --capture --output-file coverage.info
COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --remove coverage.info 'tests/*' '/usr/*' --output-file coverage.info.cleaned
COMMAND ${GENHTML_PATH} --rc lcov_branch_coverage=1 -o coverage coverage.info.cleaned
COMMAND ${CMAKE_COMMAND} -E remove coverage.info coverage.info.cleaned

WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
)

# Show info where to find the report
ADD_CUSTOM_COMMAND(TARGET test_coverage POST_BUILD
COMMAND ;
COMMENT "Open ./coverage/index.html in your browser to view the coverage report."
)

ENDIF(GCOV_PATH AND LCOV_PATH AND GENHTML_PATH)
16 changes: 6 additions & 10 deletions tests/MeterSML.cpp
@@ -1,20 +1,16 @@
#include <cmath>
#include <fcntl.h>
#include <stdio.h>

#include "Options.hpp"
#include "protocols/MeterSML.hpp"
#include "gtest/gtest.h"

// this is a dirty hack. we should think about better ways/rules to link against the
// test objects.
// e.g. single files in the tests directory that just include the real file. This way one
// will avoid multiple includes of the same file in a different test case
// (or linking against the real file from the CMakeLists.txt)

#include "../src/protocols/MeterSML.cpp"
#include <Options.hpp>
#include <protocols/MeterSML.hpp>

int writes_hex(int fd, const char *str); // impl. in MeterD0.cpp

TEST(MeterSML, EMH_basic) {
using std::fabs;

char tempfilename[L_tmpnam + 1];
ASSERT_NE(tmpnam_r(tempfilename), (char *)0);
std::list<Option> options;
Expand Down
15 changes: 15 additions & 0 deletions tests/include/test_config.hpp.in
@@ -0,0 +1,15 @@
#ifndef TEST_CONFIG_HPP
#define TEST_CONFIG_HPP

#include<string>

inline std::string ocrTestImage(const char* file) {
return std::string("@CMAKE_SOURCE_DIR@/tests/meterOCR/") + file;
}

inline constexpr const char* config_file() {
return "@CMAKE_SOURCE_DIR@/etc/vzlogger.conf";
}


#endif // TEST_CONFIG_HPP

0 comments on commit 8d06176

Please sign in to comment.