diff options
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rw-r--r-- | cmake/Modules/CodeCoverage.cmake | 197 | ||||
-rw-r--r-- | cmake/Modules/GrBuildTypes.cmake | 33 | ||||
-rw-r--r-- | cmake/Modules/GrTest.cmake | 1 | ||||
-rw-r--r-- | gr-digital/lib/additive_scrambler_bb_impl.cc | 41 | ||||
-rwxr-xr-x | gr-digital/python/digital/qa_scrambler.py | 31 |
6 files changed, 295 insertions, 14 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index f85d18c534..a733a8014f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -365,6 +365,12 @@ GR_REGISTER_COMPONENT("testing-support" ENABLE_TESTING CPPUNIT_FOUND ) +if(${CMAKE_BUILD_TYPE} STREQUAL "Coverage") + include(CodeCoverage) + setup_target_for_coverage(coverage "ctest" coverage) +endif() + + ######################################################################## # Setup volk as a subproject ######################################################################## diff --git a/cmake/Modules/CodeCoverage.cmake b/cmake/Modules/CodeCoverage.cmake new file mode 100644 index 0000000000..a0b0ef5269 --- /dev/null +++ b/cmake/Modules/CodeCoverage.cmake @@ -0,0 +1,197 @@ +# Copyright (c) 2012 - 2015, Lars Bilke +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# +# +# 2012-01-31, Lars Bilke +# - Enable Code Coverage +# +# 2013-09-17, Joakim Söderberg +# - Added support for Clang. +# - Some additional usage instructions. +# +# USAGE: + +# 0. (Mac only) If you use Xcode 5.1 make sure to patch geninfo as described here: +# http://stackoverflow.com/a/22404544/80480 +# +# 1. Copy this file into your cmake modules path. +# +# 2. Add the following line to your CMakeLists.txt: +# INCLUDE(CodeCoverage) +# +# 3. Set compiler flags to turn off optimization and enable coverage: +# SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") +# SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") +# +# 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target +# which runs your test executable and produces a lcov code coverage report: +# Example: +# SETUP_TARGET_FOR_COVERAGE( +# my_coverage_target # Name for custom target. +# test_driver # Name of the test driver executable that runs the tests. +# # NOTE! This should always have a ZERO as exit code +# # otherwise the coverage generation will not complete. +# coverage # Name of output directory. +# ) +# +# 4. Build a Debug build: +# cmake -DCMAKE_BUILD_TYPE=Debug .. +# make +# make my_coverage_target +# +# + +# Check prereqs +FIND_PROGRAM( GCOV_PATH gcov ) +FIND_PROGRAM( LCOV_PATH lcov ) +FIND_PROGRAM( GENHTML_PATH genhtml ) +FIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests) + +IF(NOT GCOV_PATH) + MESSAGE(FATAL_ERROR "gcov not found! Aborting...") +ENDIF() # NOT GCOV_PATH + +IF("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + IF("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3) + MESSAGE(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") + ENDIF() +ELSEIF(NOT CMAKE_COMPILER_IS_GNUCXX) + MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") +ENDIF() # CHECK VALID COMPILER + +SET(CMAKE_CXX_FLAGS_COVERAGE + "-g -O0 --coverage -fprofile-arcs -ftest-coverage" + CACHE STRING "Flags used by the C++ compiler during coverage builds." + FORCE ) +SET(CMAKE_C_FLAGS_COVERAGE + "-g -O0 --coverage -fprofile-arcs -ftest-coverage" + CACHE STRING "Flags used by the C compiler during coverage builds." + FORCE ) +SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used for linking binaries during coverage builds." + FORCE ) +SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used by the shared libraries linker during coverage builds." + FORCE ) +MARK_AS_ADVANCED( + CMAKE_CXX_FLAGS_COVERAGE + CMAKE_C_FLAGS_COVERAGE + CMAKE_EXE_LINKER_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) + +IF ( NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "Coverage")) + MESSAGE( WARNING "Code coverage results with an optimized (non-Debug) build may be misleading" ) +ENDIF() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" + + +# Param _targetname The name of new the custom make target +# Param _testrunner The name of the target which runs the tests. +# MUST return ZERO always, even on errors. +# If not, no coverage report will be created! +# Param _outputname lcov output is generated as _outputname.info +# HTML report is generated in _outputname/index.html +# Optional fourth parameter is passed as arguments to _testrunner +# Pass them in list form, e.g.: "-j;2" for -j 2 +FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname) + + IF(NOT LCOV_PATH) + MESSAGE(FATAL_ERROR "lcov not found! Aborting...") + ENDIF() # NOT LCOV_PATH + + IF(NOT GENHTML_PATH) + MESSAGE(FATAL_ERROR "genhtml not found! Aborting...") + ENDIF() # NOT GENHTML_PATH + + SET(coverage_info "${CMAKE_BINARY_DIR}/${_outputname}.info") + SET(coverage_cleaned "${coverage_info}.cleaned") + + SEPARATE_ARGUMENTS(test_command UNIX_COMMAND "${_testrunner}") + + # Setup target + ADD_CUSTOM_TARGET(${_targetname} + + # Cleanup lcov + ${LCOV_PATH} --directory . --zerocounters + + # Run tests + COMMAND ${test_command} ${ARGV3} + + # Capturing lcov counters and generating report + COMMAND ${LCOV_PATH} --directory . --capture --output-file ${coverage_info} + COMMAND ${LCOV_PATH} --remove ${coverage_info} 'tests/*' '/usr/*' --output-file ${coverage_cleaned} + COMMAND ${GENHTML_PATH} -o ${_outputname} ${coverage_cleaned} + COMMAND ${CMAKE_COMMAND} -E remove ${coverage_info} ${coverage_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 ${_targetname} POST_BUILD + COMMAND ; + COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report." + ) + +ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE + +# Param _targetname The name of new the custom make target +# Param _testrunner The name of the target which runs the tests +# Param _outputname cobertura output is generated as _outputname.xml +# Optional fourth parameter is passed as arguments to _testrunner +# Pass them in list form, e.g.: "-j;2" for -j 2 +FUNCTION(SETUP_TARGET_FOR_COVERAGE_COBERTURA _targetname _testrunner _outputname) + + IF(NOT PYTHON_EXECUTABLE) + MESSAGE(FATAL_ERROR "Python not found! Aborting...") + ENDIF() # NOT PYTHON_EXECUTABLE + + IF(NOT GCOVR_PATH) + MESSAGE(FATAL_ERROR "gcovr not found! Aborting...") + ENDIF() # NOT GCOVR_PATH + + ADD_CUSTOM_TARGET(${_targetname} + + # Run tests + ${_testrunner} ${ARGV3} + + # Running gcovr + COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} -e '${CMAKE_SOURCE_DIR}/tests/' -o ${_outputname}.xml + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Running gcovr to produce Cobertura code coverage report." + ) + + # Show info where to find the report + ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD + COMMAND ; + COMMENT "Cobertura code coverage report saved in ${_outputname}.xml." + ) + +ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE_COBERTURA diff --git a/cmake/Modules/GrBuildTypes.cmake b/cmake/Modules/GrBuildTypes.cmake index 34614c9d08..5789d88934 100644 --- a/cmake/Modules/GrBuildTypes.cmake +++ b/cmake/Modules/GrBuildTypes.cmake @@ -38,7 +38,7 @@ set(__INCLUDED_GR_BUILD_TYPES_CMAKE TRUE) # build type below, make sure to add it to this list. list(APPEND AVAIL_BUILDTYPES None Debug Release RelWithDebInfo MinSizeRel - NoOptWithASM O2WithASM O3WithASM + Coverage NoOptWithASM O2WithASM O3WithASM ) ######################################################################## @@ -67,6 +67,37 @@ endfunction(GR_CHECK_BUILD_TYPE) ######################################################################## # For GCC and Clang, we can set a build type: # +# -DCMAKE_BUILD_TYPE=Coverage +# +# This type uses no optimization (-O0), outputs debug symbols (-g) and +# outputs all intermediary files the build system produces, including +# all assembly (.s) files. Look in the build directory for these +# files. +# NOTE: This is not defined on Windows systems. +######################################################################## +if(NOT WIN32) + SET(CMAKE_CXX_FLAGS_COVERAGE "-Wall -pedantic -pthread -g -O0 -fprofile-arcs -ftest-coverage" CACHE STRING + "Flags used by the C++ compiler during Coverage builds." FORCE) + SET(CMAKE_C_FLAGS_COVERAGE "-Wall -pedantic -pthread -g -O0 -fprofile-arcs -ftest-coverage" CACHE STRING + "Flags used by the C compiler during Coverage builds." FORCE) + SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE + "-Wl,--warn-unresolved-symbols,--warn-once" CACHE STRING + "Flags used for linking binaries during Coverage builds." FORCE) + SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE + "-Wl,--warn-unresolved-symbols,--warn-once" CACHE STRING + "Flags used by the shared lib linker during Coverage builds." FORCE) + + MARK_AS_ADVANCED( + CMAKE_CXX_FLAGS_COVERAGE + CMAKE_C_FLAGS_COVERAGE + CMAKE_EXE_LINKER_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_COVERAGE) +endif(NOT WIN32) + + +######################################################################## +# For GCC and Clang, we can set a build type: +# # -DCMAKE_BUILD_TYPE=NoOptWithASM # # This type uses no optimization (-O0), outputs debug symbols (-g) and diff --git a/cmake/Modules/GrTest.cmake b/cmake/Modules/GrTest.cmake index 69df96d4c8..5f90be3326 100644 --- a/cmake/Modules/GrTest.cmake +++ b/cmake/Modules/GrTest.cmake @@ -113,7 +113,6 @@ function(GR_ADD_TEST test_name) execute_process(COMMAND chmod +x ${sh_file}) add_test(${test_name} ${SHELL} ${sh_file}) - endif(UNIX) if(WIN32) diff --git a/gr-digital/lib/additive_scrambler_bb_impl.cc b/gr-digital/lib/additive_scrambler_bb_impl.cc index 58a2455aa5..d1112ee5f4 100644 --- a/gr-digital/lib/additive_scrambler_bb_impl.cc +++ b/gr-digital/lib/additive_scrambler_bb_impl.cc @@ -121,18 +121,35 @@ namespace gr { unsigned char *out = (unsigned char *)output_items[0]; int reset_index = _get_next_reset_index(noutput_items); - for(int i = 0; i < noutput_items; i++) { - unsigned char scramble_byte = 0x00; - for (int k = 0; k < d_bits_per_byte; k++) { - scramble_byte ^= (d_lfsr.next_bit() << k); - } - out[i] = in[i] ^ scramble_byte; - d_bytes++; - if (i == reset_index) { - d_lfsr.reset(); - d_bytes = 0; - reset_index = _get_next_reset_index(noutput_items, reset_index); - } + if (d_count >= 0) { + for(int i = 0; i < noutput_items; i++) { + unsigned char scramble_byte = 0x00; + for (int k = 0; k < d_bits_per_byte; k++) { + scramble_byte ^= (d_lfsr.next_bit() << k); + } + out[i] = in[i] ^ scramble_byte; + d_bytes++; + if (i == reset_index) { + d_lfsr.reset(); + d_bytes = 0; + reset_index = _get_next_reset_index(noutput_items, reset_index); + } + } + } else { + for(int i = 0; i < noutput_items; i++) { + // Reset should occur at/before the item associated with the tag. + if (i == reset_index) { + d_lfsr.reset(); + d_bytes = 0; + reset_index = _get_next_reset_index(noutput_items, reset_index); + } + unsigned char scramble_byte = 0x00; + for (int k = 0; k < d_bits_per_byte; k++) { + scramble_byte ^= (d_lfsr.next_bit() << k); + } + out[i] = in[i] ^ scramble_byte; + d_bytes++; + } } return noutput_items; diff --git a/gr-digital/python/digital/qa_scrambler.py b/gr-digital/python/digital/qa_scrambler.py index 4d35879b1f..522b23245f 100755 --- a/gr-digital/python/digital/qa_scrambler.py +++ b/gr-digital/python/digital/qa_scrambler.py @@ -23,6 +23,17 @@ from gnuradio import gr, gr_unittest, digital, blocks import pmt +# See gr-digital/lib/additive_scrambler_bb_impl.cc for reference. +def additive_scramble_lfsr(mask, seed, reglen, bpb, data): + l = digital.lfsr(mask, seed, reglen) + out = [] + for d in data: + scramble_word = 0 + for i in xrange(0,bpb): + scramble_word ^= l.next_bit() << i + out.append(d ^ scramble_word) + return tuple(out) + class test_scrambler(gr_unittest.TestCase): def setUp(self): @@ -98,5 +109,25 @@ class test_scrambler(gr_unittest.TestCase): self.tb.run() self.assertEqual(src_data, dst.data()) + def test_additive_scrambler_tags_oneway(self): + src_data = range(0, 10) + reset_tag_key = 'reset_lfsr' + reset_tag1 = gr.tag_t() + reset_tag1.key = pmt.string_to_symbol(reset_tag_key) + reset_tag1.offset = 0 + reset_tag2 = gr.tag_t() + reset_tag2.key = pmt.string_to_symbol(reset_tag_key) + reset_tag2.offset = 10 + reset_tag3 = gr.tag_t() + reset_tag3.key = pmt.string_to_symbol(reset_tag_key) + reset_tag3.offset = 20 + src = blocks.vector_source_b(src_data * 3, False, 1, (reset_tag1, reset_tag2, reset_tag3)) + scrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7, 0, 8, reset_tag_key) + dst = blocks.vector_sink_b() + self.tb.connect(src, scrambler, dst) + self.tb.run() + expected_data = additive_scramble_lfsr(0x8a, 0x7f, 7, 8, src_data) + self.assertEqual(expected_data * 3, dst.data()) + if __name__ == '__main__': gr_unittest.run(test_scrambler, "test_scrambler.xml") |