diff --git a/UNITTESTS/CMakeLists.txt b/UNITTESTS/CMakeLists.txt index e9dfb7b9d20..18dc8af0472 100644 --- a/UNITTESTS/CMakeLists.txt +++ b/UNITTESTS/CMakeLists.txt @@ -82,6 +82,10 @@ if (COVERAGE) endif(COVERAGE) +if (VALGRIND) + find_program(MEMORYCHECK_COMMAND valgrind) +endif(VALGRIND) + #################### # UNIT TESTS #################### @@ -196,6 +200,7 @@ foreach(testfile ${unittest-file-list}) if (unittest-test-sources) # Create the executable. add_executable(${TEST_SUITE_NAME} ${unittest-test-sources}) + target_include_directories(${TEST_SUITE_NAME} PRIVATE ${unittest-includes}) target_compile_options(${TEST_SUITE_NAME} PRIVATE diff --git a/UNITTESTS/mbed_unittest.py b/UNITTESTS/mbed_unittest.py index 627c58ed0ec..7a3279fb807 100755 --- a/UNITTESTS/mbed_unittest.py +++ b/UNITTESTS/mbed_unittest.py @@ -76,13 +76,15 @@ def _mbed_unittest_test(options, cwd, pwd): tool.create_makefiles(path_to_src=src_path, generator=options.cmake_generator, coverage_output_type=options.coverage, - debug=options.debug_build) + debug=options.debug_build, + valgrind=options.valgrind) # Build tests tool.build_tests() if options.run_only: - tool.run_tests(filter_regex=options.test_regex) + tool.run_tests(filter_regex=options.test_regex, + valgrind=options.valgrind) # If code coverage generation: if options.coverage: diff --git a/UNITTESTS/moduletests/storage/blockdevice/SlicingBlockDevice/moduletest.cpp b/UNITTESTS/moduletests/storage/blockdevice/SlicingBlockDevice/moduletest.cpp index 7a96d93378d..5a1f4f9b444 100644 --- a/UNITTESTS/moduletests/storage/blockdevice/SlicingBlockDevice/moduletest.cpp +++ b/UNITTESTS/moduletests/storage/blockdevice/SlicingBlockDevice/moduletest.cpp @@ -120,6 +120,8 @@ TEST_F(SlicingBlockModuleTest, slice_in_middle) EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE)); bd.read(buf, BLOCK_SIZE * 3, BLOCK_SIZE); EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE)); + + delete[] program; } TEST_F(SlicingBlockModuleTest, slice_at_the_end) @@ -143,6 +145,8 @@ TEST_F(SlicingBlockModuleTest, slice_at_the_end) //Verify that blocks before and after the slicing blocks are not touched bd.read(buf, BLOCK_SIZE * 7, BLOCK_SIZE); EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE)); + + delete[] program; } TEST_F(SlicingBlockModuleTest, over_write) @@ -163,6 +167,8 @@ TEST_F(SlicingBlockModuleTest, over_write) //Program a test value to address that is one pass the device size EXPECT_EQ(slice.program(program, 2 * BLOCK_SIZE, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR); + + delete[] buf; delete[] program; } diff --git a/UNITTESTS/unit_test/get_tools.py b/UNITTESTS/unit_test/get_tools.py index 35887052cc6..6cbd94eed93 100644 --- a/UNITTESTS/unit_test/get_tools.py +++ b/UNITTESTS/unit_test/get_tools.py @@ -53,6 +53,13 @@ def get_cmake_tool(): return _get_program(["cmake"]) +def get_valgrind_tool(): + """ + Get Valgrind program + """ + + return _get_program(["valgrind"]) + def get_cxx_tool(): """ Get C++ compiler diff --git a/UNITTESTS/unit_test/options.py b/UNITTESTS/unit_test/options.py index 211c5d10b9b..0273d997306 100644 --- a/UNITTESTS/unit_test/options.py +++ b/UNITTESTS/unit_test/options.py @@ -103,6 +103,11 @@ def get_options_parser(): help="Build directory. Default: UNITTESTS/build/", dest="build") + parser.add_argument("--valgrind", + help="Use Valgrind when running executables", + action="store_true", + dest="valgrind") + parser.add_argument("--new", action="append", help="Source file from which to generate test files. E.g. rtos/Semaphore.cpp", diff --git a/UNITTESTS/unit_test/test.py b/UNITTESTS/unit_test/test.py index ac7d70975b1..a2f8b894804 100644 --- a/UNITTESTS/unit_test/test.py +++ b/UNITTESTS/unit_test/test.py @@ -28,7 +28,8 @@ from .get_tools import get_make_tool, \ get_cmake_tool, \ get_cxx_tool, \ - get_c_tool + get_c_tool, \ + get_valgrind_tool from .settings import DEFAULT_CMAKE_GENERATORS class UnitTestTool(object): @@ -59,7 +60,8 @@ def create_makefiles(self, path_to_src=None, generator=None, coverage_output_type=None, - debug=False): + debug=False, + valgrind=False): """ Create Makefiles and prepare targets with CMake. @@ -94,6 +96,17 @@ def create_makefiles(self, if coverage_output_type: args.append("-DCOVERAGE:STRING=%s" % coverage_output_type) + if valgrind: + valgrind = get_valgrind_tool() + if valgrind is None: + logging.error( + "No Valgrind found in Path. Install all the required tools.\n") + sys.exit(1) + args.append("-DVALGRIND=1") + args.append("-DMEMORYCHECK_COMMAND_OPTIONS=\"--track-origins=yes\" \"--leak-check=full\" \"--show-reachable=yes\" \"--error-exitcode=1\"") + else: + args.append("-DVALGRIND=0") + if path_to_src is not None: args.append(path_to_src) @@ -118,7 +131,7 @@ def build_tests(self): "Building unit tests failed.", "Unit tests built successfully.") - def run_tests(self, filter_regex=None): + def run_tests(self, filter_regex=None, valgrind=False): """ Run unit tests. @@ -127,11 +140,16 @@ def run_tests(self, filter_regex=None): """ args = [self.make_program, "test"] - - if filter_regex: - args.append("ARGS=-R %s -V -D ExperimentalTest" % filter_regex) + if valgrind: + if filter_regex: + args.append("ARGS=-R %s -V -D ExperimentalMemCheck" % filter_regex) + else: + args.append("ARGS=-V -D ExperimentalMemCheck") else: - args.append("ARGS=-V -D ExperimentalTest") + if filter_regex: + args.append("ARGS=-R %s -V -D ExperimentalTest" % filter_regex) + else: + args.append("ARGS=-V -D ExperimentalTest") if logging.getLogger().getEffectiveLevel() == logging.DEBUG: args.append("VERBOSE=1")