+ Input description
+ Automatic choice of formatter.
+
+
+ Output variant
+ 2
+ 0
+
+
+ Output description
+ Automatic choice of formatter.
+
+
+ GOutputBinary
+ 1
+
+
+ OGCoreOrChip
+ 0
+
+
+ GRuntimeLibSelect
+ 0
+ 1
+
+
+ GRuntimeLibSelectSlave
+ 0
+ 1
+
+
+ RTDescription
+ To be used with the normal configuration of the C/C++ runtime library. No locale interface, C locale, no file descriptor support, no multibytes in printf and scanf, and no hex floats in strtod.
+
+ Input description
+ Automatic choice of formatter.
+
+
+ Output variant
+ 2
+ 0
+
+
+ Output description
+ Automatic choice of formatter.
+
+
+ GOutputBinary
+ 0
+
+
+ OGCoreOrChip
+ 0
+
+
+ GRuntimeLibSelect
+ 0
+ 1
+
+
+ GRuntimeLibSelectSlave
+ 0
+ 1
+
+
+ RTDescription
+ Use the normal configuration of the C/C++ runtime library. No locale interface, C locale, no file descriptor support, no multibytes in printf and scanf, and no hex floats in strtod.
+
-
-
-
-
- tests
-
- failing
-
-
- passing
-
- $PROJ_DIR$\..\..\tests\AllocationInCFile.c
-
-
- $PROJ_DIR$\..\..\tests\AllocationInCppFile.cpp
-
-
- $PROJ_DIR$\..\..\tests\AllocLetTestFree.c
-
-
- $PROJ_DIR$\..\..\tests\AllocLetTestFreeTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\CheatSheetTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\CommandLineArgumentsTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\CommandLineTestRunnerTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\JUnitOutputTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\MemoryLeakDetectorTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\MemoryLeakWarningTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\MemoryOperatorOverloadTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\PluginTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\PreprocessorTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\SetPluginTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\SimpleMutexTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\SimpleStringTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\TestFailureNaNTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\TestFailureTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\TestFilterTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\TestHarness_cTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\TestHarness_cTestCFile.c
-
-
- $PROJ_DIR$\..\..\tests\TestInstallerTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\TestMemoryAllocatorTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\TestOutputTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\TestRegistryTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\TestResultTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\TestUTestMacro.cpp
-
-
- $PROJ_DIR$\..\..\tests\UtestPlatformTest.cpp
-
-
- $PROJ_DIR$\..\..\tests\UtestTest.cpp
-
-
-
- warnings
-
-
- $PROJ_DIR$\tests\AllTests.cpp
-
-
-
-
-
diff --git a/platforms/iar/CppUTestTest.icf b/platforms/iar/CppUTestTest.icf
index 3384b6152..23bfb64c3 100644
--- a/platforms/iar/CppUTestTest.icf
+++ b/platforms/iar/CppUTestTest.icf
@@ -5,7 +5,7 @@
define symbol __ICFEDIT_intvec_start__ = 0x00000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_IROM1_start__ = 0x00000080;
-define symbol __ICFEDIT_region_IROM1_end__ = 0x0007FFFF;
+define symbol __ICFEDIT_region_IROM1_end__ = 0x000FFFFF;
define symbol __ICFEDIT_region_IROM2_start__ = 0x0;
define symbol __ICFEDIT_region_IROM2_end__ = 0x0;
define symbol __ICFEDIT_region_EROM1_start__ = 0x0;
@@ -25,13 +25,13 @@ define symbol __ICFEDIT_region_ERAM2_end__ = 0x0;
define symbol __ICFEDIT_region_ERAM3_start__ = 0x0;
define symbol __ICFEDIT_region_ERAM3_end__ = 0x0;
/*-Sizes-*/
-define symbol __ICFEDIT_size_cstack__ = 0x600;
+define symbol __ICFEDIT_size_cstack__ = 0x2000;
define symbol __ICFEDIT_size_svcstack__ = 0x100;
define symbol __ICFEDIT_size_irqstack__ = 0x100;
define symbol __ICFEDIT_size_fiqstack__ = 0x100;
define symbol __ICFEDIT_size_undstack__ = 0x100;
define symbol __ICFEDIT_size_abtstack__ = 0x100;
-define symbol __ICFEDIT_size_heap__ = 0x8000;
+define symbol __ICFEDIT_size_heap__ = 0x10000;
/**** End of ICF editor section. ###ICF###*/
define memory mem with size = 4G;
diff --git a/platforms/iar/tests/iar_argc_argv.c b/platforms/iar/tests/iar_argc_argv.c
new file mode 100644
index 000000000..e12de9d41
--- /dev/null
+++ b/platforms/iar/tests/iar_argc_argv.c
@@ -0,0 +1,14 @@
+#define NUM_ARGS 2
+
+static char __argvbuf0[] = {"exe"};
+static char __argvbuf1[] = {"-v"};
+
+static int __argc = NUM_ARGS;
+static char * __argv[NUM_ARGS] = { __argvbuf0, __argvbuf1 };
+
+void __iar_argc_argv(void)
+{
+ // setup R0 (argc) and R1 (argv) arguments to main (see cmain.s)
+ asm volatile ("MOVS R1, %0" : : "r" (__argv));
+ asm volatile ("MOVS R0, %0" : : "r" (__argc));
+}
diff --git a/platforms_examples/armcc/AT91SAM7A3/tests/main.cpp b/platforms_examples/armcc/AT91SAM7A3/tests/main.cpp
index e1eac674c..8199883d5 100644
--- a/platforms_examples/armcc/AT91SAM7A3/tests/main.cpp
+++ b/platforms_examples/armcc/AT91SAM7A3/tests/main.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
diff --git a/platforms_examples/armcc/LPC1768/tests/main.cpp b/platforms_examples/armcc/LPC1768/tests/main.cpp
index b8dd10eec..254b171ae 100644
--- a/platforms_examples/armcc/LPC1768/tests/main.cpp
+++ b/platforms_examples/armcc/LPC1768/tests/main.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
diff --git a/platforms_examples/armcc/LPC1833/tests/main.cpp b/platforms_examples/armcc/LPC1833/tests/main.cpp
index 90f317a05..f1299259f 100644
--- a/platforms_examples/armcc/LPC1833/tests/main.cpp
+++ b/platforms_examples/armcc/LPC1833/tests/main.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
diff --git a/scripts/InstallScripts.sh b/scripts/InstallScripts.sh
index 54b85e3a9..1c632e718 100755
--- a/scripts/InstallScripts.sh
+++ b/scripts/InstallScripts.sh
@@ -3,7 +3,8 @@ FirstLetter=${0:0:1}
if [[ $FirstLetter == "/" ]] ; then
CPPUTEST_HOME=${0%/scripts/*}
else
- CPPUTEST_HOME="$(pwd)/${0%/scripts/*}"
+ file=$(pwd)/${0}
+ CPPUTEST_HOME="${file%/scripts/*}"
fi
EXE_DIR=${EXE_DIR:-/usr/local/bin}
diff --git a/scripts/README.txt b/scripts/README.txt
index 8840b1b0a..c6adab6f0 100644
--- a/scripts/README.txt
+++ b/scripts/README.txt
@@ -1,5 +1,5 @@
The New*.sh scripts are helpful for creating the initial files for a new class...
- NewClass.sh - for TTDing a new C++ class
+ NewClass.sh - for TDDing a new C++ class
NewInterface.sh - for TDDing a new interface along with its Mock
NewCModule.sh - for TDDing a C module
NewCmiModule.sh - for TDDing a C module where there will be multiple
@@ -14,7 +14,7 @@ Like this:
You might have to add the execute privilege to the shell scripts.
Like this:
- chmod *.sh
+ chmod +x *.sh
Using NewClass for example:
cd to the directory where you want the files located
diff --git a/scripts/VS2010Templates/CppUTest_VS2010.props b/scripts/VS2010Templates/CppUTest_VS2010.props
index fad877723..7655261a1 100644
--- a/scripts/VS2010Templates/CppUTest_VS2010.props
+++ b/scripts/VS2010Templates/CppUTest_VS2010.props
@@ -2,9 +2,9 @@
- $(CPPUTEST_HOME)\include;$(CPPUTEST_HOME)\include\CppUTestExt\CppUTestGTest;$(CPPUTEST_HOME)\include\CppUTestExt\CppUTestGMock;$(CPPUTEST_HOME)\include\Platforms\VisualCpp
+ $(CPPUTEST_HOME)\include;$(CPPUTEST_HOME)\include\CppUTestExt\CppUTestGTest;$(CPPUTEST_HOME)\include\CppUTestExt\CppUTestGMock$(CPPUTEST_HOME)\lib
- $(CPPUTEST_HOME)\include\Platforms\VisualCpp\Platform.h;$(CPPUTEST_HOME)\include\CppUTest\MemoryLeakDetectorMallocMacros.h;
+ $(CPPUTEST_HOME)\include\CppUTest\MemoryLeakDetectorMallocMacros.h;CppUTest.lib
diff --git a/scripts/appveyor_ci_build.ps1 b/scripts/appveyor_ci_build.ps1
index 238688545..5f33eacd6 100644
--- a/scripts/appveyor_ci_build.ps1
+++ b/scripts/appveyor_ci_build.ps1
@@ -2,6 +2,8 @@
# Load functions from the helper file
. (Join-Path (Split-Path $MyInvocation.MyCommand.Path) 'appveyor_helpers.ps1')
+mkdir cpputest_build
+
function Invoke-BuildCommand($command, $directory = '.')
{
$command_wrapped = "$command;`$err = `$?"
@@ -27,7 +29,7 @@ function Invoke-CygwinCommand($command, $directory = '.')
$cygwin_directory = (. "${cygwin_bin}\cygpath.exe" (Resolve-Path $directory))
$command_wrapped = "${cygwin_bin}\bash.exe --login -c 'cd $cygwin_directory ; $command'"
-
+
Write-Host "Executing <$command> in <$cygwin_directory>"
Invoke-Expression $command_wrapped
@@ -73,10 +75,18 @@ switch -Wildcard ($env:Platform)
{
$mingw_path = Get-MinGWBin
+ if ($env:Platform -like 'MinGWClang*')
+ {
+ $toolchain_filename = Get-ClangToolchainFilename
+ $toolchain_path = (Join-Path (Split-Path $MyInvocation.MyCommand.Path) "..\cmake\Toolchains\$toolchain_filename")
+ $toolchain = "-DCMAKE_TOOLCHAIN_FILE=$toolchain_path -DCPPUTEST_WERROR=OFF"
+ }
+
# Add mingw to the path
Add-PathFolder $mingw_path
- Invoke-BuildCommand "cmake -G 'MinGW Makefiles' .." 'cpputest_build'
+ Invoke-BuildCommand "cmake --version"
+ Invoke-BuildCommand "cmake -G 'MinGW Makefiles' -DCMAKE_CXX_STANDARD=17 $toolchain .." 'cpputest_build'
Invoke-BuildCommand "mingw32-make all" 'cpputest_build'
Remove-PathFolder $mingw_path
diff --git a/scripts/appveyor_ci_test.ps1 b/scripts/appveyor_ci_test.ps1
index 423395117..830542932 100644
--- a/scripts/appveyor_ci_test.ps1
+++ b/scripts/appveyor_ci_test.ps1
@@ -37,8 +37,12 @@ function Invoke-Tests($executable)
{
# Run tests and output the results using junit
$TestCommand = "$executable -ojunit"
- Write-Host $TestCommand
+ Write-Host $TestCommand -NoNewline
Invoke-Expression $TestCommand
+ Write-Host " - return code: $LASTEXITCODE"
+ if ($LASTEXITCODE -lt 0) {
+ Write-Error "Runtime Exception during test execution"
+ }
}
function Invoke-CygwinTests($executable)
@@ -94,10 +98,10 @@ switch -Wildcard ($env:Platform)
{
$mingw_path = Get-MinGWBin
- Add-PathFolder $mingw_path
- Invoke-Tests '.\cpputest_build\tests\CppUTestTests.exe'
+ Set-Path "$mingw_path;C:\Windows;C:\Windows\System32"
+ Invoke-Tests '.\cpputest_build\tests\CppUTest\CppUTestTests.exe'
Invoke-Tests '.\cpputest_build\tests\CppUTestExt\CppUTestExtTests.exe'
- Remove-PathFolder $mingw_path
+ Restore-Path
}
default
diff --git a/scripts/appveyor_helpers.ps1 b/scripts/appveyor_helpers.ps1
index 8f6e0dd67..af08f21ca 100644
--- a/scripts/appveyor_helpers.ps1
+++ b/scripts/appveyor_helpers.ps1
@@ -18,6 +18,16 @@ function Get-MinGWBin() {
}
}
+# Helper function to provide the toolchain file for clang
+function Get-ClangToolchainFilename() {
+ if ($env:Platform -like '*64') {
+ Write-Output 'clang+mingw-win64.toolchain.cmake'
+ }
+ else {
+ Write-Output 'clang+mingw-win32.toolchain.cmake'
+ }
+}
+
# Helper function to provide the bin-folder path to cygwin
function Get-CygwinBin() {
if ($env:Platform -like '*64') {
@@ -74,3 +84,13 @@ function Remove-PathFolder($folder)
$env:Path = $pathFolders -join ";"
}
+function Set-Path($newPath)
+{
+ $env:RestorePath = $env:Path
+ $env:Path = $newPath
+}
+
+function Restore-Path()
+{
+ $env:Path = $env:RestorePath
+}
diff --git a/scripts/create_docker_images_and_containers b/scripts/create_docker_images_and_containers
new file mode 100755
index 000000000..ab4ec05b6
--- /dev/null
+++ b/scripts/create_docker_images_and_containers
@@ -0,0 +1,37 @@
+#!/bin/bash
+#$1 is the container name
+
+checkForCppUTestToolsEnvVariable() {
+ if [ -z "$CPPUTEST_HOME" ] ; then
+ echo "CPPUTEST_HOME not set. You must set CPPUTEST_HOME to the top level CppUTest directory"
+ exit 1
+ fi
+ if [ ! -d "$CPPUTEST_HOME" ] ; then
+ echo "CPPUTEST_HOME not set to a directory. You must set CPPUTEST_HOME to the top level CppUTest directory"
+ exit 2
+ fi
+}
+
+checkForImageNameParameter() {
+ if [ -z "$container" ] ; then
+ echo "Container name parameter not set. Check the docker directory. It should be the extension of the Dockerfile. e.g. ubuntu"
+ exit 1
+ fi
+ if [ ! -f "$CPPUTEST_HOME/docker/Dockerfile.$container" ] ; then
+ echo "The Dockerfile docker/Dockerfile.$container doesn't exist. Typo?"
+ exit 2
+ fi
+}
+
+
+container=$1
+checkForCppUTestToolsEnvVariable
+checkForImageNameParameter
+
+docker build -f $CPPUTEST_HOME/docker/Dockerfile.$container --tag cpputest/$container:latest .
+docker container rm cpputest_$container
+docker create -it -v$CPPUTEST_HOME:/cpputest -e "CPPUTEST_HOME=/cpputest" --name cpputest_$container cpputest/$container:latest
+
+echo "You can run your container through: docker start -i cpputest_. E.g. docker start -i cpputest_$container"
+
+
diff --git a/scripts/dos_build_test.sh b/scripts/dos_build_test.sh
new file mode 100755
index 000000000..cf10fe5a9
--- /dev/null
+++ b/scripts/dos_build_test.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+set -euo pipefail
+# get current dir even if the script is sourced
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+
+export CPPUTEST_HOME="$DIR/../"
+export WATCOM=./watcom
+export PATH=$PATH:$WATCOM/binl
+
+if [ ! -d "$WATCOM" ]; then
+ git clone https://github.com/cpputest/watcom-compiler.git "$WATCOM"
+fi
+
+make -f "$CPPUTEST_HOME/platforms/Dos/Makefile" clean
+make -f "$CPPUTEST_HOME/platforms/Dos/Makefile"
+make -f "$CPPUTEST_HOME/platforms/Dos/Makefile" test
diff --git a/scripts/filterGcov.sh b/scripts/filterGcov.sh
index 2f6ec1d41..b3ff67fee 100755
--- a/scripts/filterGcov.sh
+++ b/scripts/filterGcov.sh
@@ -22,7 +22,7 @@ getRidOfCruft() {
sed '-e s/^Lines.*://g' \
'-e s/^[0-9]\./ &/g' \
'-e s/^[0-9][0-9]\./ &/g' \
- '-e s/of.*File/ /g' \
+ '-e s/of.\w[^'File']*File/ /g' \
"-e s/'//g" \
'-e s/^.*\/usr\/.*$//g' \
'-e s/^.*\.$//g'
diff --git a/scripts/templates/ProjectTemplate/Project.cproject b/scripts/templates/ProjectTemplate/Project.cproject
index df56e1665..a3fb56605 100644
--- a/scripts/templates/ProjectTemplate/Project.cproject
+++ b/scripts/templates/ProjectTemplate/Project.cproject
@@ -30,6 +30,7 @@
+
@@ -37,12 +38,14 @@
+
+
diff --git a/scripts/templates/ProjectTemplate/ProjectMakefile b/scripts/templates/ProjectTemplate/ProjectMakefile
index 68747610f..f426016c8 100644
--- a/scripts/templates/ProjectTemplate/ProjectMakefile
+++ b/scripts/templates/ProjectTemplate/ProjectMakefile
@@ -32,7 +32,6 @@ INCLUDE_DIRS =\
include \
include/* \
$(CPPUTEST_HOME)/include/ \
- $(CPPUTEST_HOME)/include/Platforms/Gcc\
mocks
CPPUTEST_WARNINGFLAGS = -Wall -Werror -Wswitch-default
diff --git a/scripts/travis_ci_build.sh b/scripts/travis_ci_build.sh
deleted file mode 100755
index 0d5efa9b4..000000000
--- a/scripts/travis_ci_build.sh
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/bin/bash
-# Script run in the travis CI
-set -ex
-
-if [ "x$BUILD" = "xautotools" ]; then
- autoreconf -i ..
- ../configure
- echo "CONFIGURATION DONE. Compiling now."
- make check_all
-
- make dist
- make dist-zip
-
- if [ "x$CXX" = "xg++" ]; then
- echo "Deploy please"
-# gem install travis_github_deployer
-# cd .. && travis_github_deployer -v || exit 1
- fi;
-fi
-
-if [ "x$BUILD" = "xcmake" ]; then
- cmake .. -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE
- make
- ctest -V
-
- if [ "x$CXX" != "xg++" ]; then
- cmake .. -DC++11=ON -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE
- make
- ctest -V
- fi
-fi
-
-if [ "x$BUILD" = "xautotools_gtest" ]; then
- autoreconf -i ..
- ../configure
-
- make check_gtest
-fi
-
-if [ "x$BUILD" = "xcmake_gtest" ]; then
- wget https://googlemock.googlecode.com/files/gmock-1.6.0.zip
- unzip gmock-1.6.0.zip -d $TRAVIS_BUILD_DIR
- cd $TRAVIS_BUILD_DIR/gmock-1.6.0
- ./configure && make
- cd -
-
- export GMOCK_HOME=$TRAVIS_BUILD_DIR/gmock-1.6.0
- export GTEST_HOME=$TRAVIS_BUILD_DIR/gmock-1.6.0/gtest
- cmake .. -DGMOCK=ON
- make
- ctest -V
-fi
-
-if [ "x$BUILD" = "xtest_report" ]; then
- autoreconf -i ..
- ../configure
- make check
- ./CppUTestTests -ojunit
- ./CppUTestExtTests -ojunit
- cp ../scripts/generate_junit_report_ant.xml .
- ant -f generate_junit_report_ant.xml
-fi
-
-if [ "x$BUILD" = "xcmake_coverage" ]; then
- pip install cpp-coveralls --user `whoami`
-
- cmake .. -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -DCOVERAGE=ON -DLONGLONG=ON
- make
- ctest
-
- coveralls -b . -r .. -i "src" -i "include" --gcov-options="-lbc" || true
-fi
-
-if [ "x$BUILD" = "xmake_dos" ]; then
- wget ftp://ftp.openwatcom.org/pub/open-watcom-c-linux-1.9 -O /tmp/watcom.zip
- mkdir -p watcom && unzip -aqd watcom /tmp/watcom.zip && chmod -R +x watcom/binl
- export PATH=$PATH:$PWD/watcom/binl
- export WATCOM=$PWD/watcom
- export CPPUTEST_HOME=$TRAVIS_BUILD_DIR
- export CC=wcl
- export CXX=wcl
- $CC --version
- make -f ../platforms/Dos/Makefile || exit 1
- ../platforms/Dos/alltests.sh || exit 1
- fi
-
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 000000000..8bee1d9b8
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_subdirectory(CppUTest)
+if (CPPUTEST_EXTENSIONS)
+ add_subdirectory(CppUTestExt)
+endif ()
diff --git a/src/CppUTest/CMakeIntegration-README.md b/src/CppUTest/CMakeIntegration-README.md
new file mode 100644
index 000000000..74ec44aaa
--- /dev/null
+++ b/src/CppUTest/CMakeIntegration-README.md
@@ -0,0 +1,110 @@
+# CMake Integration
+
+## FetchContent
+
+CMake can automatically download and integrate CppUTest with
+[`FetchContent`](https://cmake.org/cmake/help/latest/module/FetchContent.html).
+This is the recommended strategy for CMake integration.
+
+```cmake
+cmake_minimum_required(VERSION 3.11)
+project(trying_CppUtest)
+
+include(FetchContent)
+FetchContent_Declare(
+ CppUTest
+ GIT_REPOSITORY https://github.com/cpputest/cpputest.git
+ GIT_TAG master # or use release tag, eg. v4.0
+ # FIND_PACKAGE_ARGS # Recent CMake versions can integrate FetchContent with find_package
+ # https://cmake.org/cmake/help/latest/module/FetchContent.html#integrating-with-find-package
+)
+
+# Either set CPPUTEST_PLATFORM to off and # provide a project-specific
+# platform.cpp, assign # one of the provided platforms under
+# src/Platforms/ # (as shown below), or let CppUTest
+# select an appropriate default.
+set(CPPUTEST_PLATFORM Gcc STRING BOOL "Platform implementation")
+
+FetchContent_MakeAvailable(CppUTest)
+
+add_executable(trying_CppUtest main.cpp)
+
+target_link_libraries(trying_CppUtest
+ PRIVATE
+ CppUTest::CppUTest
+ #or CppUTest::CppUTestExt
+)
+
+include(CTest) # Enable testing
+
+# automatically discover CppUTest tests
+include(CppUTest)
+cpputest_discover_tests(trying_CppUtest)
+```
+
+## System install
+
+If CppUTest has been installed on the system, it can be integrated with
+[`find_package`](https://cmake.org/cmake/help/latest/command/find_package.html).
+The target platform will be the same as the development host.
+This is useful for managing a common
+CppUTest installation with the system's package manager.
+
+```cmake
+cmake_minimum_required(VERSION 3.10)
+project(trying_CppUtest)
+
+find_package(CppUTest REQUIRED)
+
+add_executable(trying_CppUtest main.cpp)
+
+target_link_libraries(trying_CppUtest
+ PRIVATE
+ CppUTest
+ #or CppUTestExt
+)
+
+include(CTest) # Enable testing
+
+# automatically discover CppUTest tests
+include(CppUTest)
+cpputest_discover_tests(trying_CppUtest)
+```
+
+## Shared directory
+
+It is possible to integrate CppUTest from a local directory. This may be useful
+if CppUTest is being built for a target platform other than that of the
+development host and CMake 3.11 is not available. The following is an example
+how an external project can refer to this CMakeLists.txt to build CppUTest as a
+library and include it as a target dependency.
+
+```cmake
+cmake_minimum_required(VERSION 3.10)
+project(trying_CppUtest)
+
+SET(CppUTestRootDirectory /path/to/cpputest)
+
+# Either set CPPUTEST_PLATFORM to one of the provided platforms under
+# /src/Platforms/, or provide a project-specific
+# platform.cpp (as shown below)
+set(CPPUTEST_PLATFORM OFF CACHE BOOL "Platform implementation")
+add_subdirectory(${CppUTestRootDirectory} CppUTest)
+target_sources(CppUTest
+ PRIVATE
+ ${PROJECT_SOURCE_DIR}/UtestPlatform.cpp
+)
+
+add_executable(trying_CppUtest main.cpp)
+target_link_libraries(trying_CppUtest
+ PRIVATE
+ CppUTest::CppUTest
+ #or CppUTest::CppUTestExt
+)
+
+include(CTest) # Enable testing
+
+# automatically discover CppUTest tests
+include(CppUTest)
+cpputest_discover_tests(trying_CppUtest)
+```
diff --git a/src/CppUTest/CMakeLists.txt b/src/CppUTest/CMakeLists.txt
index 736777f5e..f7c737b0c 100644
--- a/src/CppUTest/CMakeLists.txt
+++ b/src/CppUTest/CMakeLists.txt
@@ -1,10 +1,11 @@
-set(CppUTest_src
+add_library(CppUTest
CommandLineArguments.cpp
MemoryLeakWarningPlugin.cpp
TestHarness_c.cpp
TestRegistry.cpp
CommandLineTestRunner.cpp
SimpleString.cpp
+ SimpleStringInternalCache.cpp
TestMemoryAllocator.cpp
TestResult.cpp
JUnitTestOutput.cpp
@@ -17,44 +18,110 @@ set(CppUTest_src
TestTestingFixture.cpp
SimpleMutex.cpp
Utest.cpp
- ../Platforms/${CPP_PLATFORM}/UtestPlatform.cpp
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/CommandLineArguments.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/PlatformSpecificFunctions.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/TestMemoryAllocator.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/CommandLineTestRunner.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/PlatformSpecificFunctions_c.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/TestOutput.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/CppUTestConfig.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/SimpleString.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/SimpleStringInternalCache.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/TestPlugin.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/JUnitTestOutput.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/TeamCityTestOutput.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/StandardCLibrary.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/TestRegistry.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/MemoryLeakDetector.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/TestFailure.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/TestResult.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/MemoryLeakDetectorMallocMacros.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/TestFilter.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/TestTestingFixture.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/MemoryLeakDetectorNewMacros.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/MemoryLeakDetectorForceInclude.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/TestHarness.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/Utest.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/MemoryLeakWarningPlugin.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/TestHarness_c.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/UtestMacros.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTest/SimpleMutex.h
)
-set(CppUTest_headers
- ${CppUTestRootDirectory}/include/CppUTest/CommandLineArguments.h
- ${CppUTestRootDirectory}/include/CppUTest/PlatformSpecificFunctions.h
- ${CppUTestRootDirectory}/include/CppUTest/TestMemoryAllocator.h
- ${CppUTestRootDirectory}/include/CppUTest/CommandLineTestRunner.h
- ${CppUTestRootDirectory}/include/CppUTest/PlatformSpecificFunctions_c.h
- ${CppUTestRootDirectory}/include/CppUTest/TestOutput.h
- ${CppUTestRootDirectory}/include/CppUTest/CppUTestConfig.h
- ${CppUTestRootDirectory}/include/CppUTest/SimpleString.h
- ${CppUTestRootDirectory}/include/CppUTest/TestPlugin.h
- ${CppUTestRootDirectory}/include/CppUTest/JUnitTestOutput.h
- ${CppUTestRootDirectory}/include/CppUTest/TeamCityTestOutput.h
- ${CppUTestRootDirectory}/include/CppUTest/StandardCLibrary.h
- ${CppUTestRootDirectory}/include/CppUTest/TestRegistry.h
- ${CppUTestRootDirectory}/include/CppUTest/MemoryLeakDetector.h
- ${CppUTestRootDirectory}/include/CppUTest/TestFailure.h
- ${CppUTestRootDirectory}/include/CppUTest/TestResult.h
- ${CppUTestRootDirectory}/include/CppUTest/MemoryLeakDetectorMallocMacros.h
- ${CppUTestRootDirectory}/include/CppUTest/TestFilter.h
- ${CppUTestRootDirectory}/include/CppUTest/TestTestingFixture.h
- ${CppUTestRootDirectory}/include/CppUTest/MemoryLeakDetectorNewMacros.h
- ${CppUTestRootDirectory}/include/CppUTest/TestHarness.h
- ${CppUTestRootDirectory}/include/CppUTest/Utest.h
- ${CppUTestRootDirectory}/include/CppUTest/MemoryLeakWarningPlugin.h
- ${CppUTestRootDirectory}/include/CppUTest/TestHarness_c.h
- ${CppUTestRootDirectory}/include/CppUTest/UtestMacros.h
+#[[Set CPPUTEST_PLATFORM in a parent CMakeLists.txt if reusing one of the provided platforms, else supply the missing definitions]]
+if(CPPUTEST_PLATFORM)
+ target_sources(CppUTest
+ PRIVATE
+ ${CMAKE_CURRENT_LIST_DIR}/../Platforms/${CPPUTEST_PLATFORM}/UtestPlatform.cpp
+ )
+endif()
+
+if(CPPUTEST_PLATFORM STREQUAL "c2000")
+ target_include_directories(CppUTest
+ PUBLIC
+ $
+ )
+elseif(CPPUTEST_PLATFORM STREQUAL "Iar")
+ target_compile_options(CppUTest
+ PRIVATE
+ --dlib_config full
+ )
+endif()
+
+if (MINGW)
+ include(CheckStructHasMember)
+ check_struct_has_member("struct timespec" tv_sec time.h HAVE_STRUCT_TIMESPEC LANGUAGE CXX)
+endif()
+
+#[[Arrange for the include directory to be added to the include paths of any CMake target depending on CppUTest.]]
+target_include_directories(CppUTest
+ PUBLIC
+ $
+ $
+)
+
+target_compile_definitions(CppUTest
+ PRIVATE
+ $<$:STDC_WANT_SECURE_LIB>
+ # Apply workaround for MinGW timespec redefinition (pthread.h / time.h).
+ $<$:_TIMESPEC_DEFINED>
)
-add_library(CppUTest STATIC ${CppUTest_src} ${CppUTest_headers})
-if (WIN32)
- target_link_libraries(CppUTest winmm.lib)
-endif (WIN32)
-install(FILES ${CppUTest_headers} DESTINATION include/CppUTest)
-install(TARGETS CppUTest
- EXPORT CppUTestTargets
- RUNTIME DESTINATION bin
- LIBRARY DESTINATION lib
- ARCHIVE DESTINATION lib)
+set(THREADS_PREFER_PTHREAD_FLAG ON)
+find_package(Threads)
+
+target_link_libraries(CppUTest
+ PRIVATE
+ $<$:winmm>
+ $<$:${CMAKE_THREAD_LIBS_INIT}>
+)
+
+add_library(CppUTest::CppUTest ALIAS CppUTest)
+
+if(NOT CPPUTEST_MEM_LEAK_DETECTION_DISABLED)
+ if(MSVC)
+ set(force_include "/FI")
+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "IAR")
+ set(force_include "--preinclude=")
+ else()
+ set(force_include "-include")
+ endif()
+ target_compile_options(CppUTest
+ PUBLIC
+ ${force_include}CppUTest/MemoryLeakDetectorForceInclude.h
+ )
+endif()
+
+# Installation
+if(PROJECT_IS_TOP_LEVEL)
+ install(
+ TARGETS CppUTest
+ EXPORT CppUTestTargets
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ )
+ install(
+ DIRECTORY "${PROJECT_SOURCE_DIR}/include/CppUTest"
+ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
+ )
+endif()
diff --git a/src/CppUTest/CommandLineArguments.cpp b/src/CppUTest/CommandLineArguments.cpp
old mode 100755
new mode 100644
index e0b993bcd..e3d1a8cbe
--- a/src/CppUTest/CommandLineArguments.cpp
+++ b/src/CppUTest/CommandLineArguments.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -29,8 +29,11 @@
#include "CppUTest/CommandLineArguments.h"
#include "CppUTest/PlatformSpecificFunctions.h"
-CommandLineArguments::CommandLineArguments(int ac, const char** av) :
- ac_(ac), av_(av), verbose_(false), color_(false), runTestsAsSeperateProcess_(false), listTestGroupNames_(false), listTestGroupAndCaseNames_(false), runIgnored_(false), repeat_(1), groupFilters_(NULL), nameFilters_(NULL), outputType_(OUTPUT_ECLIPSE)
+CommandLineArguments::CommandLineArguments(int ac, const char *const *av) :
+ ac_(ac), av_(av), needHelp_(false), verbose_(false), veryVerbose_(false), color_(false), runTestsAsSeperateProcess_(false),
+ listTestGroupNames_(false), listTestGroupAndCaseNames_(false), listTestLocations_(false), runIgnored_(false), reversing_(false),
+ crashOnFail_(false), rethrowExceptions_(true), shuffling_(false), shufflingPreSeeded_(false), repeat_(1), shuffleSeed_(0),
+ groupFilters_(NULLPTR), nameFilters_(NULLPTR), outputType_(OUTPUT_ECLIPSE)
{
}
@@ -54,26 +57,40 @@ bool CommandLineArguments::parse(TestPlugin* plugin)
for (int i = 1; i < ac_; i++) {
SimpleString argument = av_[i];
- if (argument == "-v") verbose_ = true;
+ if (argument == "-h") {
+ needHelp_ = true;
+ correctParameters = false;
+ }
+ else if (argument == "-v") verbose_ = true;
+ else if (argument == "-vv") veryVerbose_ = true;
else if (argument == "-c") color_ = true;
else if (argument == "-p") runTestsAsSeperateProcess_ = true;
+ else if (argument == "-b") reversing_ = true;
else if (argument == "-lg") listTestGroupNames_ = true;
else if (argument == "-ln") listTestGroupAndCaseNames_ = true;
+ else if (argument == "-ll") listTestLocations_ = true;
else if (argument == "-ri") runIgnored_ = true;
- else if (argument.startsWith("-r")) SetRepeatCount(ac_, av_, i);
- else if (argument.startsWith("-g")) AddGroupFilter(ac_, av_, i);
- else if (argument.startsWith("-sg")) AddStrictGroupFilter(ac_, av_, i);
- else if (argument.startsWith("-xg")) AddExcludeGroupFilter(ac_, av_, i);
- else if (argument.startsWith("-xsg")) AddExcludeStrictGroupFilter(ac_, av_, i);
- else if (argument.startsWith("-n")) AddNameFilter(ac_, av_, i);
- else if (argument.startsWith("-sn")) AddStrictNameFilter(ac_, av_, i);
- else if (argument.startsWith("-xn")) AddExcludeNameFilter(ac_, av_, i);
- else if (argument.startsWith("-xsn")) AddExcludeStrictNameFilter(ac_, av_, i);
- else if (argument.startsWith("TEST(")) AddTestToRunBasedOnVerboseOutput(ac_, av_, i, "TEST(");
- else if (argument.startsWith("IGNORE_TEST(")) AddTestToRunBasedOnVerboseOutput(ac_, av_, i, "IGNORE_TEST(");
- else if (argument.startsWith("-o")) correctParameters = SetOutputType(ac_, av_, i);
+ else if (argument == "-f") crashOnFail_ = true;
+ else if ((argument == "-e") || (argument == "-ci")) rethrowExceptions_ = false;
+ else if (argument.startsWith("-r")) setRepeatCount(ac_, av_, i);
+ else if (argument.startsWith("-g")) addGroupFilter(ac_, av_, i);
+ else if (argument.startsWith("-t")) correctParameters = addGroupDotNameFilter(ac_, av_, i, "-t", false, false);
+ else if (argument.startsWith("-st")) correctParameters = addGroupDotNameFilter(ac_, av_, i, "-st", true, false);
+ else if (argument.startsWith("-xt")) correctParameters = addGroupDotNameFilter(ac_, av_, i, "-xt", false, true);
+ else if (argument.startsWith("-xst")) correctParameters = addGroupDotNameFilter(ac_, av_, i, "-xst", true, true);
+ else if (argument.startsWith("-sg")) addStrictGroupFilter(ac_, av_, i);
+ else if (argument.startsWith("-xg")) addExcludeGroupFilter(ac_, av_, i);
+ else if (argument.startsWith("-xsg")) addExcludeStrictGroupFilter(ac_, av_, i);
+ else if (argument.startsWith("-n")) addNameFilter(ac_, av_, i);
+ else if (argument.startsWith("-sn")) addStrictNameFilter(ac_, av_, i);
+ else if (argument.startsWith("-xn")) addExcludeNameFilter(ac_, av_, i);
+ else if (argument.startsWith("-xsn")) addExcludeStrictNameFilter(ac_, av_, i);
+ else if (argument.startsWith("-s")) correctParameters = setShuffle(ac_, av_, i);
+ else if (argument.startsWith("TEST(")) addTestToRunBasedOnVerboseOutput(ac_, av_, i, "TEST(");
+ else if (argument.startsWith("IGNORE_TEST(")) addTestToRunBasedOnVerboseOutput(ac_, av_, i, "IGNORE_TEST(");
+ else if (argument.startsWith("-o")) correctParameters = setOutputType(ac_, av_, i);
else if (argument.startsWith("-p")) correctParameters = plugin->parseAllArguments(ac_, av_, i);
- else if (argument.startsWith("-k")) SetPackageName(ac_, av_, i);
+ else if (argument.startsWith("-k")) setPackageName(ac_, av_, i);
else correctParameters = false;
if (correctParameters == false) {
@@ -85,7 +102,67 @@ bool CommandLineArguments::parse(TestPlugin* plugin)
const char* CommandLineArguments::usage() const
{
- return "usage [-v] [-c] [-p] [-lg] [-ln] [-ri] [-r#] [-g|sg|xg|xsg groupName]... [-n|sn|xn|xsn testName]... [\"TEST(groupName, testName)\"]... [-o{normal, junit, teamcity}] [-k packageName]\n";
+ return "use -h for more extensive help\n"
+ "usage [-h] [-v] [-vv] [-c] [-p] [-lg] [-ln] [-ll] [-ri] [-r[<#>]] [-f] [-e] [-ci]\n"
+ " [-g|sg|xg|xsg ]... [-n|sn|xn|xsn ]... [-t|st|xt|xst .]...\n"
+ " [-b] [-s []] [\"[IGNORE_]TEST(, )\"]...\n"
+ " [-o{normal|eclipse|junit|teamcity}] [-k ]\n";
+}
+
+const char* CommandLineArguments::help() const
+{
+ return
+ "Thanks for using CppUTest.\n"
+ "\n"
+ "Options that do not run tests but query:\n"
+ " -h - this wonderful help screen. Joy!\n"
+ " -lg - print a list of group names, separated by spaces\n"
+ " -ln - print a list of test names in the form of group.name, separated by spaces\n"
+ " -ll - print a list of test names in the form of group.name.test_file_path.line\n"
+ "\n"
+ "Options that change the output format:\n"
+ " -c - colorize output, print green if OK, or red if failed\n"
+ " -v - verbose, print each test name as it runs\n"
+ " -vv - very verbose, print internal information during test run\n"
+ "\n"
+ "Options that change the output location:\n"
+ " -onormal - no output to files\n"
+ " -oeclipse - equivalent to -onormal\n"
+ " -oteamcity - output to xml files (as the name suggests, for TeamCity)\n"
+ " -ojunit - output to JUnit ant plugin style xml files (for CI systems)\n"
+ " -k - add a package name in JUnit output (for classification in CI systems)\n"
+ "\n"
+ "\n"
+ "Options that control which tests are run:\n"
+ " -g - only run tests whose group contains \n"
+ " -n - only run tests whose name contains \n"
+ " -t . - only run tests whose group and name contain and \n"
+ " -sg - only run tests whose group exactly matches \n"
+ " -sn - only run tests whose name exactly matches \n"
+ " -st . - only run tests whose group and name exactly match and \n"
+ " -xg - exclude tests whose group contains \n"
+ " -xn - exclude tests whose name contains \n"
+ " -xt . - exclude tests whose group and name contain and \n"
+ " -xsg - exclude tests whose group exactly matches \n"
+ " -xsn - exclude tests whose name exactly matches \n"
+ " -xst . - exclude tests whose group and name exactly match and \n"
+ " \"[IGNORE_]TEST(, )\"\n"
+ " - only run tests whose group and name exactly match and \n"
+ " (this can be used to copy-paste output from the -v option on the command line)\n"
+ "\n"
+ "Options that control how the tests are run:\n"
+ " -p - run tests in a separate process\n"
+ " -b - run the tests backwards, reversing the normal way\n"
+ " -s [] - shuffle tests randomly (randomization seed is optional, must be greater than 0)\n"
+ " -r[<#>] - repeat the tests <#> times (or twice if <#> is not specified)\n"
+ " -f - Cause the tests to crash on failure (to allow the test to be debugged if necessary)\n"
+ " -e - do not rethrow unexpected exceptions on failure\n"
+ " -ci - continuous integration mode (equivalent to -e)\n";
+}
+
+bool CommandLineArguments::needHelp() const
+{
+ return needHelp_;
}
bool CommandLineArguments::isVerbose() const
@@ -93,6 +170,11 @@ bool CommandLineArguments::isVerbose() const
return verbose_;
}
+bool CommandLineArguments::isVeryVerbose() const
+{
+ return veryVerbose_;
+}
+
bool CommandLineArguments::isColor() const
{
return color_;
@@ -108,6 +190,11 @@ bool CommandLineArguments::isListingTestGroupAndCaseNames() const
return listTestGroupAndCaseNames_;
}
+bool CommandLineArguments::isListingTestLocations() const
+{
+ return listTestLocations_;
+}
+
bool CommandLineArguments::isRunIgnored() const
{
return runIgnored_;
@@ -119,11 +206,36 @@ bool CommandLineArguments::runTestsInSeperateProcess() const
}
-int CommandLineArguments::getRepeatCount() const
+size_t CommandLineArguments::getRepeatCount() const
{
return repeat_;
}
+bool CommandLineArguments::isReversing() const
+{
+ return reversing_;
+}
+
+bool CommandLineArguments::isCrashingOnFail() const
+{
+ return crashOnFail_;
+}
+
+bool CommandLineArguments::isRethrowingExceptions() const
+{
+ return rethrowExceptions_;
+}
+
+bool CommandLineArguments::isShuffling() const
+{
+ return shuffling_;
+}
+
+size_t CommandLineArguments::getShuffleSeed() const
+{
+ return shuffleSeed_;
+}
+
const TestFilter* CommandLineArguments::getGroupFilters() const
{
return groupFilters_;
@@ -134,14 +246,14 @@ const TestFilter* CommandLineArguments::getNameFilters() const
return nameFilters_;
}
-void CommandLineArguments::SetRepeatCount(int ac, const char** av, int& i)
+void CommandLineArguments::setRepeatCount(int ac, const char *const *av, int& i)
{
repeat_ = 0;
SimpleString repeatParameter(av[i]);
- if (repeatParameter.size() > 2) repeat_ = SimpleString::AtoI(av[i] + 2);
+ if (repeatParameter.size() > 2) repeat_ = (size_t) (SimpleString::AtoI(av[i] + 2));
else if (i + 1 < ac) {
- repeat_ = SimpleString::AtoI(av[i + 1]);
+ repeat_ = (size_t) (SimpleString::AtoI(av[i + 1]));
if (repeat_ != 0) i++;
}
@@ -149,7 +261,29 @@ void CommandLineArguments::SetRepeatCount(int ac, const char** av, int& i)
}
-SimpleString CommandLineArguments::getParameterField(int ac, const char** av, int& i, const SimpleString& parameterName)
+bool CommandLineArguments::setShuffle(int ac, const char * const *av, int& i)
+{
+ shuffling_ = true;
+ shuffleSeed_ = (unsigned int)GetPlatformSpecificTimeInMillis();
+ if (shuffleSeed_ == 0) shuffleSeed_++;
+
+ SimpleString shuffleParameter = av[i];
+ if (shuffleParameter.size() > 2) {
+ shufflingPreSeeded_ = true;
+ shuffleSeed_ = SimpleString::AtoU(av[i] + 2);
+ } else if (i + 1 < ac) {
+ unsigned int parsedParameter = SimpleString::AtoU(av[i + 1]);
+ if (parsedParameter != 0)
+ {
+ shufflingPreSeeded_ = true;
+ shuffleSeed_ = parsedParameter;
+ i++;
+ }
+ }
+ return (shuffleSeed_ != 0);
+}
+
+SimpleString CommandLineArguments::getParameterField(int ac, const char * const *av, int& i, const SimpleString& parameterName)
{
size_t parameterLength = parameterName.size();
SimpleString parameter(av[i]);
@@ -158,27 +292,53 @@ SimpleString CommandLineArguments::getParameterField(int ac, const char** av, in
return "";
}
-void CommandLineArguments::AddGroupFilter(int ac, const char** av, int& i)
+void CommandLineArguments::addGroupFilter(int ac, const char *const *av, int& i)
{
TestFilter* groupFilter = new TestFilter(getParameterField(ac, av, i, "-g"));
groupFilters_ = groupFilter->add(groupFilters_);
}
-void CommandLineArguments::AddStrictGroupFilter(int ac, const char** av, int& i)
+bool CommandLineArguments::addGroupDotNameFilter(int ac, const char *const *av, int& i, const SimpleString& parameterName,
+ bool strict, bool exclude)
+{
+ SimpleString groupDotName = getParameterField(ac, av, i, parameterName);
+ SimpleStringCollection collection;
+ groupDotName.split(".", collection);
+
+ if (collection.size() != 2) return false;
+
+ TestFilter* groupFilter = new TestFilter(collection[0].subString(0, collection[0].size()-1));
+ TestFilter* nameFilter = new TestFilter(collection[1]);
+ if (strict)
+ {
+ groupFilter->strictMatching();
+ nameFilter->strictMatching();
+ }
+ if (exclude)
+ {
+ groupFilter->invertMatching();
+ nameFilter->invertMatching();
+ }
+ groupFilters_ = groupFilter->add(groupFilters_);
+ nameFilters_ = nameFilter->add(nameFilters_);
+ return true;
+}
+
+void CommandLineArguments::addStrictGroupFilter(int ac, const char *const *av, int& i)
{
TestFilter* groupFilter = new TestFilter(getParameterField(ac, av, i, "-sg"));
groupFilter->strictMatching();
groupFilters_ = groupFilter->add(groupFilters_);
}
-void CommandLineArguments::AddExcludeGroupFilter(int ac, const char** av, int& i)
+void CommandLineArguments::addExcludeGroupFilter(int ac, const char *const *av, int& i)
{
TestFilter* groupFilter = new TestFilter(getParameterField(ac, av, i, "-xg"));
groupFilter->invertMatching();
groupFilters_ = groupFilter->add(groupFilters_);
}
-void CommandLineArguments::AddExcludeStrictGroupFilter(int ac, const char** av, int& i)
+void CommandLineArguments::addExcludeStrictGroupFilter(int ac, const char *const *av, int& i)
{
TestFilter* groupFilter = new TestFilter(getParameterField(ac, av, i, "-xsg"));
groupFilter->strictMatching();
@@ -186,27 +346,27 @@ void CommandLineArguments::AddExcludeStrictGroupFilter(int ac, const char** av,
groupFilters_ = groupFilter->add(groupFilters_);
}
-void CommandLineArguments::AddNameFilter(int ac, const char** av, int& i)
+void CommandLineArguments::addNameFilter(int ac, const char *const *av, int& i)
{
TestFilter* nameFilter = new TestFilter(getParameterField(ac, av, i, "-n"));
nameFilters_ = nameFilter->add(nameFilters_);
}
-void CommandLineArguments::AddStrictNameFilter(int ac, const char** av, int& index)
+void CommandLineArguments::addStrictNameFilter(int ac, const char *const *av, int& index)
{
TestFilter* nameFilter = new TestFilter(getParameterField(ac, av, index, "-sn"));
nameFilter->strictMatching();
nameFilters_= nameFilter->add(nameFilters_);
}
-void CommandLineArguments::AddExcludeNameFilter(int ac, const char** av, int& index)
+void CommandLineArguments::addExcludeNameFilter(int ac, const char *const *av, int& index)
{
TestFilter* nameFilter = new TestFilter(getParameterField(ac, av, index, "-xn"));
nameFilter->invertMatching();
nameFilters_= nameFilter->add(nameFilters_);
}
-void CommandLineArguments::AddExcludeStrictNameFilter(int ac, const char** av, int& index)
+void CommandLineArguments::addExcludeStrictNameFilter(int ac, const char *const *av, int& index)
{
TestFilter* nameFilter = new TestFilter(getParameterField(ac, av, index, "-xsn"));
nameFilter->invertMatching();
@@ -214,11 +374,11 @@ void CommandLineArguments::AddExcludeStrictNameFilter(int ac, const char** av, i
nameFilters_= nameFilter->add(nameFilters_);
}
-void CommandLineArguments::AddTestToRunBasedOnVerboseOutput(int ac, const char** av, int& index, const char* parameterName)
+void CommandLineArguments::addTestToRunBasedOnVerboseOutput(int ac, const char *const *av, int& index, const char* parameterName)
{
SimpleString wholename = getParameterField(ac, av, index, parameterName);
SimpleString testname = wholename.subStringFromTill(',', ')');
- testname = testname.subString(2, testname.size());
+ testname = testname.subString(2);
TestFilter* namefilter = new TestFilter(testname);
TestFilter* groupfilter = new TestFilter(wholename.subStringFromTill(wholename.at(0), ','));
namefilter->strictMatching();
@@ -227,7 +387,7 @@ void CommandLineArguments::AddTestToRunBasedOnVerboseOutput(int ac, const char**
nameFilters_ = namefilter->add(nameFilters_);
}
-void CommandLineArguments::SetPackageName(int ac, const char** av, int& i)
+void CommandLineArguments::setPackageName(int ac, const char *const *av, int& i)
{
SimpleString packageName = getParameterField(ac, av, i, "-k");
if (packageName.size() == 0) return;
@@ -235,7 +395,7 @@ void CommandLineArguments::SetPackageName(int ac, const char** av, int& i)
packageName_ = packageName;
}
-bool CommandLineArguments::SetOutputType(int ac, const char** av, int& i)
+bool CommandLineArguments::setOutputType(int ac, const char *const *av, int& i)
{
SimpleString outputType = getParameterField(ac, av, i, "-o");
if (outputType.size() == 0) return false;
diff --git a/src/CppUTest/CommandLineTestRunner.cpp b/src/CppUTest/CommandLineTestRunner.cpp
old mode 100755
new mode 100644
index 43d2dec5c..b50e897e7
--- a/src/CppUTest/CommandLineTestRunner.cpp
+++ b/src/CppUTest/CommandLineTestRunner.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -34,10 +34,10 @@
int CommandLineTestRunner::RunAllTests(int ac, char** av)
{
- return RunAllTests(ac, (const char**) av);
+ return RunAllTests(ac, (const char *const *) av);
}
-int CommandLineTestRunner::RunAllTests(int ac, const char** av)
+int CommandLineTestRunner::RunAllTests(int ac, const char *const *av)
{
int result = 0;
ConsoleTestOutput backupOutput;
@@ -58,8 +58,8 @@ int CommandLineTestRunner::RunAllTests(int ac, const char** av)
return result;
}
-CommandLineTestRunner::CommandLineTestRunner(int ac, const char** av, TestRegistry* registry) :
- output_(NULL), arguments_(NULL), registry_(registry)
+CommandLineTestRunner::CommandLineTestRunner(int ac, const char *const *av, TestRegistry* registry) :
+ output_(NULLPTR), arguments_(NULLPTR), registry_(registry)
{
arguments_ = new CommandLineArguments(ac, av);
}
@@ -72,7 +72,7 @@ CommandLineTestRunner::~CommandLineTestRunner()
int CommandLineTestRunner::runAllTestsMain()
{
- int testResult = 0;
+ int testResult = 1;
SetPointerPlugin pPlugin(DEF_PLUGIN_SET_POINTER);
registry_->installPlugin(&pPlugin);
@@ -88,19 +88,24 @@ void CommandLineTestRunner::initializeTestRun()
{
registry_->setGroupFilters(arguments_->getGroupFilters());
registry_->setNameFilters(arguments_->getNameFilters());
-
- if (arguments_->isVerbose()) output_->verbose();
+
+ if (arguments_->isVerbose()) output_->verbose(TestOutput::level_verbose);
+ if (arguments_->isVeryVerbose()) output_->verbose(TestOutput::level_veryVerbose);
if (arguments_->isColor()) output_->color();
if (arguments_->runTestsInSeperateProcess()) registry_->setRunTestsInSeperateProcess();
if (arguments_->isRunIgnored()) registry_->setRunIgnored();
+ if (arguments_->isCrashingOnFail()) UtestShell::setCrashOnFail();
+
+ UtestShell::setRethrowExceptions( arguments_->isRethrowingExceptions() );
}
int CommandLineTestRunner::runAllTests()
{
initializeTestRun();
- int loopCount = 0;
- int failureCount = 0;
- int repeat_ = arguments_->getRepeatCount();
+ size_t loopCount = 0;
+ size_t failedTestCount = 0;
+ size_t failedExecutionCount = 0;
+ size_t repeatCount = arguments_->getRepeatCount();
if (arguments_->isListingTestGroupNames())
{
@@ -116,14 +121,36 @@ int CommandLineTestRunner::runAllTests()
return 0;
}
- while (loopCount++ < repeat_) {
- output_->printTestRun(loopCount, repeat_);
+ if (arguments_->isListingTestLocations())
+ {
TestResult tr(*output_);
- registry_->runAllTests(tr);
- failureCount += tr.getFailureCount();
+ registry_->listTestLocations(tr);
+ return 0;
}
- return failureCount;
+ if (arguments_->isReversing())
+ registry_->reverseTests();
+
+ if (arguments_->isShuffling())
+ {
+ output_->print("Test order shuffling enabled with seed: ");
+ output_->print(arguments_->getShuffleSeed());
+ output_->print("\n");
+ }
+ while (loopCount++ < repeatCount) {
+
+ if (arguments_->isShuffling())
+ registry_->shuffleTests(arguments_->getShuffleSeed());
+
+ output_->printTestRun(loopCount, repeatCount);
+ TestResult tr(*output_);
+ registry_->runAllTests(tr);
+ failedTestCount += tr.getFailureCount();
+ if (tr.isFailure()) {
+ failedExecutionCount++;
+ }
+ }
+ return (int) (failedTestCount != 0 ? failedTestCount : failedExecutionCount);
}
TestOutput* CommandLineTestRunner::createTeamCityOutput()
@@ -134,7 +161,7 @@ TestOutput* CommandLineTestRunner::createTeamCityOutput()
TestOutput* CommandLineTestRunner::createJUnitOutput(const SimpleString& packageName)
{
JUnitTestOutput* junitOutput = new JUnitTestOutput;
- if (junitOutput != NULL) {
+ if (junitOutput != NULLPTR) {
junitOutput->setPackageName(packageName);
}
return junitOutput;
@@ -157,13 +184,13 @@ bool CommandLineTestRunner::parseArguments(TestPlugin* plugin)
{
if (!arguments_->parse(plugin)) {
output_ = createConsoleOutput();
- output_->print(arguments_->usage());
+ output_->print((arguments_->needHelp()) ? arguments_->help() : arguments_->usage());
return false;
}
if (arguments_->isJUnitOutput()) {
output_= createJUnitOutput(arguments_->getPackageName());
- if (arguments_->isVerbose())
+ if (arguments_->isVerbose() || arguments_->isVeryVerbose())
output_ = createCompositeOutput(output_, createConsoleOutput());
} else if (arguments_->isTeamCityOutput()) {
output_ = createTeamCityOutput();
diff --git a/src/CppUTest/JUnitTestOutput.cpp b/src/CppUTest/JUnitTestOutput.cpp
index 929f9dd8f..f509d9b72 100644
--- a/src/CppUTest/JUnitTestOutput.cpp
+++ b/src/CppUTest/JUnitTestOutput.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -34,28 +34,32 @@
struct JUnitTestCaseResultNode
{
JUnitTestCaseResultNode() :
- execTime_(0), failure_(0), ignored_(false), next_(0)
+ execTime_(0), failure_(NULLPTR), ignored_(false), lineNumber_ (0), checkCount_ (0), next_(NULLPTR)
{
}
SimpleString name_;
- long execTime_;
+ size_t execTime_;
TestFailure* failure_;
bool ignored_;
+ SimpleString file_;
+ size_t lineNumber_;
+ size_t checkCount_;
JUnitTestCaseResultNode* next_;
};
struct JUnitTestGroupResult
{
JUnitTestGroupResult() :
- testCount_(0), failureCount_(0), startTime_(0), groupExecTime_(0), head_(0), tail_(0)
+ testCount_(0), failureCount_(0), totalCheckCount_(0), startTime_(0), groupExecTime_(0), head_(NULLPTR), tail_(NULLPTR)
{
}
- int testCount_;
- int failureCount_;
- long startTime_;
- long groupExecTime_;
+ size_t testCount_;
+ size_t failureCount_;
+ size_t totalCheckCount_;
+ size_t startTime_;
+ size_t groupExecTime_;
SimpleString group_;
JUnitTestCaseResultNode* head_;
JUnitTestCaseResultNode* tail_;
@@ -66,6 +70,7 @@ struct JUnitTestOutputImpl
JUnitTestGroupResult results_;
PlatformSpecificFile file_;
SimpleString package_;
+ SimpleString stdOutput_;
};
JUnitTestOutput::JUnitTestOutput() :
@@ -87,13 +92,12 @@ void JUnitTestOutput::resetTestGroupResult()
JUnitTestCaseResultNode* cur = impl_->results_.head_;
while (cur) {
JUnitTestCaseResultNode* tmp = cur->next_;
- ;
delete cur->failure_;
delete cur;
cur = tmp;
}
- impl_->results_.head_ = 0;
- impl_->results_.tail_ = 0;
+ impl_->results_.head_ = NULLPTR;
+ impl_->results_.tail_ = NULLPTR;
}
void JUnitTestOutput::printTestsStarted()
@@ -106,8 +110,8 @@ void JUnitTestOutput::printCurrentGroupStarted(const UtestShell& /*test*/)
void JUnitTestOutput::printCurrentTestEnded(const TestResult& result)
{
- impl_->results_.tail_->execTime_
- = result.getCurrentTestTotalExecutionTime();
+ impl_->results_.tail_->execTime_ = result.getCurrentTestTotalExecutionTime();
+ impl_->results_.tail_->checkCount_ = result.getCheckCount();
}
void JUnitTestOutput::printTestsEnded(const TestResult& /*result*/)
@@ -125,9 +129,9 @@ void JUnitTestOutput::printCurrentTestStarted(const UtestShell& test)
{
impl_->results_.testCount_++;
impl_->results_.group_ = test.getGroup();
- impl_->results_.startTime_ = GetPlatformSpecificTimeInMillis();
+ impl_->results_.startTime_ = (size_t) GetPlatformSpecificTimeInMillis();
- if (impl_->results_.tail_ == 0) {
+ if (impl_->results_.tail_ == NULLPTR) {
impl_->results_.head_ = impl_->results_.tail_
= new JUnitTestCaseResultNode;
}
@@ -136,6 +140,8 @@ void JUnitTestOutput::printCurrentTestStarted(const UtestShell& test)
impl_->results_.tail_ = impl_->results_.tail_->next_;
}
impl_->results_.tail_->name_ = test.getName();
+ impl_->results_.tail_->file_ = test.getFile();
+ impl_->results_.tail_->lineNumber_ = test.getLineNumber();
if (!test.willRun()) {
impl_->results_.tail_->ignored_ = true;
}
@@ -144,15 +150,29 @@ void JUnitTestOutput::printCurrentTestStarted(const UtestShell& test)
SimpleString JUnitTestOutput::createFileName(const SimpleString& group)
{
SimpleString fileName = "cpputest_";
+ if (!impl_->package_.isEmpty()) {
+ fileName += impl_->package_;
+ fileName += "_";
+ }
fileName += group;
- fileName.replace('/', '_');
- fileName += ".xml";
- return fileName;
+ return encodeFileName(fileName) + ".xml";
+}
+
+SimpleString JUnitTestOutput::encodeFileName(const SimpleString& fileName)
+{
+ // special character list based on: https://en.wikipedia.org/wiki/Filename
+ static const char* const forbiddenCharacters = "/\\?%*:|\"<>";
+
+ SimpleString result = fileName;
+ for (const char* sym = forbiddenCharacters; *sym; ++sym) {
+ result.replace(*sym, '_');
+ }
+ return result;
}
void JUnitTestOutput::setPackageName(const SimpleString& package)
{
- if (impl_ != NULL) {
+ if (impl_ != NULLPTR) {
impl_->package_ = package;
}
}
@@ -168,9 +188,9 @@ void JUnitTestOutput::writeTestSuiteSummary()
buf =
StringFromFormat(
"\n",
- impl_->results_.failureCount_,
+ (int)impl_->results_.failureCount_,
impl_->results_.group_.asCharString(),
- impl_->results_.testCount_,
+ (int) impl_->results_.testCount_,
(int) (impl_->results_.groupExecTime_ / 1000), (int) (impl_->results_.groupExecTime_ % 1000),
GetPlatformSpecificTimeString());
writeToFile(buf.asCharString());
@@ -182,18 +202,37 @@ void JUnitTestOutput::writeProperties()
writeToFile("\n");
}
+SimpleString JUnitTestOutput::encodeXmlText(const SimpleString& textbody)
+{
+ SimpleString buf = textbody.asCharString();
+ buf.replace("&", "&");
+ buf.replace("\"", """);
+ buf.replace("<", "<");
+ buf.replace(">", ">");
+ buf.replace("\r", "
");
+ buf.replace("\n", "
");
+ return buf;
+}
+
void JUnitTestOutput::writeTestCases()
{
JUnitTestCaseResultNode* cur = impl_->results_.head_;
+
while (cur) {
SimpleString buf = StringFromFormat(
- "\n",
+ "\n",
impl_->package_.asCharString(),
- impl_->package_.isEmpty() == true ? "" : ".",
+ impl_->package_.isEmpty() ? "" : ".",
impl_->results_.group_.asCharString(),
- cur->name_.asCharString(), (int) (cur->execTime_ / 1000), (int)(cur->execTime_ % 1000));
+ cur->name_.asCharString(),
+ (int) (cur->checkCount_ - impl_->results_.totalCheckCount_),
+ (int) (cur->execTime_ / 1000), (int)(cur->execTime_ % 1000),
+ cur->file_.asCharString(),
+ (int) cur->lineNumber_);
writeToFile(buf.asCharString());
+ impl_->results_.totalCheckCount_ = cur->checkCount_;
+
if (cur->failure_) {
writeFailure(cur);
}
@@ -207,25 +246,23 @@ void JUnitTestOutput::writeTestCases()
void JUnitTestOutput::writeFailure(JUnitTestCaseResultNode* node)
{
- SimpleString message = node->failure_->getMessage().asCharString();
- message.replace('"', '\'');
- message.replace('<', '[');
- message.replace('>', ']');
- message.replace("&", "&");
- message.replace("\n", "{newline}");
SimpleString buf = StringFromFormat(
"\n",
node->failure_->getFileName().asCharString(),
- node->failure_->getFailureLineNumber(), message.asCharString());
+ (int) node->failure_->getFailureLineNumber(),
+ encodeXmlText(node->failure_->getMessage()).asCharString());
writeToFile(buf.asCharString());
writeToFile("\n");
}
+
void JUnitTestOutput::writeFileEnding()
{
- writeToFile("\n");
+ writeToFile("");
+ writeToFile(encodeXmlText(impl_->stdOutput_));
+ writeToFile("\n");
writeToFile("\n");
- writeToFile("");
+ writeToFile("\n");
}
void JUnitTestOutput::writeTestGroupToFile()
@@ -245,14 +282,19 @@ void JUnitTestOutput::printBuffer(const char*)
{
}
-void JUnitTestOutput::print(const char*)
+void JUnitTestOutput::print(const char *output)
{
+ impl_->stdOutput_ += output;
}
void JUnitTestOutput::print(long)
{
}
+void JUnitTestOutput::print(size_t)
+{
+}
+
void JUnitTestOutput::flush()
{
}
@@ -261,7 +303,7 @@ void JUnitTestOutput::flush()
void JUnitTestOutput::printFailure(const TestFailure& failure)
{
- if (impl_->results_.tail_->failure_ == 0) {
+ if (impl_->results_.tail_->failure_ == NULLPTR) {
impl_->results_.failureCount_++;
impl_->results_.tail_->failure_ = new TestFailure(failure);
}
diff --git a/src/CppUTest/MemoryLeakDetector.cpp b/src/CppUTest/MemoryLeakDetector.cpp
index 19cab29c9..89e45908e 100644
--- a/src/CppUTest/MemoryLeakDetector.cpp
+++ b/src/CppUTest/MemoryLeakDetector.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -30,7 +30,9 @@
#include "CppUTest/PlatformSpecificFunctions.h"
#include "CppUTest/SimpleMutex.h"
-#define UNKNOWN ((char*)(""))
+static const char* UNKNOWN = "";
+
+static const char GuardBytes[] = {'B','A','S'};
SimpleStringBuffer::SimpleStringBuffer() :
positions_filled_(0), write_limit_(SIMPLE_STRING_BUFFER_LEN-1)
@@ -46,13 +48,12 @@ void SimpleStringBuffer::clear()
void SimpleStringBuffer::add(const char* format, ...)
{
- int count = 0;
- size_t positions_left = write_limit_ - positions_filled_;
- if (positions_left <= 0) return;
+ const size_t positions_left = write_limit_ - positions_filled_;
+ if (positions_left == 0) return;
va_list arguments;
va_start(arguments, format);
- count = PlatformSpecificVSNprintf(buffer_ + positions_filled_, positions_left+1, format, arguments);
+ const int count = PlatformSpecificVSNprintf(buffer_ + positions_filled_, positions_left+1, format, arguments);
if (count > 0) positions_filled_ += (size_t) count;
if (positions_filled_ > write_limit_) positions_filled_ = write_limit_;
va_end(arguments);
@@ -63,7 +64,7 @@ void SimpleStringBuffer::addMemoryDump(const void* memory, size_t memorySize)
const unsigned char* byteMemory = (const unsigned char*)memory;
const size_t maxLineBytes = 16;
size_t currentPos = 0;
- size_t p;
+ size_t p;
while (currentPos < memorySize) {
add(" %04lx: ", (unsigned long) currentPos);
@@ -134,14 +135,14 @@ MemoryLeakOutputStringBuffer::MemoryLeakOutputStringBuffer()
{
}
-void MemoryLeakOutputStringBuffer::addAllocationLocation(const char* allocationFile, int allocationLineNumber, size_t allocationSize, TestMemoryAllocator* allocator)
+void MemoryLeakOutputStringBuffer::addAllocationLocation(const char* allocationFile, size_t allocationLineNumber, size_t allocationSize, TestMemoryAllocator* allocator)
{
- outputBuffer_.add(" allocated at file: %s line: %d size: %lu type: %s\n", allocationFile, allocationLineNumber, (unsigned long) allocationSize, allocator->alloc_name());
+ outputBuffer_.add(" allocated at file: %s line: %d size: %lu type: %s\n", allocationFile, (int) allocationLineNumber, (unsigned long) allocationSize, allocator->alloc_name());
}
-void MemoryLeakOutputStringBuffer::addDeallocationLocation(const char* freeFile, int freeLineNumber, TestMemoryAllocator* allocator)
+void MemoryLeakOutputStringBuffer::addDeallocationLocation(const char* freeFile, size_t freeLineNumber, TestMemoryAllocator* allocator)
{
- outputBuffer_.add(" deallocated at file: %s line: %d type: %s\n", freeFile, freeLineNumber, allocator->free_name());
+ outputBuffer_.add(" deallocated at file: %s line: %d type: %s\n", freeFile, (int) freeLineNumber, allocator->free_name());
}
void MemoryLeakOutputStringBuffer::addNoMemoryLeaksMessage()
@@ -168,7 +169,7 @@ void MemoryLeakOutputStringBuffer::reportMemoryLeak(MemoryLeakDetectorNode* leak
total_leaks_++;
outputBuffer_.add("Alloc num (%u) Leak size: %lu Allocated at: %s and line: %d. Type: \"%s\"\n\tMemory: <%p> Content:\n",
- leak->number_, (unsigned long) leak->size_, leak->file_, leak->line_, leak->allocator_->alloc_name(), (void*) leak->memory_);
+ leak->number_, (unsigned long) leak->size_, leak->file_, (int) leak->line_, leak->allocator_->alloc_name(), (void*) leak->memory_);
outputBuffer_.addMemoryDump(leak->memory_, leak->size_);
if (SimpleString::StrCmp(leak->allocator_->alloc_name(), (const char*) "malloc") == 0)
@@ -205,9 +206,9 @@ void MemoryLeakOutputStringBuffer::addErrorMessageForTooMuchLeaks()
outputBuffer_.add(MEM_LEAK_TOO_MUCH);
}
-void MemoryLeakOutputStringBuffer::addMemoryLeakFooter(int amountOfLeaks)
+void MemoryLeakOutputStringBuffer::addMemoryLeakFooter(size_t amountOfLeaks)
{
- outputBuffer_.add("%s %d\n", MEM_LEAK_FOOTER, amountOfLeaks);
+ outputBuffer_.add("%s %d\n", MEM_LEAK_FOOTER, (int) amountOfLeaks);
}
void MemoryLeakOutputStringBuffer::addWarningForUsingMalloc()
@@ -215,22 +216,22 @@ void MemoryLeakOutputStringBuffer::addWarningForUsingMalloc()
outputBuffer_.add(MEM_LEAK_ADDITION_MALLOC_WARNING);
}
-void MemoryLeakOutputStringBuffer::reportDeallocateNonAllocatedMemoryFailure(const char* freeFile, int freeLine, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
+void MemoryLeakOutputStringBuffer::reportDeallocateNonAllocatedMemoryFailure(const char* freeFile, size_t freeLine, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
{
reportFailure("Deallocating non-allocated memory\n", "", 0, 0, NullUnknownAllocator::defaultAllocator(), freeFile, freeLine, freeAllocator, reporter);
}
-void MemoryLeakOutputStringBuffer::reportAllocationDeallocationMismatchFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
+void MemoryLeakOutputStringBuffer::reportAllocationDeallocationMismatchFailure(MemoryLeakDetectorNode* node, const char* freeFile, size_t freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
{
reportFailure("Allocation/deallocation type mismatch\n", node->file_, node->line_, node->size_, node->allocator_, freeFile, freeLineNumber, freeAllocator, reporter);
}
-void MemoryLeakOutputStringBuffer::reportMemoryCorruptionFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
+void MemoryLeakOutputStringBuffer::reportMemoryCorruptionFailure(MemoryLeakDetectorNode* node, const char* freeFile, size_t freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
{
reportFailure("Memory corruption (written out of bounds?)\n", node->file_, node->line_, node->size_, node->allocator_, freeFile, freeLineNumber, freeAllocator, reporter);
}
-void MemoryLeakOutputStringBuffer::reportFailure(const char* message, const char* allocFile, int allocLine, size_t allocSize, TestMemoryAllocator* allocAllocator, const char* freeFile, int freeLine,
+void MemoryLeakOutputStringBuffer::reportFailure(const char* message, const char* allocFile, size_t allocLine, size_t allocSize, TestMemoryAllocator* allocAllocator, const char* freeFile, size_t freeLine,
TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
{
outputBuffer_.add("%s", message);
@@ -252,13 +253,14 @@ void MemoryLeakOutputStringBuffer::clear()
////////////////////////
-void MemoryLeakDetectorNode::init(char* memory, unsigned number, size_t size, TestMemoryAllocator* allocator, MemLeakPeriod period, const char* file, int line)
+void MemoryLeakDetectorNode::init(char* memory, unsigned number, size_t size, TestMemoryAllocator* allocator, MemLeakPeriod period, unsigned char allocation_stage, const char* file, size_t line)
{
number_ = number;
memory_ = memory;
size_ = size;
allocator_ = allocator;
period_ = period;
+ allocation_stage_ = allocation_stage;
file_ = file;
line_ = line;
}
@@ -270,10 +272,15 @@ bool MemoryLeakDetectorList::isInPeriod(MemoryLeakDetectorNode* node, MemLeakPer
return period == mem_leak_period_all || node->period_ == period || (node->period_ != mem_leak_period_disabled && period == mem_leak_period_enabled);
}
+bool MemoryLeakDetectorList::isInAllocationStage(MemoryLeakDetectorNode* node, unsigned char allocation_stage)
+{
+ return node->allocation_stage_ == allocation_stage;
+}
+
void MemoryLeakDetectorList::clearAllAccounting(MemLeakPeriod period)
{
MemoryLeakDetectorNode* cur = head_;
- MemoryLeakDetectorNode* prev = 0;
+ MemoryLeakDetectorNode* prev = NULLPTR;
while (cur) {
if (isInPeriod(cur, period)) {
@@ -301,7 +308,7 @@ void MemoryLeakDetectorList::addNewNode(MemoryLeakDetectorNode* node)
MemoryLeakDetectorNode* MemoryLeakDetectorList::removeNode(char* memory)
{
MemoryLeakDetectorNode* cur = head_;
- MemoryLeakDetectorNode* prev = 0;
+ MemoryLeakDetectorNode* prev = NULLPTR;
while (cur) {
if (cur->memory_ == memory) {
if (prev) {
@@ -316,7 +323,7 @@ MemoryLeakDetectorNode* MemoryLeakDetectorList::removeNode(char* memory)
prev = cur;
cur = cur->next_;
}
- return 0;
+ return NULLPTR;
}
MemoryLeakDetectorNode* MemoryLeakDetectorList::retrieveNode(char* memory)
@@ -327,14 +334,21 @@ MemoryLeakDetectorNode* MemoryLeakDetectorList::retrieveNode(char* memory)
return cur;
cur = cur->next_;
}
- return NULL;
+ return NULLPTR;
}
MemoryLeakDetectorNode* MemoryLeakDetectorList::getLeakFrom(MemoryLeakDetectorNode* node, MemLeakPeriod period)
{
for (MemoryLeakDetectorNode* cur = node; cur; cur = cur->next_)
if (isInPeriod(cur, period)) return cur;
- return 0;
+ return NULLPTR;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorList::getLeakForAllocationStageFrom(MemoryLeakDetectorNode* node, unsigned char allocation_stage)
+{
+ for (MemoryLeakDetectorNode* cur = node; cur; cur = cur->next_)
+ if (isInAllocationStage(cur, allocation_stage)) return cur;
+ return NULLPTR;
}
MemoryLeakDetectorNode* MemoryLeakDetectorList::getFirstLeak(MemLeakPeriod period)
@@ -342,14 +356,26 @@ MemoryLeakDetectorNode* MemoryLeakDetectorList::getFirstLeak(MemLeakPeriod perio
return getLeakFrom(head_, period);
}
+MemoryLeakDetectorNode* MemoryLeakDetectorList::getFirstLeakForAllocationStage(unsigned char allocation_stage)
+{
+ return getLeakForAllocationStageFrom(head_, allocation_stage);
+}
+
MemoryLeakDetectorNode* MemoryLeakDetectorList::getNextLeak(MemoryLeakDetectorNode* node, MemLeakPeriod period)
{
return getLeakFrom(node->next_, period);
}
-int MemoryLeakDetectorList::getTotalLeaks(MemLeakPeriod period)
+MemoryLeakDetectorNode* MemoryLeakDetectorList::getNextLeakForAllocationStage(MemoryLeakDetectorNode* node, unsigned char allocation_stage)
{
- int total_leaks = 0;
+ return getLeakForAllocationStageFrom(node->next_, allocation_stage);
+}
+
+
+
+size_t MemoryLeakDetectorList::getTotalLeaks(MemLeakPeriod period)
+{
+ size_t total_leaks = 0;
for (MemoryLeakDetectorNode* node = head_; node; node = node->next_) {
if (isInPeriod(node, period)) total_leaks++;
}
@@ -384,9 +410,9 @@ MemoryLeakDetectorNode* MemoryLeakDetectorTable::retrieveNode(char* memory)
return table_[hash(memory)].retrieveNode(memory);
}
-int MemoryLeakDetectorTable::getTotalLeaks(MemLeakPeriod period)
+size_t MemoryLeakDetectorTable::getTotalLeaks(MemLeakPeriod period)
{
- int total_leaks = 0;
+ size_t total_leaks = 0;
for (int i = 0; i < hash_prime; i++)
total_leaks += table_[i].getTotalLeaks(period);
return total_leaks;
@@ -398,7 +424,16 @@ MemoryLeakDetectorNode* MemoryLeakDetectorTable::getFirstLeak(MemLeakPeriod peri
MemoryLeakDetectorNode* node = table_[i].getFirstLeak(period);
if (node) return node;
}
- return 0;
+ return NULLPTR;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorTable::getFirstLeakForAllocationStage(unsigned char allocation_stage)
+{
+ for (int i = 0; i < hash_prime; i++) {
+ MemoryLeakDetectorNode* node = table_[i].getFirstLeakForAllocationStage(allocation_stage);
+ if (node) return node;
+ }
+ return NULLPTR;
}
MemoryLeakDetectorNode* MemoryLeakDetectorTable::getNextLeak(MemoryLeakDetectorNode* leak, MemLeakPeriod period)
@@ -411,7 +446,20 @@ MemoryLeakDetectorNode* MemoryLeakDetectorTable::getNextLeak(MemoryLeakDetectorN
node = table_[i].getFirstLeak(period);
if (node) return node;
}
- return 0;
+ return NULLPTR;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorTable::getNextLeakForAllocationStage(MemoryLeakDetectorNode* leak, unsigned char allocation_stage)
+{
+ unsigned long i = hash(leak->memory_);
+ MemoryLeakDetectorNode* node = table_[i].getNextLeakForAllocationStage(leak, allocation_stage);
+ if (node) return node;
+
+ for (++i; i < hash_prime; i++) {
+ node = table_[i].getFirstLeakForAllocationStage(allocation_stage);
+ if (node) return node;
+ }
+ return NULLPTR;
}
/////////////////////////////////////////////////////////////
@@ -421,6 +469,7 @@ MemoryLeakDetector::MemoryLeakDetector(MemoryLeakFailure* reporter)
doAllocationTypeChecking_ = true;
allocationSequenceNumber_ = 1;
current_period_ = mem_leak_period_disabled;
+ current_allocation_stage_ = 0;
reporter_ = reporter;
mutex_ = new SimpleMutex;
}
@@ -449,6 +498,11 @@ void MemoryLeakDetector::stopChecking()
current_period_ = mem_leak_period_enabled;
}
+unsigned char MemoryLeakDetector::getCurrentAllocationStage() const
+{
+ return current_allocation_stage_;
+}
+
void MemoryLeakDetector::enable()
{
current_period_ = mem_leak_period_enabled;
@@ -474,6 +528,16 @@ unsigned MemoryLeakDetector::getCurrentAllocationNumber()
return allocationSequenceNumber_;
}
+void MemoryLeakDetector::increaseAllocationStage()
+{
+ current_allocation_stage_++;
+}
+
+void MemoryLeakDetector::decreaseAllocationStage()
+{
+ current_allocation_stage_--;
+}
+
SimpleMutex *MemoryLeakDetector::getMutex()
{
return mutex_;
@@ -481,7 +545,11 @@ SimpleMutex *MemoryLeakDetector::getMutex()
static size_t calculateVoidPointerAlignedSize(size_t size)
{
+#ifndef CPPUTEST_DISABLE_MEM_CORRUPTION_CHECK
return (sizeof(void*) - (size % sizeof(void*))) + size;
+#else
+ return size;
+#endif
}
size_t MemoryLeakDetector::sizeOfMemoryWithCorruptionInfo(size_t size)
@@ -494,17 +562,17 @@ MemoryLeakDetectorNode* MemoryLeakDetector::getNodeFromMemoryPointer(char* memor
return (MemoryLeakDetectorNode*) (void*) (memory + sizeOfMemoryWithCorruptionInfo(memory_size));
}
-void MemoryLeakDetector::storeLeakInformation(MemoryLeakDetectorNode * node, char *new_memory, size_t size, TestMemoryAllocator *allocator, const char *file, int line)
+void MemoryLeakDetector::storeLeakInformation(MemoryLeakDetectorNode * node, char *new_memory, size_t size, TestMemoryAllocator *allocator, const char *file, size_t line)
{
- node->init(new_memory, allocationSequenceNumber_++, size, allocator, current_period_, file, line);
+ node->init(new_memory, allocationSequenceNumber_++, size, allocator, current_period_, current_allocation_stage_, file, line);
addMemoryCorruptionInformation(node->memory_ + node->size_);
memoryTable_.addNewNode(node);
}
-char* MemoryLeakDetector::reallocateMemoryAndLeakInformation(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately)
+char* MemoryLeakDetector::reallocateMemoryAndLeakInformation(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, size_t line, bool allocatNodesSeperately)
{
char* new_memory = reallocateMemoryWithAccountingInformation(allocator, memory, size, file, line, allocatNodesSeperately);
- if (new_memory == NULL) return NULL;
+ if (new_memory == NULLPTR) return NULLPTR;
MemoryLeakDetectorNode *node = createMemoryLeakAccountingInformation(allocator, size, new_memory, allocatNodesSeperately);
storeLeakInformation(node, new_memory, size, allocator, file, line);
@@ -513,21 +581,25 @@ char* MemoryLeakDetector::reallocateMemoryAndLeakInformation(TestMemoryAllocator
void MemoryLeakDetector::invalidateMemory(char* memory)
{
+#ifndef CPPUTEST_DISABLE_HEAP_POISON
MemoryLeakDetectorNode* node = memoryTable_.retrieveNode(memory);
if (node)
PlatformSpecificMemset(memory, 0xCD, node->size_);
+#endif
}
void MemoryLeakDetector::addMemoryCorruptionInformation(char* memory)
{
- memory[0] = 'B';
- memory[1] = 'A';
- memory[2] = 'S';
+ for (size_t i=0; iisOfEqualType(alloc_allocator);
}
-void MemoryLeakDetector::checkForCorruption(MemoryLeakDetectorNode* node, const char* file, int line, TestMemoryAllocator* allocator, bool allocateNodesSeperately)
+void MemoryLeakDetector::checkForCorruption(MemoryLeakDetectorNode* node, const char* file, size_t line, TestMemoryAllocator* allocator, bool allocateNodesSeperately)
{
- if (!matchingAllocation(node->allocator_, allocator))
- outputBuffer_.reportAllocationDeallocationMismatchFailure(node, file, line, allocator, reporter_);
+ if (!matchingAllocation(node->allocator_->actualAllocator(), allocator->actualAllocator()))
+ outputBuffer_.reportAllocationDeallocationMismatchFailure(node, file, line, allocator->actualAllocator(), reporter_);
else if (!validMemoryCorruptionInformation(node->memory_ + node->size_))
- outputBuffer_.reportMemoryCorruptionFailure(node, file, line, allocator, reporter_);
+ outputBuffer_.reportMemoryCorruptionFailure(node, file, line, allocator->actualAllocator(), reporter_);
else if (allocateNodesSeperately)
allocator->freeMemoryLeakNode((char*) node);
}
@@ -552,13 +624,13 @@ char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t siz
return allocMemory(allocator, size, UNKNOWN, 0, allocatNodesSeperately);
}
-char* MemoryLeakDetector::allocateMemoryWithAccountingInformation(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately)
+char* MemoryLeakDetector::allocateMemoryWithAccountingInformation(TestMemoryAllocator* allocator, size_t size, const char* file, size_t line, bool allocatNodesSeperately)
{
if (allocatNodesSeperately) return allocator->alloc_memory(sizeOfMemoryWithCorruptionInfo(size), file, line);
else return allocator->alloc_memory(sizeOfMemoryWithCorruptionInfo(size) + sizeof(MemoryLeakDetectorNode), file, line);
}
-char* MemoryLeakDetector::reallocateMemoryWithAccountingInformation(TestMemoryAllocator* /*allocator*/, char* memory, size_t size, const char* /*file*/, int /*line*/, bool allocatNodesSeperately)
+char* MemoryLeakDetector::reallocateMemoryWithAccountingInformation(TestMemoryAllocator* /*allocator*/, char* memory, size_t size, const char* /*file*/, size_t /*line*/, bool allocatNodesSeperately)
{
if (allocatNodesSeperately) return (char*) PlatformSpecificRealloc(memory, sizeOfMemoryWithCorruptionInfo(size));
else return (char*) PlatformSpecificRealloc(memory, sizeOfMemoryWithCorruptionInfo(size) + sizeof(MemoryLeakDetectorNode));
@@ -570,8 +642,11 @@ MemoryLeakDetectorNode* MemoryLeakDetector::createMemoryLeakAccountingInformatio
else return getNodeFromMemoryPointer(memory, size);
}
-char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately)
+char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t size, const char* file, size_t line, bool allocatNodesSeperately)
{
+#ifdef CPPUTEST_DISABLE_MEM_CORRUPTION_CHECK
+ allocatNodesSeperately = true;
+#endif
/* With malloc, it is harder to guarantee that the allocator free is called.
* This is because operator new is overloaded via linker symbols, but malloc just via #defines.
* If the same allocation is used and the wrong free is called, it will deallocate the memory leak information
@@ -580,7 +655,7 @@ char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t siz
*/
char* memory = allocateMemoryWithAccountingInformation(allocator, size, file, line, allocatNodesSeperately);
- if (memory == NULL) return NULL;
+ if (memory == NULLPTR) return NULLPTR;
MemoryLeakDetectorNode* node = createMemoryLeakAccountingInformation(allocator, size, memory, allocatNodesSeperately);
storeLeakInformation(node, memory, size, allocator, file, line);
@@ -593,18 +668,22 @@ void MemoryLeakDetector::removeMemoryLeakInformationWithoutCheckingOrDeallocatin
if (allocatNodesSeperately) allocator->freeMemoryLeakNode( (char*) node);
}
-void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* memory, const char* file, int line, bool allocatNodesSeperately)
+void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* memory, const char* file, size_t line, bool allocatNodesSeperately)
{
- if (memory == 0) return;
+ if (memory == NULLPTR) return;
MemoryLeakDetectorNode* node = memoryTable_.removeNode((char*) memory);
- if (node == NULL) {
+ if (node == NULLPTR) {
outputBuffer_.reportDeallocateNonAllocatedMemoryFailure(file, line, allocator, reporter_);
return;
}
+#ifdef CPPUTEST_DISABLE_MEM_CORRUPTION_CHECK
+ allocatNodesSeperately = true;
+#endif
if (!allocator->hasBeenDestroyed()) {
+ size_t size = node->size_;
checkForCorruption(node, file, line, allocator, allocatNodesSeperately);
- allocator->free_memory((char*) memory, file, line);
+ allocator->free_memory((char*) memory, size, file, line);
}
}
@@ -613,13 +692,28 @@ void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* mem
deallocMemory(allocator, (char*) memory, UNKNOWN, 0, allocatNodesSeperately);
}
-char* MemoryLeakDetector::reallocMemory(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately)
+void MemoryLeakDetector::deallocAllMemoryInCurrentAllocationStage()
+{
+ char* memory = NULLPTR;
+ MemoryLeakDetectorNode* node = memoryTable_.getFirstLeakForAllocationStage(current_allocation_stage_);
+ while (node) {
+ memory = node->memory_;
+ TestMemoryAllocator* allocator = node->allocator_;
+ node = memoryTable_.getNextLeakForAllocationStage(node, current_allocation_stage_);
+ deallocMemory(allocator, memory, __FILE__, __LINE__);
+ }
+}
+
+char* MemoryLeakDetector::reallocMemory(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, size_t line, bool allocatNodesSeperately)
{
+#ifdef CPPUTEST_DISABLE_MEM_CORRUPTION_CHECK
+ allocatNodesSeperately = true;
+#endif
if (memory) {
MemoryLeakDetectorNode* node = memoryTable_.removeNode(memory);
- if (node == NULL) {
+ if (node == NULLPTR) {
outputBuffer_.reportDeallocateNonAllocatedMemoryFailure(file, line, allocator, reporter_);
- return NULL;
+ return NULLPTR;
}
checkForCorruption(node, file, line, allocator, allocatNodesSeperately);
}
@@ -656,7 +750,7 @@ void MemoryLeakDetector::markCheckingPeriodLeaksAsNonCheckingPeriod()
}
}
-int MemoryLeakDetector::totalMemoryLeaks(MemLeakPeriod period)
+size_t MemoryLeakDetector::totalMemoryLeaks(MemLeakPeriod period)
{
return memoryTable_.getTotalLeaks(period);
}
diff --git a/src/CppUTest/MemoryLeakWarningPlugin.cpp b/src/CppUTest/MemoryLeakWarningPlugin.cpp
index 00d6e164a..e954d6338 100644
--- a/src/CppUTest/MemoryLeakWarningPlugin.cpp
+++ b/src/CppUTest/MemoryLeakWarningPlugin.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -44,80 +44,83 @@ class MemLeakScopedMutex
ScopedMutexLock lock;
};
-static void* threadsafe_mem_leak_malloc(size_t size, const char* file, int line)
+static void* threadsafe_mem_leak_malloc(size_t size, const char* file, size_t line)
{
MemLeakScopedMutex lock;
return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentMallocAllocator(), size, file, line, true);
}
-static void threadsafe_mem_leak_free(void* buffer, const char* file, int line)
+static void threadsafe_mem_leak_free(void* buffer, const char* file, size_t line)
{
MemLeakScopedMutex lock;
MemoryLeakWarningPlugin::getGlobalDetector()->invalidateMemory((char*) buffer);
MemoryLeakWarningPlugin::getGlobalDetector()->deallocMemory(getCurrentMallocAllocator(), (char*) buffer, file, line, true);
}
-static void* threadsafe_mem_leak_realloc(void* memory, size_t size, const char* file, int line)
+static void* threadsafe_mem_leak_realloc(void* memory, size_t size, const char* file, size_t line)
{
MemLeakScopedMutex lock;
return MemoryLeakWarningPlugin::getGlobalDetector()->reallocMemory(getCurrentMallocAllocator(), (char*) memory, size, file, line, true);
}
-static void* mem_leak_malloc(size_t size, const char* file, int line)
+static void* mem_leak_malloc(size_t size, const char* file, size_t line)
{
return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentMallocAllocator(), size, file, line, true);
}
-static void mem_leak_free(void* buffer, const char* file, int line)
+static void mem_leak_free(void* buffer, const char* file, size_t line)
{
MemoryLeakWarningPlugin::getGlobalDetector()->invalidateMemory((char*) buffer);
MemoryLeakWarningPlugin::getGlobalDetector()->deallocMemory(getCurrentMallocAllocator(), (char*) buffer, file, line, true);
}
-static void* mem_leak_realloc(void* memory, size_t size, const char* file, int line)
+static void* mem_leak_realloc(void* memory, size_t size, const char* file, size_t line)
{
return MemoryLeakWarningPlugin::getGlobalDetector()->reallocMemory(getCurrentMallocAllocator(), (char*) memory, size, file, line, true);
}
#endif
-static void* normal_malloc(size_t size, const char*, int)
+static void* normal_malloc(size_t size, const char*, size_t)
{
return PlatformSpecificMalloc(size);
}
-static void* normal_realloc(void* memory, size_t size, const char*, int)
+static void* normal_realloc(void* memory, size_t size, const char*, size_t)
{
return PlatformSpecificRealloc(memory, size);
}
-static void normal_free(void* buffer, const char*, int)
+static void normal_free(void* buffer, const char*, size_t)
{
PlatformSpecificFree(buffer);
}
#if CPPUTEST_USE_MEM_LEAK_DETECTION
-static void *(*malloc_fptr)(size_t size, const char* file, int line) = mem_leak_malloc;
-static void (*free_fptr)(void* mem, const char* file, int line) = mem_leak_free;
-static void*(*realloc_fptr)(void* memory, size_t size, const char* file, int line) = mem_leak_realloc;
+static void *(*malloc_fptr)(size_t size, const char* file, size_t line) = mem_leak_malloc;
+static void (*free_fptr)(void* mem, const char* file, size_t line) = mem_leak_free;
+static void*(*realloc_fptr)(void* memory, size_t size, const char* file, size_t line) = mem_leak_realloc;
+static void *(*saved_malloc_fptr)(size_t size, const char* file, size_t line) = mem_leak_malloc;
+static void (*saved_free_fptr)(void* mem, const char* file, size_t line) = mem_leak_free;
+static void*(*saved_realloc_fptr)(void* memory, size_t size, const char* file, size_t line) = mem_leak_realloc;
#else
-static void *(*malloc_fptr)(size_t size, const char* file, int line) = normal_malloc;
-static void (*free_fptr)(void* mem, const char* file, int line) = normal_free;
-static void*(*realloc_fptr)(void* memory, size_t size, const char* file, int line) = normal_realloc;
+static void *(*malloc_fptr)(size_t size, const char* file, size_t line) = normal_malloc;
+static void (*free_fptr)(void* mem, const char* file, size_t line) = normal_free;
+static void*(*realloc_fptr)(void* memory, size_t size, const char* file, size_t line) = normal_realloc;
#endif
-void* cpputest_malloc_location_with_leak_detection(size_t size, const char* file, int line)
+void* cpputest_malloc_location_with_leak_detection(size_t size, const char* file, size_t line)
{
return malloc_fptr(size, file, line);
}
-void* cpputest_realloc_location_with_leak_detection(void* memory, size_t size, const char* file, int line)
+void* cpputest_realloc_location_with_leak_detection(void* memory, size_t size, const char* file, size_t line)
{
return realloc_fptr(memory, size, file, line);
}
-void cpputest_free_location_with_leak_detection(void* buffer, const char* file, int line)
+void cpputest_free_location_with_leak_detection(void* buffer, const char* file, size_t line)
{
free_fptr(buffer, file, line);
}
@@ -127,13 +130,13 @@ void cpputest_free_location_with_leak_detection(void* buffer, const char* file,
#if CPPUTEST_USE_MEM_LEAK_DETECTION
#undef new
-#if CPPUTEST_USE_STD_CPP_LIB
-#define UT_THROW_BAD_ALLOC_WHEN_NULL(memory) if (memory == NULL) throw std::bad_alloc();
+#if CPPUTEST_HAVE_EXCEPTIONS
+#define UT_THROW_BAD_ALLOC_WHEN_NULL(memory) if ((memory) == NULLPTR) throw CPPUTEST_BAD_ALLOC()
#else
#define UT_THROW_BAD_ALLOC_WHEN_NULL(memory)
#endif
-static void* threadsafe_mem_leak_operator_new (size_t size) UT_THROW(std::bad_alloc)
+static void* threadsafe_mem_leak_operator_new (size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
MemLeakScopedMutex lock;
void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size);
@@ -147,15 +150,15 @@ static void* threadsafe_mem_leak_operator_new_nothrow (size_t size) UT_NOTHROW
return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size);
}
-static void* threadsafe_mem_leak_operator_new_debug (size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
+static void* threadsafe_mem_leak_operator_new_debug (size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC)
{
MemLeakScopedMutex lock;
- void *memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size, (char*) file, line);
+ void *memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size, file, line);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
return memory;
}
-static void* threadsafe_mem_leak_operator_new_array (size_t size) UT_THROW(std::bad_alloc)
+static void* threadsafe_mem_leak_operator_new_array (size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
MemLeakScopedMutex lock;
void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size);
@@ -169,10 +172,10 @@ static void* threadsafe_mem_leak_operator_new_array_nothrow (size_t size) UT_NOT
return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size);
}
-static void* threadsafe_mem_leak_operator_new_array_debug (size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
+static void* threadsafe_mem_leak_operator_new_array_debug (size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC)
{
MemLeakScopedMutex lock;
- void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size, (char*) file, line);
+ void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size, file, line);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
return memory;
}
@@ -192,7 +195,7 @@ static void threadsafe_mem_leak_operator_delete_array (void* mem) UT_NOTHROW
}
-static void* mem_leak_operator_new (size_t size) UT_THROW(std::bad_alloc)
+static void* mem_leak_operator_new (size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
@@ -204,14 +207,14 @@ static void* mem_leak_operator_new_nothrow (size_t size) UT_NOTHROW
return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size);
}
-static void* mem_leak_operator_new_debug (size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
+static void* mem_leak_operator_new_debug (size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC)
{
- void *memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size, (char*) file, line);
+ void *memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size, file, line);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
return memory;
}
-static void* mem_leak_operator_new_array (size_t size) UT_THROW(std::bad_alloc)
+static void* mem_leak_operator_new_array (size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
@@ -223,9 +226,9 @@ static void* mem_leak_operator_new_array_nothrow (size_t size) UT_NOTHROW
return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size);
}
-static void* mem_leak_operator_new_array_debug (size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
+static void* mem_leak_operator_new_array_debug (size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC)
{
- void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size, (char*) file, line);
+ void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size, file, line);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
return memory;
}
@@ -242,7 +245,7 @@ static void mem_leak_operator_delete_array (void* mem) UT_NOTHROW
MemoryLeakWarningPlugin::getGlobalDetector()->deallocMemory(getCurrentNewArrayAllocator(), (char*) mem);
}
-static void* normal_operator_new (size_t size) UT_THROW(std::bad_alloc)
+static void* normal_operator_new (size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
void* memory = PlatformSpecificMalloc(size);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
@@ -254,14 +257,14 @@ static void* normal_operator_new_nothrow (size_t size) UT_NOTHROW
return PlatformSpecificMalloc(size);
}
-static void* normal_operator_new_debug (size_t size, const char* /*file*/, int /*line*/) UT_THROW(std::bad_alloc)
+static void* normal_operator_new_debug (size_t size, const char* /*file*/, size_t /*line*/) UT_THROW(CPPUTEST_BAD_ALLOC)
{
void* memory = PlatformSpecificMalloc(size);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
return memory;
}
-static void* normal_operator_new_array (size_t size) UT_THROW(std::bad_alloc)
+static void* normal_operator_new_array (size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
void* memory = PlatformSpecificMalloc(size);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
@@ -273,7 +276,7 @@ static void* normal_operator_new_array_nothrow (size_t size) UT_NOTHROW
return PlatformSpecificMalloc(size);
}
-static void* normal_operator_new_array_debug (size_t size, const char* /*file*/, int /*line*/) UT_THROW(std::bad_alloc)
+static void* normal_operator_new_array_debug (size_t size, const char* /*file*/, size_t /*line*/) UT_THROW(CPPUTEST_BAD_ALLOC)
{
void* memory = PlatformSpecificMalloc(size);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
@@ -290,21 +293,36 @@ static void normal_operator_delete_array (void* mem) UT_NOTHROW
PlatformSpecificFree(mem);
}
-static void *(*operator_new_fptr)(size_t size) UT_THROW(std::bad_alloc) = mem_leak_operator_new;
+static void *(*operator_new_fptr)(size_t size) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new;
static void *(*operator_new_nothrow_fptr)(size_t size) UT_NOTHROW = mem_leak_operator_new_nothrow;
-static void *(*operator_new_debug_fptr)(size_t size, const char* file, int line) UT_THROW(std::bad_alloc) = mem_leak_operator_new_debug;
-static void *(*operator_new_array_fptr)(size_t size) UT_THROW(std::bad_alloc) = mem_leak_operator_new_array;
+static void *(*operator_new_debug_fptr)(size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new_debug;
+static void *(*operator_new_array_fptr)(size_t size) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new_array;
static void *(*operator_new_array_nothrow_fptr)(size_t size) UT_NOTHROW = mem_leak_operator_new_array_nothrow;
-static void *(*operator_new_array_debug_fptr)(size_t size, const char* file, int line) UT_THROW(std::bad_alloc) = mem_leak_operator_new_array_debug;
+static void *(*operator_new_array_debug_fptr)(size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new_array_debug;
static void (*operator_delete_fptr)(void* mem) UT_NOTHROW = mem_leak_operator_delete;
static void (*operator_delete_array_fptr)(void* mem) UT_NOTHROW = mem_leak_operator_delete_array;
-void* operator new(size_t size) UT_THROW(std::bad_alloc)
+static void *(*saved_operator_new_fptr)(size_t size) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new;
+static void *(*saved_operator_new_nothrow_fptr)(size_t size) UT_NOTHROW = mem_leak_operator_new_nothrow;
+static void *(*saved_operator_new_debug_fptr)(size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new_debug;
+static void *(*saved_operator_new_array_fptr)(size_t size) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new_array;
+static void *(*saved_operator_new_array_nothrow_fptr)(size_t size) UT_NOTHROW = mem_leak_operator_new_array_nothrow;
+static void *(*saved_operator_new_array_debug_fptr)(size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new_array_debug;
+static void (*saved_operator_delete_fptr)(void* mem) UT_NOTHROW = mem_leak_operator_delete;
+static void (*saved_operator_delete_array_fptr)(void* mem) UT_NOTHROW = mem_leak_operator_delete_array;
+static int save_counter = 0;
+
+void* operator new(size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
return operator_new_fptr(size);
}
-void* operator new(size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
+void* operator new(size_t size, const char* file, int line) UT_THROW(CPPUTEST_BAD_ALLOC)
+{
+ return operator_new_debug_fptr(size, file, (size_t)line);
+}
+
+void* operator new(size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC)
{
return operator_new_debug_fptr(size, file, line);
}
@@ -319,17 +337,29 @@ void operator delete(void* mem, const char*, int) UT_NOTHROW
operator_delete_fptr(mem);
}
+void operator delete(void* mem, const char*, size_t) UT_NOTHROW
+{
+ operator_delete_fptr(mem);
+}
+
+#if __cplusplus >= 201402L
void operator delete (void* mem, size_t) UT_NOTHROW
{
operator_delete_fptr(mem);
}
+#endif
-void* operator new[](size_t size) UT_THROW(std::bad_alloc)
+void* operator new[](size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
return operator_new_array_fptr(size);
}
-void* operator new [](size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
+void* operator new [](size_t size, const char* file, int line) UT_THROW(CPPUTEST_BAD_ALLOC)
+{
+ return operator_new_array_debug_fptr(size, file, (size_t)line);
+}
+
+void* operator new [](size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC)
{
return operator_new_array_debug_fptr(size, file, line);
}
@@ -344,10 +374,17 @@ void operator delete[](void* mem, const char*, int) UT_NOTHROW
operator_delete_array_fptr(mem);
}
+void operator delete[](void* mem, const char*, size_t) UT_NOTHROW
+{
+ operator_delete_array_fptr(mem);
+}
+
+#if __cplusplus >= 201402L
void operator delete[] (void* mem, size_t) UT_NOTHROW
{
operator_delete_array_fptr(mem);
}
+#endif
#if CPPUTEST_USE_STD_CPP_LIB
@@ -356,11 +393,21 @@ void* operator new(size_t size, const std::nothrow_t&) UT_NOTHROW
return operator_new_nothrow_fptr(size);
}
+void operator delete(void* mem, const std::nothrow_t&) UT_NOTHROW
+{
+ operator_delete_fptr(mem);
+}
+
void* operator new[](size_t size, const std::nothrow_t&) UT_NOTHROW
{
return operator_new_array_nothrow_fptr(size);
}
+void operator delete[](void* mem, const std::nothrow_t&) UT_NOTHROW
+{
+ operator_delete_array_fptr(mem);
+}
+
#else
/* Have a similar method. This avoid unused operator_new_nothrow_fptr warning */
@@ -399,7 +446,7 @@ void MemoryLeakWarningPlugin::turnOffNewDeleteOverloads()
#endif
}
-void MemoryLeakWarningPlugin::turnOnNewDeleteOverloads()
+void MemoryLeakWarningPlugin::turnOnDefaultNotThreadSafeNewDeleteOverloads()
{
#if CPPUTEST_USE_MEM_LEAK_DETECTION
operator_new_fptr = mem_leak_operator_new;
@@ -416,15 +463,6 @@ void MemoryLeakWarningPlugin::turnOnNewDeleteOverloads()
#endif
}
-bool MemoryLeakWarningPlugin::areNewDeleteOverloaded()
-{
-#if CPPUTEST_USE_MEM_LEAK_DETECTION
- return operator_new_fptr == mem_leak_operator_new;
-#else
- return false;
-#endif
-}
-
void MemoryLeakWarningPlugin::turnOnThreadSafeNewDeleteOverloads()
{
#if CPPUTEST_USE_MEM_LEAK_DETECTION
@@ -442,6 +480,52 @@ void MemoryLeakWarningPlugin::turnOnThreadSafeNewDeleteOverloads()
#endif
}
+bool MemoryLeakWarningPlugin::areNewDeleteOverloaded()
+{
+#if CPPUTEST_USE_MEM_LEAK_DETECTION
+ return operator_new_fptr == mem_leak_operator_new || operator_new_fptr == threadsafe_mem_leak_operator_new;
+#else
+ return false;
+#endif
+}
+
+void MemoryLeakWarningPlugin::saveAndDisableNewDeleteOverloads()
+{
+#if CPPUTEST_USE_MEM_LEAK_DETECTION
+ if (++save_counter > 1) return;
+ saved_operator_new_fptr = operator_new_fptr;
+ saved_operator_new_nothrow_fptr = operator_new_nothrow_fptr;
+ saved_operator_new_debug_fptr = operator_new_debug_fptr;
+ saved_operator_new_array_fptr = operator_new_array_fptr;
+ saved_operator_new_array_nothrow_fptr = operator_new_array_nothrow_fptr;
+ saved_operator_new_array_debug_fptr = operator_new_array_debug_fptr;
+ saved_operator_delete_fptr = operator_delete_fptr;
+ saved_operator_delete_array_fptr = operator_delete_array_fptr;
+ saved_malloc_fptr = malloc_fptr;
+ saved_realloc_fptr = realloc_fptr;
+ saved_free_fptr = free_fptr;
+ turnOffNewDeleteOverloads();
+#endif
+}
+
+void MemoryLeakWarningPlugin::restoreNewDeleteOverloads()
+{
+#if CPPUTEST_USE_MEM_LEAK_DETECTION
+ if (--save_counter > 0) return;
+ operator_new_fptr = saved_operator_new_fptr;
+ operator_new_nothrow_fptr = saved_operator_new_nothrow_fptr;
+ operator_new_debug_fptr = saved_operator_new_debug_fptr;
+ operator_new_array_fptr = saved_operator_new_array_fptr;
+ operator_new_array_nothrow_fptr = saved_operator_new_array_nothrow_fptr;
+ operator_new_array_debug_fptr = saved_operator_new_array_debug_fptr;
+ operator_delete_fptr = saved_operator_delete_fptr;
+ operator_delete_array_fptr = saved_operator_delete_array_fptr;
+ malloc_fptr = saved_malloc_fptr;
+ realloc_fptr = saved_realloc_fptr;
+ free_fptr = saved_free_fptr;
+#endif
+}
+
void crash_on_allocation_number(unsigned alloc_number)
{
static CrashOnAllocationAllocator crashAllocator;
@@ -454,30 +538,29 @@ void crash_on_allocation_number(unsigned alloc_number)
class MemoryLeakWarningReporter: public MemoryLeakFailure
{
public:
- virtual ~MemoryLeakWarningReporter()
+ virtual ~MemoryLeakWarningReporter() CPPUTEST_DESTRUCTOR_OVERRIDE
{
}
- virtual void fail(char* fail_string)
+ virtual void fail(char* fail_string) CPPUTEST_OVERRIDE
{
UtestShell* currentTest = UtestShell::getCurrent();
- currentTest->failWith(FailFailure(currentTest, currentTest->getName().asCharString(), currentTest->getLineNumber(), fail_string), TestTerminatorWithoutExceptions());
+ currentTest->failWith(FailFailure(currentTest, currentTest->getName().asCharString(), currentTest->getLineNumber(), fail_string), UtestShell::getCurrentTestTerminatorWithoutExceptions());
} // LCOV_EXCL_LINE
};
-static MemoryLeakFailure* globalReporter = 0;
-static MemoryLeakDetector* globalDetector = 0;
+static MemoryLeakFailure* globalReporter = NULLPTR;
+static MemoryLeakDetector* globalDetector = NULLPTR;
MemoryLeakDetector* MemoryLeakWarningPlugin::getGlobalDetector()
{
- if (globalDetector == 0) {
- bool newDeleteOverloaded = areNewDeleteOverloaded();
- turnOffNewDeleteOverloads();
+ if (globalDetector == NULLPTR) {
+ saveAndDisableNewDeleteOverloads();
globalReporter = new MemoryLeakWarningReporter;
globalDetector = new MemoryLeakDetector(globalReporter);
- if (newDeleteOverloaded) turnOnNewDeleteOverloads();
+ restoreNewDeleteOverloads();
}
return globalDetector;
}
@@ -503,11 +586,11 @@ void MemoryLeakWarningPlugin::destroyGlobalDetector()
turnOffNewDeleteOverloads();
delete globalDetector;
delete globalReporter;
- globalDetector = NULL;
+ globalDetector = NULLPTR;
}
-MemoryLeakWarningPlugin* MemoryLeakWarningPlugin::firstPlugin_ = 0;
+MemoryLeakWarningPlugin* MemoryLeakWarningPlugin::firstPlugin_ = NULLPTR;
MemoryLeakWarningPlugin* MemoryLeakWarningPlugin::getFirstPlugin()
{
@@ -524,7 +607,7 @@ void MemoryLeakWarningPlugin::ignoreAllLeaksInTest()
ignoreAllWarnings_ = true;
}
-void MemoryLeakWarningPlugin::expectLeaksInTest(int n)
+void MemoryLeakWarningPlugin::expectLeaksInTest(size_t n)
{
expectedLeaks_ = n;
}
@@ -532,7 +615,7 @@ void MemoryLeakWarningPlugin::expectLeaksInTest(int n)
MemoryLeakWarningPlugin::MemoryLeakWarningPlugin(const SimpleString& name, MemoryLeakDetector* localDetector) :
TestPlugin(name), ignoreAllWarnings_(false), destroyGlobalDetectorAndTurnOfMemoryLeakDetectionInDestructor_(false), expectedLeaks_(0)
{
- if (firstPlugin_ == 0) firstPlugin_ = this;
+ if (firstPlugin_ == NULLPTR) firstPlugin_ = this;
if (localDetector) memLeakDetector_ = localDetector;
else memLeakDetector_ = getGlobalDetector();
@@ -557,20 +640,24 @@ void MemoryLeakWarningPlugin::preTestAction(UtestShell& /*test*/, TestResult& re
void MemoryLeakWarningPlugin::postTestAction(UtestShell& test, TestResult& result)
{
memLeakDetector_->stopChecking();
- int leaks = memLeakDetector_->totalMemoryLeaks(mem_leak_period_checking);
+ size_t leaks = memLeakDetector_->totalMemoryLeaks(mem_leak_period_checking);
if (!ignoreAllWarnings_ && expectedLeaks_ != leaks && failureCount_ == result.getFailureCount()) {
- TestFailure f(&test, memLeakDetector_->report(mem_leak_period_checking));
- result.addFailure(f);
+ if(MemoryLeakWarningPlugin::areNewDeleteOverloaded()) {
+ TestFailure f(&test, memLeakDetector_->report(mem_leak_period_checking));
+ result.addFailure(f);
+ } else if(expectedLeaks_ > 0) {
+ result.print(StringFromFormat("Warning: Expected %d leak(s), but leak detection was disabled", (int) expectedLeaks_).asCharString());
+ }
}
memLeakDetector_->markCheckingPeriodLeaksAsNonCheckingPeriod();
ignoreAllWarnings_ = false;
expectedLeaks_ = 0;
}
-const char* MemoryLeakWarningPlugin::FinalReport(int toBeDeletedLeaks)
+const char* MemoryLeakWarningPlugin::FinalReport(size_t toBeDeletedLeaks)
{
- int leaks = memLeakDetector_->totalMemoryLeaks(mem_leak_period_enabled);
+ size_t leaks = memLeakDetector_->totalMemoryLeaks(mem_leak_period_enabled);
if (leaks != toBeDeletedLeaks) return memLeakDetector_->report(mem_leak_period_enabled);
return "";
}
diff --git a/src/CppUTest/SimpleMutex.cpp b/src/CppUTest/SimpleMutex.cpp
index a1f4d7027..8fd9c887f 100644
--- a/src/CppUTest/SimpleMutex.cpp
+++ b/src/CppUTest/SimpleMutex.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
diff --git a/src/CppUTest/SimpleString.cpp b/src/CppUTest/SimpleString.cpp
index b63fcc935..a62491e32 100644
--- a/src/CppUTest/SimpleString.cpp
+++ b/src/CppUTest/SimpleString.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -30,11 +30,83 @@
#include "CppUTest/PlatformSpecificFunctions.h"
#include "CppUTest/TestMemoryAllocator.h"
-TestMemoryAllocator* SimpleString::stringAllocator_ = NULL;
+GlobalSimpleStringAllocatorStash::GlobalSimpleStringAllocatorStash()
+ : originalAllocator_(NULLPTR)
+{
+}
+
+void GlobalSimpleStringAllocatorStash::save()
+{
+ originalAllocator_ = SimpleString::getStringAllocator();
+}
+
+void GlobalSimpleStringAllocatorStash::restore()
+{
+ SimpleString::setStringAllocator(originalAllocator_);
+}
+
+
+GlobalSimpleStringMemoryAccountant::GlobalSimpleStringMemoryAccountant()
+ : allocator_(NULLPTR)
+{
+ accountant_ = new MemoryAccountant();
+}
+
+GlobalSimpleStringMemoryAccountant::~GlobalSimpleStringMemoryAccountant()
+{
+ restoreAllocator();
+
+ delete accountant_;
+ delete allocator_;
+}
+
+void GlobalSimpleStringMemoryAccountant::restoreAllocator()
+{
+ if (allocator_ && (SimpleString::getStringAllocator() == allocator_))
+ SimpleString::setStringAllocator(allocator_->originalAllocator());
+}
+
+void GlobalSimpleStringMemoryAccountant::useCacheSizes(size_t cacheSizes[], size_t length)
+{
+ accountant_->useCacheSizes(cacheSizes, length);
+}
+
+void GlobalSimpleStringMemoryAccountant::start()
+{
+ if (allocator_ != NULLPTR)
+ return;
+
+ allocator_ = new AccountingTestMemoryAllocator(*accountant_, SimpleString::getStringAllocator());
+
+ SimpleString::setStringAllocator(allocator_);
+}
+
+void GlobalSimpleStringMemoryAccountant::stop()
+{
+ if (allocator_ == NULLPTR)
+ FAIL("Global SimpleString allocator stopped without starting");
+
+ if (SimpleString::getStringAllocator() != allocator_)
+ FAIL("GlobalStrimpleStringMemoryAccountant: allocator has changed between start and stop!");
+
+ restoreAllocator();
+}
+
+SimpleString GlobalSimpleStringMemoryAccountant::report()
+{
+ return accountant_->report();
+}
+
+AccountingTestMemoryAllocator* GlobalSimpleStringMemoryAccountant::getAllocator()
+{
+ return allocator_;
+}
+
+TestMemoryAllocator* SimpleString::stringAllocator_ = NULLPTR;
TestMemoryAllocator* SimpleString::getStringAllocator()
{
- if (stringAllocator_ == NULL)
+ if (stringAllocator_ == NULLPTR)
return defaultNewArrayAllocator();
return stringAllocator_;
}
@@ -45,14 +117,14 @@ void SimpleString::setStringAllocator(TestMemoryAllocator* allocator)
}
/* Avoid using the memory leak detector INSIDE SimpleString as its used inside the detector */
-char* SimpleString::allocStringBuffer(size_t _size, const char* file, int line)
+char* SimpleString::allocStringBuffer(size_t _size, const char* file, size_t line)
{
return getStringAllocator()->alloc_memory(_size, file, line);
}
-void SimpleString::deallocStringBuffer(char* str, const char* file, int line)
+void SimpleString::deallocStringBuffer(char* str, size_t size, const char* file, size_t line)
{
- getStringAllocator()->free_memory(str, file, line);
+ getStringAllocator()->free_memory(str, size, file, line);
}
char* SimpleString::getEmptyString() const
@@ -62,6 +134,20 @@ char* SimpleString::getEmptyString() const
return empty;
}
+// does not support + or - prefixes
+unsigned SimpleString::AtoU(const char* str)
+{
+ while (isSpace(*str)) str++;
+
+ unsigned result = 0;
+ for(; isDigit(*str) && *str >= '0'; str++)
+ {
+ result *= 10;
+ result += static_cast(*str - '0');
+ }
+ return result;
+}
+
int SimpleString::AtoI(const char* str)
{
while (isSpace(*str)) str++;
@@ -80,9 +166,11 @@ int SimpleString::AtoI(const char* str)
int SimpleString::StrCmp(const char* s1, const char* s2)
{
- while(*s1 && *s1 == *s2)
- s1++, s2++;
- return *(unsigned char *) s1 - *(unsigned char *) s2;
+ while(*s1 && *s1 == *s2) {
+ ++s1;
+ ++s2;
+ }
+ return *(const unsigned char *) s1 - *(const unsigned char *) s2;
}
size_t SimpleString::StrLen(const char* str)
@@ -95,29 +183,33 @@ size_t SimpleString::StrLen(const char* str)
int SimpleString::StrNCmp(const char* s1, const char* s2, size_t n)
{
while (n && *s1 && *s1 == *s2) {
- n--, s1++, s2++;
+ --n;
+ ++s1;
+ ++s2;
}
- return n ? *(unsigned char *) s1 - *(unsigned char *) s2 : 0;
+ return n ? *(const unsigned char *) s1 - *(const unsigned char *) s2 : 0;
}
char* SimpleString::StrNCpy(char* s1, const char* s2, size_t n)
{
char* result = s1;
- if((NULL == s1) || (0 == n)) return result;
+ if((NULLPTR == s1) || (0 == n)) return result;
- while ((*s1++ = *s2++) && --n != 0)
- ;
+ *s1 = *s2;
+ while ((--n != 0) && *s1){
+ *++s1 = *++s2;
+ }
return result;
}
-char* SimpleString::StrStr(const char* s1, const char* s2)
+const char* SimpleString::StrStr(const char* s1, const char* s2)
{
- if(!*s2) return (char*) s1;
+ if(!*s2) return s1;
for (; *s1; s1++)
if (StrNCmp(s1, s2, StrLen(s2)) == 0)
- return (char*) s1;
- return NULL;
+ return s1;
+ return NULLPTR;
}
char SimpleString::ToLower(char ch)
@@ -131,28 +223,87 @@ int SimpleString::MemCmp(const void* s1, const void *s2, size_t n)
const unsigned char* p2 = (const unsigned char*) s2;
while (n--)
- if (*p1 != *p2)
+ if (*p1 != *p2) {
return *p1 - *p2;
- else
- p1++, p2++;
+ } else {
+ ++p1;
+ ++p2;
+ }
return 0;
}
-SimpleString::SimpleString(const char *otherBuffer)
+void SimpleString::deallocateInternalBuffer()
{
- if (otherBuffer == 0) {
- buffer_ = getEmptyString();
- }
- else {
- buffer_ = copyToNewBuffer(otherBuffer);
+ if (buffer_) {
+ deallocStringBuffer(buffer_, bufferSize_, __FILE__, __LINE__);
+ buffer_ = NULLPTR;
+ bufferSize_ = 0;
}
}
+void SimpleString::setInternalBufferAsEmptyString()
+{
+ deallocateInternalBuffer();
+
+ bufferSize_ = 1;
+ buffer_ = getEmptyString();
+}
+
+void SimpleString::copyBufferToNewInternalBuffer(const char* otherBuffer, size_t bufferSize)
+{
+ deallocateInternalBuffer();
+
+ bufferSize_ = bufferSize;
+ buffer_ = copyToNewBuffer(otherBuffer, bufferSize_);
+}
+
+void SimpleString::setInternalBufferToNewBuffer(size_t bufferSize)
+{
+ deallocateInternalBuffer();
+
+ bufferSize_ = bufferSize;
+ buffer_ = allocStringBuffer(bufferSize_, __FILE__, __LINE__);
+ buffer_[0] = '\0';
+}
+
+void SimpleString::setInternalBufferTo(char* buffer, size_t bufferSize)
+{
+ deallocateInternalBuffer();
+
+ bufferSize_ = bufferSize;
+ buffer_ = buffer;
+}
+
+void SimpleString::copyBufferToNewInternalBuffer(const SimpleString& otherBuffer)
+{
+ copyBufferToNewInternalBuffer(otherBuffer.buffer_, otherBuffer.size() + 1);
+}
+
+void SimpleString::copyBufferToNewInternalBuffer(const char* otherBuffer)
+{
+ copyBufferToNewInternalBuffer(otherBuffer, StrLen(otherBuffer) + 1);
+}
+
+const char* SimpleString::getBuffer() const
+{
+ return buffer_;
+}
+
+SimpleString::SimpleString(const char *otherBuffer)
+ : buffer_(NULLPTR), bufferSize_(0)
+{
+ if (otherBuffer == NULLPTR)
+ setInternalBufferAsEmptyString();
+ else
+ copyBufferToNewInternalBuffer(otherBuffer);
+}
+
SimpleString::SimpleString(const char *other, size_t repeatCount)
+ : buffer_(NULLPTR), bufferSize_(0)
{
size_t otherStringLength = StrLen(other);
- size_t len = otherStringLength * repeatCount + 1;
- buffer_ = allocStringBuffer(len, __FILE__, __LINE__);
+ setInternalBufferToNewBuffer(otherStringLength * repeatCount + 1);
+
char* next = buffer_;
for (size_t i = 0; i < repeatCount; i++) {
StrNCpy(next, other, otherStringLength + 1);
@@ -162,22 +313,21 @@ SimpleString::SimpleString(const char *other, size_t repeatCount)
}
SimpleString::SimpleString(const SimpleString& other)
+ : buffer_(NULLPTR), bufferSize_(0)
{
- buffer_ = copyToNewBuffer(other.buffer_);
+ copyBufferToNewInternalBuffer(other.getBuffer());
}
SimpleString& SimpleString::operator=(const SimpleString& other)
{
- if (this != &other) {
- deallocStringBuffer(buffer_, __FILE__, __LINE__);
- buffer_ = copyToNewBuffer(other.buffer_);
- }
+ if (this != &other)
+ copyBufferToNewInternalBuffer(other);
return *this;
}
bool SimpleString::contains(const SimpleString& other) const
{
- return StrStr(buffer_, other.buffer_) != 0;
+ return StrStr(getBuffer(), other.getBuffer()) != NULLPTR;
}
bool SimpleString::containsNoCase(const SimpleString& other) const
@@ -187,28 +337,36 @@ bool SimpleString::containsNoCase(const SimpleString& other) const
bool SimpleString::startsWith(const SimpleString& other) const
{
- if (StrLen(other.buffer_) == 0) return true;
+ if (other.size() == 0) return true;
else if (size() == 0) return false;
- else return StrStr(buffer_, other.buffer_) == buffer_;
+ else return StrStr(getBuffer(), other.getBuffer()) == getBuffer();
}
bool SimpleString::endsWith(const SimpleString& other) const
{
- size_t buffer_length = size();
- size_t other_buffer_length = StrLen(other.buffer_);
- if (other_buffer_length == 0) return true;
- if (buffer_length == 0) return false;
- if (buffer_length < other_buffer_length) return false;
- return StrCmp(buffer_ + buffer_length - other_buffer_length, other.buffer_) == 0;
+ size_t length = size();
+ size_t other_length = other.size();
+
+ if (other_length == 0) return true;
+ if (length == 0) return false;
+ if (length < other_length) return false;
+
+ return StrCmp(getBuffer() + length - other_length, other.getBuffer()) == 0;
}
size_t SimpleString::count(const SimpleString& substr) const
{
size_t num = 0;
- char* str = buffer_;
- while (*str && (str = StrStr(str, substr.buffer_))) {
- num++;
+ const char* str = getBuffer();
+ const char* strpart = NULLPTR;
+ if (*str){
+ strpart = StrStr(str, substr.getBuffer());
+ }
+ while (*str && strpart) {
+ str = strpart;
str++;
+ num++;
+ strpart = StrStr(str, substr.getBuffer());
}
return num;
}
@@ -219,11 +377,11 @@ void SimpleString::split(const SimpleString& delimiter, SimpleStringCollection&
size_t extraEndToken = (endsWith(delimiter)) ? 0 : 1U;
col.allocate(num + extraEndToken);
- char* str = buffer_;
- char* prev;
+ const char* str = getBuffer();
+ const char* prev;
for (size_t i = 0; i < num; ++i) {
prev = str;
- str = StrStr(str, delimiter.buffer_) + 1;
+ str = StrStr(str, delimiter.getBuffer()) + 1;
col[i] = SimpleString(prev).subString(0, size_t (str - prev));
}
if (extraEndToken) {
@@ -235,13 +393,16 @@ void SimpleString::replace(char to, char with)
{
size_t s = size();
for (size_t i = 0; i < s; i++) {
- if (buffer_[i] == to) buffer_[i] = with;
+ if (getBuffer()[i] == to) buffer_[i] = with;
}
}
void SimpleString::replace(const char* to, const char* with)
{
size_t c = count(to);
+ if (c == 0) {
+ return;
+ }
size_t len = size();
size_t tolen = StrLen(to);
size_t withlen = StrLen(with);
@@ -251,25 +412,86 @@ void SimpleString::replace(const char* to, const char* with)
if (newsize > 1) {
char* newbuf = allocStringBuffer(newsize, __FILE__, __LINE__);
for (size_t i = 0, j = 0; i < len;) {
- if (StrNCmp(&buffer_[i], to, tolen) == 0) {
+ if (StrNCmp(&getBuffer()[i], to, tolen) == 0) {
StrNCpy(&newbuf[j], with, withlen + 1);
j += withlen;
i += tolen;
}
else {
- newbuf[j] = buffer_[i];
+ newbuf[j] = getBuffer()[i];
j++;
i++;
}
}
- deallocStringBuffer(buffer_, __FILE__, __LINE__);
- buffer_ = newbuf;
- buffer_[newsize - 1] = '\0';
+ newbuf[newsize - 1] = '\0';
+ setInternalBufferTo(newbuf, newsize);
}
- else {
- deallocStringBuffer(buffer_, __FILE__, __LINE__);
- buffer_ = getEmptyString();
+ else
+ setInternalBufferAsEmptyString();
+}
+
+SimpleString SimpleString::printable() const
+{
+ static const char* shortEscapeCodes[] =
+ {
+ "\\a",
+ "\\b",
+ "\\t",
+ "\\n",
+ "\\v",
+ "\\f",
+ "\\r"
+ };
+
+ SimpleString result;
+ result.setInternalBufferToNewBuffer(getPrintableSize() + 1);
+
+ size_t str_size = size();
+ size_t j = 0;
+ for (size_t i = 0; i < str_size; i++)
+ {
+ char c = buffer_[i];
+ if (isControlWithShortEscapeSequence(c))
+ {
+ StrNCpy(&result.buffer_[j], shortEscapeCodes[(unsigned char)(c - '\a')], 2);
+ j += 2;
+ }
+ else if (isControl(c))
+ {
+ SimpleString hexEscapeCode = StringFromFormat("\\x%02X ", c);
+ StrNCpy(&result.buffer_[j], hexEscapeCode.asCharString(), 4);
+ j += 4;
+ }
+ else
+ {
+ result.buffer_[j] = c;
+ j++;
+ }
}
+ result.buffer_[j] = 0;
+
+ return result;
+}
+
+size_t SimpleString::getPrintableSize() const
+{
+ size_t str_size = size();
+ size_t printable_str_size = str_size;
+
+ for (size_t i = 0; i < str_size; i++)
+ {
+ char c = buffer_[i];
+ if (isControlWithShortEscapeSequence(c))
+ {
+ printable_str_size += 1;
+ }
+ else if (isControl(c))
+ {
+ printable_str_size += 3;
+ }
+ }
+
+ return printable_str_size;
}
SimpleString SimpleString::lowerCase() const
@@ -278,19 +500,19 @@ SimpleString SimpleString::lowerCase() const
size_t str_size = str.size();
for (size_t i = 0; i < str_size; i++)
- str.buffer_[i] = ToLower(str.buffer_[i]);
+ str.buffer_[i] = ToLower(str.getBuffer()[i]);
return str;
}
const char *SimpleString::asCharString() const
{
- return buffer_;
+ return getBuffer();
}
size_t SimpleString::size() const
{
- return StrLen(buffer_);
+ return StrLen(getBuffer());
}
bool SimpleString::isEmpty() const
@@ -298,10 +520,9 @@ bool SimpleString::isEmpty() const
return size() == 0;
}
-
SimpleString::~SimpleString()
{
- deallocStringBuffer(buffer_, __FILE__, __LINE__);
+ deallocateInternalBuffer();
}
bool operator==(const SimpleString& left, const SimpleString& right)
@@ -322,14 +543,14 @@ bool operator!=(const SimpleString& left, const SimpleString& right)
SimpleString SimpleString::operator+(const SimpleString& rhs) const
{
- SimpleString t(buffer_);
- t += rhs.buffer_;
+ SimpleString t(getBuffer());
+ t += rhs.getBuffer();
return t;
}
SimpleString& SimpleString::operator+=(const SimpleString& rhs)
{
- return operator+=(rhs.buffer_);
+ return operator+=(rhs.getBuffer());
}
SimpleString& SimpleString::operator+=(const char* rhs)
@@ -337,10 +558,10 @@ SimpleString& SimpleString::operator+=(const char* rhs)
size_t originalSize = this->size();
size_t additionalStringSize = StrLen(rhs) + 1;
size_t sizeOfNewString = originalSize + additionalStringSize;
- char* tbuffer = copyToNewBuffer(this->buffer_, sizeOfNewString);
+ char* tbuffer = copyToNewBuffer(this->getBuffer(), sizeOfNewString);
StrNCpy(tbuffer + originalSize, rhs, additionalStringSize);
- deallocStringBuffer(this->buffer_, __FILE__, __LINE__);
- this->buffer_ = tbuffer;
+
+ setInternalBufferTo(tbuffer, sizeOfNewString);
return *this;
}
@@ -361,7 +582,7 @@ SimpleString SimpleString::subString(size_t beginPos, size_t amount) const
{
if (beginPos > size()-1) return "";
- SimpleString newString = buffer_ + beginPos;
+ SimpleString newString = getBuffer() + beginPos;
if (newString.size() > amount)
newString.buffer_[amount] = '\0';
@@ -376,7 +597,7 @@ SimpleString SimpleString::subString(size_t beginPos) const
char SimpleString::at(size_t pos) const
{
- return buffer_[pos];
+ return getBuffer()[pos];
}
size_t SimpleString::find(char ch) const
@@ -388,7 +609,7 @@ size_t SimpleString::findFrom(size_t starting_position, char ch) const
{
size_t length = size();
for (size_t i = starting_position; i < length; i++)
- if (buffer_[i] == ch) return i;
+ if (at(i) == ch) return i;
return npos;
}
@@ -405,21 +626,20 @@ SimpleString SimpleString::subStringFromTill(char startChar, char lastExcludedCh
char* SimpleString::copyToNewBuffer(const char* bufferToCopy, size_t bufferSize)
{
- if(bufferSize == 0) bufferSize = StrLen(bufferToCopy) + 1;
-
char* newBuffer = allocStringBuffer(bufferSize, __FILE__, __LINE__);
StrNCpy(newBuffer, bufferToCopy, bufferSize);
newBuffer[bufferSize-1] = '\0';
return newBuffer;
}
+
void SimpleString::copyToBuffer(char* bufferToCopy, size_t bufferSize) const
{
- if (bufferToCopy == NULL || bufferSize == 0) return;
+ if (bufferToCopy == NULLPTR || bufferSize == 0) return;
- size_t sizeToCopy = (bufferSize-1 < size()) ? bufferSize : size();
+ size_t sizeToCopy = (bufferSize-1 < size()) ? (bufferSize-1) : size();
- StrNCpy(bufferToCopy, buffer_, sizeToCopy);
+ StrNCpy(bufferToCopy, getBuffer(), sizeToCopy);
bufferToCopy[sizeToCopy] = '\0';
}
@@ -438,6 +658,16 @@ bool SimpleString::isUpper(char ch)
return 'A' <= ch && 'Z' >= ch;
}
+bool SimpleString::isControl(char ch)
+{
+ return ch < ' ' || ch == char(0x7F);
+}
+
+bool SimpleString::isControlWithShortEscapeSequence(char ch)
+{
+ return '\a' <= ch && '\r' >= ch;
+}
+
SimpleString StringFrom(bool value)
{
return SimpleString(StringFromFormat("%s", value ? "true" : "false"));
@@ -450,7 +680,12 @@ SimpleString StringFrom(const char *value)
SimpleString StringFromOrNull(const char * expected)
{
- return (expected) ? StringFrom(expected) : "(null)";
+ return (expected) ? StringFrom(expected) : StringFrom("(null)");
+}
+
+SimpleString PrintableStringFromOrNull(const char * expected)
+{
+ return (expected) ? StringFrom(expected).printable() : StringFrom("(null)");
}
SimpleString StringFrom(int value)
@@ -475,7 +710,12 @@ SimpleString StringFrom(void (*value)())
SimpleString HexStringFrom(long value)
{
- return StringFromFormat("%lx", value);
+ return HexStringFrom((unsigned long)value);
+}
+
+SimpleString HexStringFrom(int value)
+{
+ return HexStringFrom((unsigned int)value);
}
SimpleString HexStringFrom(signed char value)
@@ -493,7 +733,55 @@ SimpleString HexStringFrom(unsigned long value)
return StringFromFormat("%lx", value);
}
-#ifdef CPPUTEST_USE_LONG_LONG
+SimpleString HexStringFrom(unsigned int value)
+{
+ return StringFromFormat("%x", value);
+}
+
+SimpleString BracketsFormattedHexStringFrom(int value)
+{
+ return BracketsFormattedHexString(HexStringFrom(value));
+}
+
+SimpleString BracketsFormattedHexStringFrom(unsigned int value)
+{
+ return BracketsFormattedHexString(HexStringFrom(value));
+}
+
+SimpleString BracketsFormattedHexStringFrom(long value)
+{
+ return BracketsFormattedHexString(HexStringFrom(value));
+}
+
+
+SimpleString BracketsFormattedHexStringFrom(unsigned long value)
+{
+ return BracketsFormattedHexString(HexStringFrom(value));
+}
+
+SimpleString BracketsFormattedHexStringFrom(signed char value)
+{
+ return BracketsFormattedHexString(HexStringFrom(value));
+}
+
+SimpleString BracketsFormattedHexString(SimpleString hexString)
+{
+ return SimpleString("(0x") + hexString + ")" ;
+}
+
+/*
+ * ARM compiler has only partial support for C++11.
+ * Specifically nullptr_t is not officially supported
+ */
+#if __cplusplus > 199711L && !defined __arm__ && CPPUTEST_USE_STD_CPP_LIB
+SimpleString StringFrom(const std::nullptr_t value)
+{
+ (void) value;
+ return "(null)";
+}
+#endif
+
+#if CPPUTEST_USE_LONG_LONG
SimpleString StringFrom(cpputest_longlong value)
{
@@ -502,12 +790,12 @@ SimpleString StringFrom(cpputest_longlong value)
SimpleString StringFrom(cpputest_ulonglong value)
{
- return StringFromFormat("%llu (0x%llx)", value, value);
+ return StringFromFormat("%llu", value);
}
SimpleString HexStringFrom(cpputest_longlong value)
{
- return StringFromFormat("%llx", value);
+ return HexStringFrom((cpputest_ulonglong)value);
}
SimpleString HexStringFrom(cpputest_ulonglong value)
@@ -525,6 +813,17 @@ SimpleString HexStringFrom(void (*value)())
return HexStringFrom((cpputest_ulonglong) value);
}
+SimpleString BracketsFormattedHexStringFrom(cpputest_longlong value)
+{
+ return BracketsFormattedHexString(HexStringFrom(value));
+}
+
+
+SimpleString BracketsFormattedHexStringFrom(cpputest_ulonglong value)
+{
+ return BracketsFormattedHexString(HexStringFrom(value));
+}
+
#else /* CPPUTEST_USE_LONG_LONG */
static long convertPointerToLongValue(const void* value)
@@ -579,6 +878,17 @@ SimpleString HexStringFrom(void (*value)())
return StringFromFormat("%lx", convertFunctionPointerToLongValue(value));
}
+SimpleString BracketsFormattedHexStringFrom(cpputest_longlong)
+{
+ return "";
+}
+
+
+SimpleString BracketsFormattedHexStringFrom(cpputest_ulonglong)
+{
+ return "";
+}
+
#endif /* CPPUTEST_USE_LONG_LONG */
SimpleString StringFrom(double value, int precision)
@@ -614,7 +924,7 @@ SimpleString StringFromFormat(const char* format, ...)
SimpleString StringFrom(unsigned int i)
{
- return StringFromFormat("%10u (0x%08x)", i, i);
+ return StringFromFormat("%u", i);
}
#if CPPUTEST_USE_STD_CPP_LIB
@@ -630,14 +940,9 @@ SimpleString StringFrom(const std::string& value)
SimpleString StringFrom(unsigned long i)
{
- return StringFromFormat("%lu (0x%lx)", i, i);
+ return StringFromFormat("%lu", i);
}
-//Kludge to get a va_copy in VC++ V6
-#ifndef va_copy
-#define va_copy(copy, original) copy = original;
-#endif
-
SimpleString VStringFromFormat(const char* format, va_list args)
{
va_list argsCopy;
@@ -659,7 +964,7 @@ SimpleString VStringFromFormat(const char* format, va_list args)
PlatformSpecificVSNprintf(newBuffer, newBufferSize, format, argsCopy);
resultString = SimpleString(newBuffer);
- SimpleString::deallocStringBuffer(newBuffer, __FILE__, __LINE__);
+ SimpleString::deallocStringBuffer(newBuffer, newBufferSize, __FILE__, __LINE__);
}
va_end(argsCopy);
return resultString;
@@ -679,7 +984,7 @@ SimpleString StringFromBinary(const unsigned char* value, size_t size)
SimpleString StringFromBinaryOrNull(const unsigned char* value, size_t size)
{
- return (value) ? StringFromBinary(value, size) : "(null)";
+ return (value) ? StringFromBinary(value, size) : StringFrom("(null)");
}
SimpleString StringFromBinaryWithSize(const unsigned char* value, size_t size)
@@ -696,7 +1001,7 @@ SimpleString StringFromBinaryWithSize(const unsigned char* value, size_t size)
SimpleString StringFromBinaryWithSizeOrNull(const unsigned char* value, size_t size)
{
- return (value) ? StringFromBinaryWithSize(value, size) : "(null)";
+ return (value) ? StringFromBinaryWithSize(value, size) : StringFrom("(null)");
}
SimpleString StringFromMaskedBits(unsigned long value, unsigned long mask, size_t byteCount)
@@ -726,19 +1031,17 @@ SimpleString StringFromMaskedBits(unsigned long value, unsigned long mask, size_
SimpleString StringFromOrdinalNumber(unsigned int number)
{
- unsigned int onesDigit = number % 10;
-
- const char* suffix;
- if (number >= 11 && number <= 13) {
- suffix = "th";
- } else if (3 == onesDigit) {
- suffix = "rd";
- } else if (2 == onesDigit) {
- suffix = "nd";
- } else if (1 == onesDigit) {
- suffix = "st";
- } else {
- suffix = "th";
+ const char* suffix = "th";
+
+ if ((number < 11) || (number > 13)) {
+ unsigned int const onesDigit = number % 10;
+ if (3 == onesDigit) {
+ suffix = "rd";
+ } else if (2 == onesDigit) {
+ suffix = "nd";
+ } else if (1 == onesDigit) {
+ suffix = "st";
+ }
}
return StringFromFormat("%u%s", number, suffix);
@@ -746,7 +1049,7 @@ SimpleString StringFromOrdinalNumber(unsigned int number)
SimpleStringCollection::SimpleStringCollection()
{
- collection_ = 0;
+ collection_ = NULLPTR;
size_ = 0;
}
diff --git a/src/CppUTest/SimpleStringInternalCache.cpp b/src/CppUTest/SimpleStringInternalCache.cpp
new file mode 100644
index 000000000..2964a2d2c
--- /dev/null
+++ b/src/CppUTest/SimpleStringInternalCache.cpp
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of the 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 EARLIER MENTIONED AUTHORS ''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 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.
+ */
+
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/SimpleStringInternalCache.h"
+
+struct SimpleStringMemoryBlock
+{
+ SimpleStringMemoryBlock* next_;
+ char* memory_;
+};
+
+struct SimpleStringInternalCacheNode
+{
+ size_t size_;
+ SimpleStringMemoryBlock* freeMemoryHead_;
+ SimpleStringMemoryBlock* usedMemoryHead_;
+};
+
+SimpleStringInternalCache::SimpleStringInternalCache()
+ : allocator_(defaultMallocAllocator()), cache_(NULLPTR), nonCachedAllocations_(NULLPTR), hasWarnedAboutDeallocations(false)
+{
+ cache_ = createInternalCacheNodes();
+}
+
+SimpleStringInternalCache::~SimpleStringInternalCache()
+{
+ allocator_ = defaultMallocAllocator();
+ destroyInternalCacheNode(cache_);
+}
+
+void SimpleStringInternalCache::setAllocator(TestMemoryAllocator* allocator)
+{
+ allocator_ = allocator;
+}
+
+SimpleStringInternalCacheNode* SimpleStringInternalCache::createInternalCacheNodes()
+{
+ SimpleStringInternalCacheNode* node = (SimpleStringInternalCacheNode*) (void*) allocator_->alloc_memory(sizeof(SimpleStringInternalCacheNode) * amountOfInternalCacheNodes, __FILE__, __LINE__);
+
+ for (int i = 0; i < amountOfInternalCacheNodes; i++) {
+ node[i].freeMemoryHead_ = NULLPTR;
+ node[i].usedMemoryHead_ = NULLPTR;
+ }
+ node[0].size_ = 32;
+ node[1].size_ = 64;
+ node[2].size_ = 96;
+ node[3].size_ = 128;
+ node[4].size_ = 256;
+ return node;
+}
+
+bool SimpleStringInternalCache::isCached(size_t size)
+{
+ return size <= 256;
+}
+
+size_t SimpleStringInternalCache::getIndexForCache(size_t size)
+{
+ for (size_t i = 0; i < amountOfInternalCacheNodes; i++)
+ if (size <= cache_[i].size_)
+ return i;
+ return 0; // LCOV_EXCL_LINE
+}
+
+SimpleStringInternalCacheNode* SimpleStringInternalCache::getCacheNodeFromSize(size_t size)
+{
+ size_t index = getIndexForCache(size);
+ return &cache_[index];
+}
+
+void SimpleStringInternalCache::destroyInternalCacheNode(SimpleStringInternalCacheNode * node)
+{
+ allocator_->free_memory((char*) node, sizeof(SimpleStringInternalCacheNode) * amountOfInternalCacheNodes, __FILE__, __LINE__);
+}
+
+SimpleStringMemoryBlock* SimpleStringInternalCache::createSimpleStringMemoryBlock(size_t size, SimpleStringMemoryBlock* next)
+{
+ SimpleStringMemoryBlock* block = (SimpleStringMemoryBlock*) (void*) allocator_->alloc_memory(sizeof(SimpleStringMemoryBlock) , __FILE__, __LINE__);
+ block->memory_ = allocator_->alloc_memory(size , __FILE__, __LINE__);
+ block->next_ = next;
+ return block;
+}
+
+void SimpleStringInternalCache::destroySimpleStringMemoryBlock(SimpleStringMemoryBlock * block, size_t size)
+{
+ allocator_->free_memory(block->memory_, size, __FILE__, __LINE__);
+ allocator_->free_memory((char*) block, sizeof(SimpleStringMemoryBlock), __FILE__, __LINE__);
+}
+
+void SimpleStringInternalCache::destroySimpleStringMemoryBlockList(SimpleStringMemoryBlock * block, size_t size)
+{
+ SimpleStringMemoryBlock* current = block;
+ while (current) {
+ SimpleStringMemoryBlock* next = current->next_;
+ destroySimpleStringMemoryBlock(current, size);
+ current = next;
+ }
+}
+
+SimpleStringMemoryBlock* SimpleStringInternalCache::addToSimpleStringMemoryBlockList(SimpleStringMemoryBlock* newBlock, SimpleStringMemoryBlock* previousHead)
+{
+ newBlock->next_ = previousHead;
+ return newBlock;
+}
+
+bool SimpleStringInternalCache::hasFreeBlocksOfSize(size_t size)
+{
+ return getCacheNodeFromSize(size)->freeMemoryHead_ != NULLPTR;
+}
+
+SimpleStringMemoryBlock* SimpleStringInternalCache::reserveCachedBlockFrom(SimpleStringInternalCacheNode* node)
+{
+ SimpleStringMemoryBlock* block = node->freeMemoryHead_;
+ node->freeMemoryHead_ = block->next_;
+ node->usedMemoryHead_ = addToSimpleStringMemoryBlockList(block, node->usedMemoryHead_);
+ return block;
+}
+
+SimpleStringMemoryBlock* SimpleStringInternalCache::allocateNewCacheBlockFrom(SimpleStringInternalCacheNode* node)
+{
+ SimpleStringMemoryBlock* block = createSimpleStringMemoryBlock(node->size_, node->usedMemoryHead_);
+ node->usedMemoryHead_ = addToSimpleStringMemoryBlockList(block, node->usedMemoryHead_);
+ return block;
+}
+
+void SimpleStringInternalCache::printDeallocatingUnknownMemory(char* memory)
+{
+ if (!hasWarnedAboutDeallocations) {
+ hasWarnedAboutDeallocations = true;
+ UtestShell::getCurrent()->print(StringFromFormat("\nWARNING: Attempting to deallocate a String buffer that was allocated while not caching. Ignoring it!\n"
+ "This is likely due statics and will cause problems.\n"
+ "Only warning once to avoid recursive warnings.\n"
+ "String we are deallocating: \"%s\"\n", memory).asCharString(), __FILE__, __LINE__);
+ }
+}
+
+void SimpleStringInternalCache::releaseCachedBlockFrom(char* memory, SimpleStringInternalCacheNode* node)
+{
+ if (node->usedMemoryHead_ && node->usedMemoryHead_->memory_ == memory) {
+ SimpleStringMemoryBlock* block = node->usedMemoryHead_;
+ node->usedMemoryHead_ = node->usedMemoryHead_->next_;
+ node->freeMemoryHead_ = addToSimpleStringMemoryBlockList(block, node->freeMemoryHead_);
+ return;
+ }
+
+ for (SimpleStringMemoryBlock* block = node->usedMemoryHead_; block; block = block->next_) {
+ if (block->next_ && block->next_->memory_ == memory) {
+ SimpleStringMemoryBlock* blockToFree = block->next_;
+ block->next_ = block->next_->next_;
+ node->freeMemoryHead_ = addToSimpleStringMemoryBlockList(blockToFree, node->freeMemoryHead_);
+ return;
+ }
+ }
+ printDeallocatingUnknownMemory(memory);
+
+}
+
+void SimpleStringInternalCache::releaseNonCachedMemory(char* memory, size_t size)
+{
+ if (nonCachedAllocations_ && nonCachedAllocations_->memory_ == memory) {
+ SimpleStringMemoryBlock* block = nonCachedAllocations_;
+ nonCachedAllocations_ = block->next_;
+ destroySimpleStringMemoryBlock(block, size);
+ return;
+ }
+
+ for (SimpleStringMemoryBlock* block = nonCachedAllocations_; block; block = block->next_) {
+ if (block->next_ && block->next_->memory_ == memory) {
+ SimpleStringMemoryBlock* blockToFree = block->next_;
+ block->next_ = block->next_->next_;
+ destroySimpleStringMemoryBlock(blockToFree, size);
+ return;
+ }
+ }
+
+ printDeallocatingUnknownMemory(memory);
+}
+
+char* SimpleStringInternalCache::alloc(size_t size)
+{
+ if (isCached(size)) {
+ if (hasFreeBlocksOfSize(size))
+ return reserveCachedBlockFrom(getCacheNodeFromSize(size))->memory_;
+ else
+ return allocateNewCacheBlockFrom(getCacheNodeFromSize(size))->memory_;
+ }
+
+ nonCachedAllocations_ = createSimpleStringMemoryBlock(size, nonCachedAllocations_);
+ return nonCachedAllocations_->memory_;
+}
+
+void SimpleStringInternalCache::dealloc(char* memory, size_t size)
+{
+ if (isCached(size)) {
+ size_t index = getIndexForCache(size);
+ SimpleStringInternalCacheNode* cacheNode = &cache_[index];
+ releaseCachedBlockFrom(memory, cacheNode);
+ return;
+ }
+ releaseNonCachedMemory(memory, size);
+}
+
+void SimpleStringInternalCache::clearCache()
+{
+ for (size_t i = 0; i < amountOfInternalCacheNodes; i++) {
+ destroySimpleStringMemoryBlockList(cache_[i].freeMemoryHead_, cache_[i].size_);
+ cache_[i].freeMemoryHead_ = NULLPTR;
+ }
+}
+
+void SimpleStringInternalCache::clearAllIncludingCurrentlyUsedMemory()
+{
+ for (size_t i = 0; i < amountOfInternalCacheNodes; i++) {
+ destroySimpleStringMemoryBlockList(cache_[i].freeMemoryHead_, cache_[i].size_);
+ destroySimpleStringMemoryBlockList(cache_[i].usedMemoryHead_, cache_[i].size_);
+ cache_[i].freeMemoryHead_ = NULLPTR;
+ cache_[i].usedMemoryHead_ = NULLPTR;
+ }
+
+ destroySimpleStringMemoryBlockList(nonCachedAllocations_, 0);
+ nonCachedAllocations_ = NULLPTR;
+}
+
+GlobalSimpleStringCache::GlobalSimpleStringCache()
+{
+ allocator_ = new SimpleStringCacheAllocator(cache_, SimpleString::getStringAllocator());
+ SimpleString::setStringAllocator(allocator_);
+}
+
+GlobalSimpleStringCache::~GlobalSimpleStringCache()
+{
+ SimpleString::setStringAllocator(allocator_->originalAllocator());
+ cache_.clearAllIncludingCurrentlyUsedMemory();
+ delete allocator_;
+}
+
+TestMemoryAllocator* GlobalSimpleStringCache::getAllocator()
+{
+ return allocator_;
+}
+
+SimpleStringCacheAllocator::SimpleStringCacheAllocator(SimpleStringInternalCache& cache, TestMemoryAllocator* origAllocator)
+ : cache_(cache), originalAllocator_(origAllocator)
+{
+ cache_.setAllocator(origAllocator);
+}
+
+SimpleStringCacheAllocator::~SimpleStringCacheAllocator()
+{
+ cache_.setAllocator(NULLPTR);
+}
+
+char* SimpleStringCacheAllocator::alloc_memory(size_t size, const char*, size_t)
+{
+ return cache_.alloc(size);
+}
+
+void SimpleStringCacheAllocator::free_memory(char* memory, size_t size, const char*, size_t)
+{
+ cache_.dealloc(memory, size);
+}
+
+const char* SimpleStringCacheAllocator::name() const
+{
+ return "SimpleStringCacheAllocator";
+}
+
+const char* SimpleStringCacheAllocator::alloc_name() const
+{
+ return originalAllocator_->alloc_name();
+}
+
+const char* SimpleStringCacheAllocator::free_name() const
+{
+ return originalAllocator_->free_name();
+}
+
+TestMemoryAllocator* SimpleStringCacheAllocator::actualAllocator()
+{
+ return originalAllocator_->actualAllocator();
+}
+
+TestMemoryAllocator* SimpleStringCacheAllocator::originalAllocator()
+{
+ return originalAllocator_;
+}
+
diff --git a/src/CppUTest/TeamCityTestOutput.cpp b/src/CppUTest/TeamCityTestOutput.cpp
index 779bc6eb4..faa775363 100644
--- a/src/CppUTest/TeamCityTestOutput.cpp
+++ b/src/CppUTest/TeamCityTestOutput.cpp
@@ -1,7 +1,7 @@
#include "CppUTest/TestHarness.h"
#include "CppUTest/TeamCityTestOutput.h"
-TeamCityTestOutput::TeamCityTestOutput() : currtest_(0), currGroup_()
+TeamCityTestOutput::TeamCityTestOutput() : currtest_(NULLPTR), currGroup_()
{
}
@@ -12,11 +12,11 @@ TeamCityTestOutput::~TeamCityTestOutput()
void TeamCityTestOutput::printCurrentTestStarted(const UtestShell& test)
{
print("##teamcity[testStarted name='");
- print(test.getName().asCharString());
+ printEscaped(test.getName().asCharString());
print("']\n");
if (!test.willRun()) {
print("##teamcity[testIgnored name='");
- print(test.getName().asCharString());
+ printEscaped(test.getName().asCharString());
print("']\n");
}
currtest_ = &test;
@@ -28,7 +28,7 @@ void TeamCityTestOutput::printCurrentTestEnded(const TestResult& res)
return;
print("##teamcity[testFinished name='");
- print(currtest_->getName().asCharString());
+ printEscaped(currtest_->getName().asCharString());
print("' duration='");
print(res.getCurrentTestTotalExecutionTime());
print("']\n");
@@ -38,7 +38,7 @@ void TeamCityTestOutput::printCurrentGroupStarted(const UtestShell& test)
{
currGroup_ = test.getGroup();
print("##teamcity[testSuiteStarted name='");
- print(currGroup_.asCharString());
+ printEscaped(currGroup_.asCharString());
print("']\n");
}
@@ -48,7 +48,7 @@ void TeamCityTestOutput::printCurrentGroupEnded(const TestResult& /*res*/)
return;
print("##teamcity[testSuiteFinished name='");
- print(currGroup_.asCharString());
+ printEscaped(currGroup_.asCharString());
print("']\n");
}
@@ -80,7 +80,7 @@ void TeamCityTestOutput::printEscaped(const char* s)
void TeamCityTestOutput::printFailure(const TestFailure& failure)
{
print("##teamcity[testFailed name='");
- print(failure.getTestNameOnly().asCharString());
+ printEscaped(failure.getTestNameOnly().asCharString());
print("' message='");
if (failure.isOutsideTestFile() || failure.isInHelperFunction()) {
print("TEST failed (");
@@ -90,7 +90,7 @@ void TeamCityTestOutput::printFailure(const TestFailure& failure)
print("): ");
}
- print(failure.getFileName().asCharString());
+ printEscaped(failure.getFileName().asCharString());
print(":");
print(failure.getFailureLineNumber());
diff --git a/src/CppUTest/TestFailure.cpp b/src/CppUTest/TestFailure.cpp
index a077578dd..a3a9bb82e 100644
--- a/src/CppUTest/TestFailure.cpp
+++ b/src/CppUTest/TestFailure.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -31,36 +31,15 @@
#include "CppUTest/SimpleString.h"
#include "CppUTest/PlatformSpecificFunctions.h"
-static SimpleString removeAllPrintableCharactersFrom(const SimpleString& str)
-{
- size_t bufferSize = str.size()+1;
- char* buffer = (char*) PlatformSpecificMalloc(bufferSize);
- str.copyToBuffer(buffer, bufferSize);
-
- for (size_t i = 0; i < bufferSize-1; i++)
- if (buffer[i] != '\t' && buffer[i] != '\n')
- buffer[i] = ' ';
-
- SimpleString result(buffer);
- PlatformSpecificFree(buffer);
- return result;
-}
+#if CPPUTEST_USE_STD_CPP_LIB
+#include
+#if defined(__GNUC__)
+#include
+#include
+#endif
+#endif
-static SimpleString addMarkerToString(const SimpleString& str, int markerPos)
-{
- size_t bufferSize = str.size()+1;
- char* buffer = (char*) PlatformSpecificMalloc(bufferSize);
- str.copyToBuffer(buffer, bufferSize);
-
- buffer[markerPos] = '^';
-
- SimpleString result(buffer);
- PlatformSpecificFree(buffer);
- return result;
-
-}
-
-TestFailure::TestFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& theMessage) :
+TestFailure::TestFailure(UtestShell* test, const char* fileName, size_t lineNumber, const SimpleString& theMessage) :
testName_(test->getFormattedName()), testNameOnly_(test->getName()), fileName_(fileName), lineNumber_(lineNumber), testFileName_(test->getFile()), testLineNumber_(test->getLineNumber()), message_(theMessage)
{
}
@@ -70,7 +49,7 @@ TestFailure::TestFailure(UtestShell* test, const SimpleString& theMessage) :
{
}
-TestFailure::TestFailure(UtestShell* test, const char* fileName, int lineNum) :
+TestFailure::TestFailure(UtestShell* test, const char* fileName, size_t lineNum) :
testName_(test->getFormattedName()), testNameOnly_(test->getName()), fileName_(fileName), lineNumber_(lineNum), testFileName_(test->getFile()), testLineNumber_(test->getLineNumber()), message_("no message")
{
}
@@ -105,12 +84,12 @@ SimpleString TestFailure::getTestNameOnly() const
return testNameOnly_;
}
-int TestFailure::getFailureLineNumber() const
+size_t TestFailure::getFailureLineNumber() const
{
return lineNumber_;
}
-int TestFailure::getTestLineNumber() const
+size_t TestFailure::getTestLineNumber() const
{
return testLineNumber_;
}
@@ -135,25 +114,21 @@ SimpleString TestFailure::createButWasString(const SimpleString& expected, const
return StringFromFormat("expected <%s>\n\tbut was <%s>", expected.asCharString(), actual.asCharString());
}
-SimpleString TestFailure::createDifferenceAtPosString(const SimpleString& actual, size_t position, DifferenceFormat format)
+SimpleString TestFailure::createDifferenceAtPosString(const SimpleString& actual, size_t offset, size_t reportedPosition)
{
SimpleString result;
const size_t extraCharactersWindow = 20;
const size_t halfOfExtraCharactersWindow = extraCharactersWindow / 2;
- const size_t actualOffset = (format == DIFFERENCE_STRING) ? position : (position * 3 + 1);
SimpleString paddingForPreventingOutOfBounds (" ", halfOfExtraCharactersWindow);
SimpleString actualString = paddingForPreventingOutOfBounds + actual + paddingForPreventingOutOfBounds;
- SimpleString differentString = StringFromFormat("difference starts at position %lu at: <", (unsigned long) position);
+ SimpleString differentString = StringFromFormat("difference starts at position %lu at: <", (unsigned long) reportedPosition);
result += "\n";
- result += StringFromFormat("\t%s%s>\n", differentString.asCharString(), actualString.subString(actualOffset, extraCharactersWindow).asCharString());
+ result += StringFromFormat("\t%s%s>\n", differentString.asCharString(), actualString.subString(offset, extraCharactersWindow).asCharString());
- SimpleString markString = actualString.subString(actualOffset, halfOfExtraCharactersWindow+1);
- markString = removeAllPrintableCharactersFrom(markString);
- markString = addMarkerToString(markString, halfOfExtraCharactersWindow);
- result += StringFromFormat("\t%s%s", SimpleString(" ", differentString.size()).asCharString(), markString.asCharString());
+ result += StringFromFormat("\t%s^", SimpleString(" ", (differentString.size() + halfOfExtraCharactersWindow)).asCharString());
return result;
}
@@ -162,14 +137,18 @@ SimpleString TestFailure::createUserText(const SimpleString& text)
SimpleString userMessage = "";
if (!text.isEmpty())
{
- userMessage += "Message: ";
+ //This is a kludge to turn off "Message: " for this case.
+ //I don't think "Message: " adds anything, as you get to see the
+ //message. I propose we remove "Message: " lead in
+ if (!text.startsWith("LONGS_EQUAL"))
+ userMessage += "Message: ";
userMessage += text;
userMessage += "\n\t";
}
return userMessage;
}
-EqualsFailure::EqualsFailure(UtestShell* test, const char* fileName, int lineNumber, const char* expected, const char* actual, const SimpleString& text) :
+EqualsFailure::EqualsFailure(UtestShell* test, const char* fileName, size_t lineNumber, const char* expected, const char* actual, const SimpleString& text) :
TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
@@ -177,7 +156,7 @@ EqualsFailure::EqualsFailure(UtestShell* test, const char* fileName, int lineNum
message_ += createButWasString(StringFromOrNull(expected), StringFromOrNull(actual));
}
-EqualsFailure::EqualsFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual, const SimpleString& text)
+EqualsFailure::EqualsFailure(UtestShell* test, const char* fileName, size_t lineNumber, const SimpleString& expected, const SimpleString& actual, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
@@ -185,7 +164,7 @@ EqualsFailure::EqualsFailure(UtestShell* test, const char* fileName, int lineNum
message_ += createButWasString(expected, actual);
}
-DoublesEqualFailure::DoublesEqualFailure(UtestShell* test, const char* fileName, int lineNumber, double expected, double actual, double threshold, const SimpleString& text)
+DoublesEqualFailure::DoublesEqualFailure(UtestShell* test, const char* fileName, size_t lineNumber, double expected, double actual, double threshold, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
@@ -199,20 +178,36 @@ DoublesEqualFailure::DoublesEqualFailure(UtestShell* test, const char* fileName,
message_ += "\n\tCannot make comparisons with Nan";
}
-CheckEqualFailure::CheckEqualFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual, const SimpleString& text)
+CheckEqualFailure::CheckEqualFailure(UtestShell* test, const char* fileName, size_t lineNumber, const SimpleString& expected, const SimpleString& actual, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
+ SimpleString printableExpected = PrintableStringFromOrNull(expected.asCharString());
+ SimpleString printableActual = PrintableStringFromOrNull(actual.asCharString());
+
+ message_ += createButWasString(printableExpected, printableActual);
+
size_t failStart;
- for (failStart = 0; actual.asCharString()[failStart] == expected.asCharString()[failStart]; failStart++)
+ for (failStart = 0; actual.at(failStart) == expected.at(failStart); failStart++)
;
- message_ += createButWasString(expected, actual);
- message_ += createDifferenceAtPosString(actual, failStart);
+ size_t failStartPrintable;
+ for (failStartPrintable = 0; printableActual.at(failStartPrintable) == printableExpected.at(failStartPrintable); failStartPrintable++)
+ ;
+ message_ += createDifferenceAtPosString(printableActual, failStartPrintable, failStart);
+}
+ComparisonFailure::ComparisonFailure(UtestShell *test, const char *fileName, size_t lineNumber, const SimpleString& checkString, const SimpleString &comparisonString, const SimpleString &text)
+: TestFailure(test, fileName, lineNumber)
+{
+ message_ = createUserText(text);
+ message_ += checkString;
+ message_ += "(";
+ message_ += comparisonString;
+ message_ += ") failed";
}
-ContainsFailure::ContainsFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual, const SimpleString& text)
+ContainsFailure::ContainsFailure(UtestShell* test, const char* fileName, size_t lineNumber, const SimpleString& expected, const SimpleString& actual, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
@@ -220,7 +215,7 @@ ContainsFailure::ContainsFailure(UtestShell* test, const char* fileName, int lin
message_ += StringFromFormat("actual <%s>\n\tdid not contain <%s>", actual.asCharString(), expected.asCharString());
}
-CheckFailure::CheckFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& checkString, const SimpleString& conditionString, const SimpleString& text)
+CheckFailure::CheckFailure(UtestShell* test, const char* fileName, size_t lineNumber, const SimpleString& checkString, const SimpleString& conditionString, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
@@ -231,148 +226,150 @@ CheckFailure::CheckFailure(UtestShell* test, const char* fileName, int lineNumbe
message_ += ") failed";
}
-FailFailure::FailFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& message) : TestFailure(test, fileName, lineNumber)
+FailFailure::FailFailure(UtestShell* test, const char* fileName, size_t lineNumber, const SimpleString& message) : TestFailure(test, fileName, lineNumber)
{
message_ = message;
}
-LongsEqualFailure::LongsEqualFailure(UtestShell* test, const char* fileName, int lineNumber, long expected, long actual, const SimpleString& text)
+LongsEqualFailure::LongsEqualFailure(UtestShell* test, const char* fileName, size_t lineNumber, long expected, long actual, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
SimpleString aDecimal = StringFrom(actual);
- SimpleString aHex = HexStringFrom(actual);
SimpleString eDecimal = StringFrom(expected);
- SimpleString eHex = HexStringFrom(expected);
SimpleString::padStringsToSameLength(aDecimal, eDecimal, ' ');
- SimpleString::padStringsToSameLength(aHex, eHex, '0');
- SimpleString actualReported = aDecimal + " 0x" + aHex;
- SimpleString expectedReported = eDecimal + " 0x" + eHex;
+ SimpleString actualReported = aDecimal + " " + BracketsFormattedHexStringFrom(actual);
+ SimpleString expectedReported = eDecimal + " " + BracketsFormattedHexStringFrom(expected);
message_ += createButWasString(expectedReported, actualReported);
}
-UnsignedLongsEqualFailure::UnsignedLongsEqualFailure(UtestShell* test, const char* fileName, int lineNumber, unsigned long expected, unsigned long actual, const SimpleString& text)
+UnsignedLongsEqualFailure::UnsignedLongsEqualFailure(UtestShell* test, const char* fileName, size_t lineNumber, unsigned long expected, unsigned long actual, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
SimpleString aDecimal = StringFrom(actual);
- SimpleString aHex = HexStringFrom(actual);
SimpleString eDecimal = StringFrom(expected);
- SimpleString eHex = HexStringFrom(expected);
SimpleString::padStringsToSameLength(aDecimal, eDecimal, ' ');
- SimpleString::padStringsToSameLength(aHex, eHex, '0');
- SimpleString actualReported = aDecimal + " 0x" + aHex;
- SimpleString expectedReported = eDecimal + " 0x" + eHex;
+ SimpleString actualReported = aDecimal + " " + BracketsFormattedHexStringFrom(actual);
+ SimpleString expectedReported = eDecimal + " " + BracketsFormattedHexStringFrom(expected);
+
message_ += createButWasString(expectedReported, actualReported);
}
-LongLongsEqualFailure::LongLongsEqualFailure(UtestShell* test, const char* fileName, int lineNumber, cpputest_longlong expected, cpputest_longlong actual, const SimpleString& text)
+LongLongsEqualFailure::LongLongsEqualFailure(UtestShell* test, const char* fileName, size_t lineNumber, cpputest_longlong expected, cpputest_longlong actual, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
SimpleString aDecimal = StringFrom(actual);
- SimpleString aHex = HexStringFrom(actual);
SimpleString eDecimal = StringFrom(expected);
- SimpleString eHex = HexStringFrom(expected);
SimpleString::padStringsToSameLength(aDecimal, eDecimal, ' ');
- SimpleString::padStringsToSameLength(aHex, eHex, '0');
- SimpleString actualReported = aDecimal + " 0x" + aHex;
- SimpleString expectedReported = eDecimal + " 0x" + eHex;
+ SimpleString actualReported = aDecimal + " " + BracketsFormattedHexStringFrom(actual);
+ SimpleString expectedReported = eDecimal + " " + BracketsFormattedHexStringFrom(expected);
message_ += createButWasString(expectedReported, actualReported);
}
-UnsignedLongLongsEqualFailure::UnsignedLongLongsEqualFailure(UtestShell* test, const char* fileName, int lineNumber, cpputest_ulonglong expected, cpputest_ulonglong actual, const SimpleString& text)
+UnsignedLongLongsEqualFailure::UnsignedLongLongsEqualFailure(UtestShell* test, const char* fileName, size_t lineNumber, cpputest_ulonglong expected, cpputest_ulonglong actual, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
SimpleString aDecimal = StringFrom(actual);
- SimpleString aHex = HexStringFrom(actual);
SimpleString eDecimal = StringFrom(expected);
- SimpleString eHex = HexStringFrom(expected);
SimpleString::padStringsToSameLength(aDecimal, eDecimal, ' ');
- SimpleString::padStringsToSameLength(aHex, eHex, '0');
- SimpleString actualReported = aDecimal + " 0x" + aHex;
- SimpleString expectedReported = eDecimal + " 0x" + eHex;
+ SimpleString actualReported = aDecimal + " " + BracketsFormattedHexStringFrom(actual);
+ SimpleString expectedReported = eDecimal + " " + BracketsFormattedHexStringFrom(expected);
message_ += createButWasString(expectedReported, actualReported);
}
-SignedBytesEqualFailure::SignedBytesEqualFailure (UtestShell* test, const char* fileName, int lineNumber, signed char expected, signed char actual, const SimpleString& text)
+SignedBytesEqualFailure::SignedBytesEqualFailure (UtestShell* test, const char* fileName, size_t lineNumber, signed char expected, signed char actual, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
SimpleString aDecimal = StringFrom((int)actual);
- SimpleString aHex = HexStringFrom(actual);
SimpleString eDecimal = StringFrom((int)expected);
- SimpleString eHex = HexStringFrom(expected);
SimpleString::padStringsToSameLength(aDecimal, eDecimal, ' ');
- SimpleString::padStringsToSameLength(aHex, eHex, '0');
- SimpleString actualReported = aDecimal + " 0x" + aHex;
- SimpleString expectedReported = eDecimal + " 0x" + eHex;
+ SimpleString actualReported = aDecimal + " " + BracketsFormattedHexStringFrom(actual);
+ SimpleString expectedReported = eDecimal + " " + BracketsFormattedHexStringFrom(expected);
message_ += createButWasString(expectedReported, actualReported);
}
-StringEqualFailure::StringEqualFailure(UtestShell* test, const char* fileName, int lineNumber, const char* expected, const char* actual, const SimpleString& text)
+StringEqualFailure::StringEqualFailure(UtestShell* test, const char* fileName, size_t lineNumber, const char* expected, const char* actual, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
- message_ += createButWasString(StringFromOrNull(expected), StringFromOrNull(actual));
+ SimpleString printableExpected = PrintableStringFromOrNull(expected);
+ SimpleString printableActual = PrintableStringFromOrNull(actual);
+
+ message_ += createButWasString(printableExpected, printableActual);
if((expected) && (actual))
{
size_t failStart;
for (failStart = 0; actual[failStart] == expected[failStart]; failStart++)
;
- message_ += createDifferenceAtPosString(actual, failStart);
+ size_t failStartPrintable;
+ for (failStartPrintable = 0; printableActual.at(failStartPrintable) == printableExpected.at(failStartPrintable); failStartPrintable++)
+ ;
+ message_ += createDifferenceAtPosString(printableActual, failStartPrintable, failStart);
}
}
-StringEqualNoCaseFailure::StringEqualNoCaseFailure(UtestShell* test, const char* fileName, int lineNumber, const char* expected, const char* actual, const SimpleString& text)
+StringEqualNoCaseFailure::StringEqualNoCaseFailure(UtestShell* test, const char* fileName, size_t lineNumber, const char* expected, const char* actual, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
- message_ += createButWasString(StringFromOrNull(expected), StringFromOrNull(actual));
+ SimpleString printableExpected = PrintableStringFromOrNull(expected);
+ SimpleString printableActual = PrintableStringFromOrNull(actual);
+
+ message_ += createButWasString(printableExpected, printableActual);
if((expected) && (actual))
{
size_t failStart;
for (failStart = 0; SimpleString::ToLower(actual[failStart]) == SimpleString::ToLower(expected[failStart]); failStart++)
;
- message_ += createDifferenceAtPosString(actual, failStart);
+ size_t failStartPrintable;
+ for (failStartPrintable = 0;
+ SimpleString::ToLower(printableActual.at(failStartPrintable)) == SimpleString::ToLower(printableExpected.at(failStartPrintable));
+ failStartPrintable++)
+ ;
+ message_ += createDifferenceAtPosString(printableActual, failStartPrintable, failStart);
}
}
-BinaryEqualFailure::BinaryEqualFailure(UtestShell* test, const char* fileName, int lineNumber, const unsigned char* expected,
+BinaryEqualFailure::BinaryEqualFailure(UtestShell* test, const char* fileName, size_t lineNumber, const unsigned char* expected,
const unsigned char* actual, size_t size, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
- message_ += createButWasString(StringFromBinaryOrNull(expected, size), StringFromBinaryOrNull(actual, size));
+ SimpleString actualHex = StringFromBinaryOrNull(actual, size);
+
+ message_ += createButWasString(StringFromBinaryOrNull(expected, size), actualHex);
if ((expected) && (actual))
{
size_t failStart;
for (failStart = 0; actual[failStart] == expected[failStart]; failStart++)
;
- message_ += createDifferenceAtPosString(StringFromBinary(actual, size), failStart, DIFFERENCE_BINARY);
+ message_ += createDifferenceAtPosString(actualHex, (failStart * 3 + 1), failStart);
}
}
-BitsEqualFailure::BitsEqualFailure(UtestShell* test, const char* fileName, int lineNumber, unsigned long expected, unsigned long actual,
+BitsEqualFailure::BitsEqualFailure(UtestShell* test, const char* fileName, size_t lineNumber, unsigned long expected, unsigned long actual,
unsigned long mask, size_t byteCount, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
@@ -381,11 +378,55 @@ BitsEqualFailure::BitsEqualFailure(UtestShell* test, const char* fileName, int l
message_ += createButWasString(StringFromMaskedBits(expected, mask, byteCount), StringFromMaskedBits(actual, mask, byteCount));
}
-FeatureUnsupportedFailure::FeatureUnsupportedFailure(UtestShell* test, const char* fileName, int lineNumber,
+FeatureUnsupportedFailure::FeatureUnsupportedFailure(UtestShell* test, const char* fileName, size_t lineNumber,
const SimpleString& featureName, const SimpleString& text)
: TestFailure(test, fileName, lineNumber)
{
message_ = createUserText(text);
- message_ += StringFromFormat("The feature \"%s\" is not supported in this environment or with the feature set selected when building the library.", featureName.asCharString());;
+ message_ += StringFromFormat("The feature \"%s\" is not supported in this environment or with the feature set selected when building the library.", featureName.asCharString());
+}
+
+#if CPPUTEST_HAVE_EXCEPTIONS
+UnexpectedExceptionFailure::UnexpectedExceptionFailure(UtestShell* test)
+: TestFailure(test, "Unexpected exception of unknown type was thrown.")
+{
+}
+
+#if CPPUTEST_USE_STD_CPP_LIB
+#if CPPUTEST_HAVE_RTTI
+static SimpleString getExceptionTypeName(const std::exception &e)
+{
+ const char *name = typeid(e).name();
+#if defined(__GNUC__) && (__cplusplus >= 201103L)
+ int status = -1;
+
+ std::unique_ptr demangledName(
+ abi::__cxa_demangle(name, NULLPTR, NULLPTR, &status),
+ std::free );
+
+ return (status==0) ? demangledName.get() : name;
+#else
+ return name;
+#endif
+}
+#endif // CPPUTEST_HAVE_RTTI
+
+UnexpectedExceptionFailure::UnexpectedExceptionFailure(UtestShell* test, const std::exception &e)
+: TestFailure(
+ test,
+#if CPPUTEST_HAVE_RTTI
+ StringFromFormat(
+ "Unexpected exception of type '%s' was thrown: %s",
+ getExceptionTypeName(e).asCharString(),
+ e.what()
+ )
+#else
+ "Unexpected exception of unknown type was thrown."
+#endif
+)
+{
+ (void) e;
}
+#endif // CPPUTEST_USE_STD_CPP_LIB
+#endif // CPPUTEST_HAVE_EXCEPTIONS
diff --git a/src/CppUTest/TestFilter.cpp b/src/CppUTest/TestFilter.cpp
index a684c0891..326767afc 100644
--- a/src/CppUTest/TestFilter.cpp
+++ b/src/CppUTest/TestFilter.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -28,16 +28,16 @@
#include "CppUTest/CppUTestConfig.h"
#include "CppUTest/TestFilter.h"
-TestFilter::TestFilter() : strictMatching_(false), invertMatching_(false), next_(NULL)
+TestFilter::TestFilter() : strictMatching_(false), invertMatching_(false), next_(NULLPTR)
{
}
-TestFilter::TestFilter(const SimpleString& filter) : strictMatching_(false), invertMatching_(false), next_(NULL)
+TestFilter::TestFilter(const SimpleString& filter) : strictMatching_(false), invertMatching_(false), next_(NULLPTR)
{
filter_ = filter;
}
-TestFilter::TestFilter(const char* filter) : strictMatching_(false), invertMatching_(false), next_(NULL)
+TestFilter::TestFilter(const char* filter) : strictMatching_(false), invertMatching_(false), next_(NULLPTR)
{
filter_ = filter;
}
diff --git a/src/CppUTest/TestHarness_c.cpp b/src/CppUTest/TestHarness_c.cpp
index 6fb9d3c29..149c8fbb6 100644
--- a/src/CppUTest/TestHarness_c.cpp
+++ b/src/CppUTest/TestHarness_c.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -34,60 +34,94 @@
extern "C"
{
+void CHECK_EQUAL_C_BOOL_LOCATION(int expected, int actual, const char* text, const char* fileName, size_t lineNumber)
+{
+ UtestShell::getCurrent()->assertEquals(!!expected != !!actual, expected ? "true" : "false", actual ? "true" : "false", text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
+}
+
+void CHECK_EQUAL_C_INT_LOCATION(int expected, int actual, const char* text, const char* fileName, size_t lineNumber)
+{
+ UtestShell::getCurrent()->assertLongsEqual((long)expected, (long)actual, text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
+}
+
+void CHECK_EQUAL_C_UINT_LOCATION(unsigned int expected, unsigned int actual, const char* text, const char* fileName, size_t lineNumber)
+{
+ UtestShell::getCurrent()->assertUnsignedLongsEqual((unsigned long)expected, (unsigned long)actual, text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
+}
+
+void CHECK_EQUAL_C_LONG_LOCATION(long expected, long actual, const char* text, const char* fileName, size_t lineNumber)
+{
+ UtestShell::getCurrent()->assertLongsEqual(expected, actual, text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
+}
+
+void CHECK_EQUAL_C_ULONG_LOCATION(unsigned long expected, unsigned long actual, const char* text, const char* fileName, size_t lineNumber)
+{
+ UtestShell::getCurrent()->assertUnsignedLongsEqual(expected, actual, text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
+}
+
+void CHECK_EQUAL_C_LONGLONG_LOCATION(cpputest_longlong expected, cpputest_longlong actual, const char* text, const char* fileName, size_t lineNumber)
+{
+ UtestShell::getCurrent()->assertLongLongsEqual(expected, actual, text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
+}
+
+void CHECK_EQUAL_C_ULONGLONG_LOCATION(cpputest_ulonglong expected, cpputest_ulonglong actual, const char* text, const char* fileName, size_t lineNumber)
+{
+ UtestShell::getCurrent()->assertUnsignedLongLongsEqual(expected, actual, text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
+}
-void CHECK_EQUAL_C_INT_LOCATION(int expected, int actual, const char* fileName, int lineNumber)
+void CHECK_EQUAL_C_REAL_LOCATION(double expected, double actual, double threshold, const char* text, const char* fileName, size_t lineNumber)
{
- UtestShell::getCurrent()->assertLongsEqual((long)expected, (long)actual, NULL, fileName, lineNumber, TestTerminatorWithoutExceptions());
+ UtestShell::getCurrent()->assertDoublesEqual(expected, actual, threshold, text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
}
-void CHECK_EQUAL_C_REAL_LOCATION(double expected, double actual, double threshold, const char* fileName, int lineNumber)
+void CHECK_EQUAL_C_CHAR_LOCATION(char expected, char actual, const char* text, const char* fileName, size_t lineNumber)
{
- UtestShell::getCurrent()->assertDoublesEqual(expected, actual, threshold, NULL, fileName, lineNumber, TestTerminatorWithoutExceptions());
+ UtestShell::getCurrent()->assertEquals(((expected) != (actual)), StringFrom(expected).asCharString(), StringFrom(actual).asCharString(), text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
}
-void CHECK_EQUAL_C_CHAR_LOCATION(char expected, char actual, const char* fileName, int lineNumber)
+extern void CHECK_EQUAL_C_UBYTE_LOCATION(unsigned char expected, unsigned char actual, const char* text, const char* fileName, size_t lineNumber)\
{
- UtestShell::getCurrent()->assertEquals(((expected) != (actual)), StringFrom(expected).asCharString(), StringFrom(actual).asCharString(), NULL, fileName, lineNumber, TestTerminatorWithoutExceptions());
+ UtestShell::getCurrent()->assertEquals(((expected) != (actual)),StringFrom((int)expected).asCharString(), StringFrom((int) actual).asCharString(), text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
}
-extern void CHECK_EQUAL_C_UBYTE_LOCATION(unsigned char expected, unsigned char actual, const char* fileName, int lineNumber)\
+void CHECK_EQUAL_C_SBYTE_LOCATION(char signed expected, signed char actual, const char* text, const char* fileName, size_t lineNumber)
{
- UtestShell::getCurrent()->assertEquals(((expected) != (actual)),StringFrom((int)expected).asCharString(), StringFrom((int) actual).asCharString(), NULL, fileName, lineNumber, TestTerminatorWithoutExceptions());
+ UtestShell::getCurrent()->assertEquals(((expected) != (actual)),StringFrom((int)expected).asCharString(), StringFrom((int) actual).asCharString(), text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
}
-void CHECK_EQUAL_C_SBYTE_LOCATION(char signed expected, signed char actual, const char* fileName, int lineNumber)
+void CHECK_EQUAL_C_STRING_LOCATION(const char* expected, const char* actual, const char* text, const char* fileName, size_t lineNumber)
{
- UtestShell::getCurrent()->assertEquals(((expected) != (actual)),StringFrom((int)expected).asCharString(), StringFrom((int) actual).asCharString(), NULL, fileName, lineNumber, TestTerminatorWithoutExceptions());
+ UtestShell::getCurrent()->assertCstrEqual(expected, actual, text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
}
-void CHECK_EQUAL_C_STRING_LOCATION(const char* expected, const char* actual, const char* fileName, int lineNumber)
+void CHECK_EQUAL_C_POINTER_LOCATION(const void* expected, const void* actual, const char* text, const char* fileName, size_t lineNumber)
{
- UtestShell::getCurrent()->assertCstrEqual(expected, actual, NULL, fileName, lineNumber, TestTerminatorWithoutExceptions());
+ UtestShell::getCurrent()->assertPointersEqual(expected, actual, text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
}
-void CHECK_EQUAL_C_POINTER_LOCATION(const void* expected, const void* actual, const char* fileName, int lineNumber)
+extern void CHECK_EQUAL_C_MEMCMP_LOCATION(const void* expected, const void* actual, size_t size, const char* text, const char* fileName, size_t lineNumber)
{
- UtestShell::getCurrent()->assertPointersEqual(expected, actual, NULL, fileName, lineNumber, TestTerminatorWithoutExceptions());
+ UtestShell::getCurrent()->assertBinaryEqual(expected, actual, size, text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
}
-extern void CHECK_EQUAL_C_BITS_LOCATION(unsigned int expected, unsigned int actual, unsigned int mask, size_t size, const char* fileName, int lineNumber)
+extern void CHECK_EQUAL_C_BITS_LOCATION(unsigned int expected, unsigned int actual, unsigned int mask, size_t size, const char* text, const char* fileName, size_t lineNumber)
{
- UtestShell::getCurrent()->assertBitsEqual(expected, actual, mask, size, NULL, fileName, lineNumber, TestTerminatorWithoutExceptions());
+ UtestShell::getCurrent()->assertBitsEqual(expected, actual, mask, size, text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
}
-void FAIL_TEXT_C_LOCATION(const char* text, const char* fileName, int lineNumber)
+void FAIL_TEXT_C_LOCATION(const char* text, const char* fileName, size_t lineNumber)
{
- UtestShell::getCurrent()->fail(text, fileName, lineNumber, TestTerminatorWithoutExceptions());
+ UtestShell::getCurrent()->fail(text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
} // LCOV_EXCL_LINE
-void FAIL_C_LOCATION(const char* fileName, int lineNumber)
+void FAIL_C_LOCATION(const char* fileName, size_t lineNumber)
{
- UtestShell::getCurrent()->fail("", fileName, lineNumber, TestTerminatorWithoutExceptions());
+ UtestShell::getCurrent()->fail("", fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
} // LCOV_EXCL_LINE
-void CHECK_C_LOCATION(int condition, const char* conditionString, const char* fileName, int lineNumber)
+void CHECK_C_LOCATION(int condition, const char* conditionString, const char* text, const char* fileName, size_t lineNumber)
{
- UtestShell::getCurrent()->assertTrue(condition != 0, "CHECK_C", conditionString, NULL, fileName, lineNumber, TestTerminatorWithoutExceptions());
+ UtestShell::getCurrent()->assertTrue(condition != 0, "CHECK_C", conditionString, text, fileName, lineNumber, UtestShell::getCurrentTestTerminatorWithoutExceptions());
}
enum { NO_COUNTDOWN = -1, OUT_OF_MEMORRY = 0 };
@@ -104,15 +138,20 @@ int cpputest_malloc_get_count()
return malloc_count;
}
+static TestMemoryAllocator* originalAllocator = NULLPTR;
+
void cpputest_malloc_set_out_of_memory()
{
+ if (originalAllocator == NULLPTR)
+ originalAllocator = getCurrentMallocAllocator();
setCurrentMallocAllocator(NullUnknownAllocator::defaultAllocator());
}
void cpputest_malloc_set_not_out_of_memory()
{
malloc_out_of_memory_counter = NO_COUNTDOWN;
- setCurrentMallocAllocatorToDefault();
+ setCurrentMallocAllocator(originalAllocator);
+ originalAllocator = NULLPTR;
}
void cpputest_malloc_set_out_of_memory_countdown(int count)
@@ -127,6 +166,16 @@ void* cpputest_malloc(size_t size)
return cpputest_malloc_location(size, "", 0);
}
+char* cpputest_strdup(const char* str)
+{
+ return cpputest_strdup_location(str, "", 0);
+}
+
+char* cpputest_strndup(const char* str, size_t n)
+{
+ return cpputest_strndup_location(str, n, "", 0);
+}
+
void* cpputest_calloc(size_t num, size_t size)
{
return cpputest_calloc_location(num, size, "", 0);
@@ -156,14 +205,44 @@ static void countdown()
cpputest_malloc_set_out_of_memory();
}
-void* cpputest_malloc_location(size_t size, const char* file, int line)
+void* cpputest_malloc_location(size_t size, const char* file, size_t line)
{
countdown();
malloc_count++;
return cpputest_malloc_location_with_leak_detection(size, file, line);
}
-void* cpputest_calloc_location(size_t num, size_t size, const char* file, int line)
+static size_t test_harness_c_strlen(const char * str)
+{
+ size_t n = 0;
+ while (*str++) n++;
+ return n;
+}
+
+static char* strdup_alloc(const char * str, size_t size, const char* file, size_t line)
+{
+ char* result = (char*) cpputest_malloc_location(size, file, line);
+ PlatformSpecificMemCpy(result, str, size);
+ result[size-1] = '\0';
+ return result;
+}
+
+char* cpputest_strdup_location(const char * str, const char* file, size_t line)
+{
+ size_t length = 1 + test_harness_c_strlen(str);
+ return strdup_alloc(str, length, file, line);
+}
+
+char* cpputest_strndup_location(const char * str, size_t n, const char* file, size_t line)
+{
+ size_t length = test_harness_c_strlen(str);
+ length = length < n ? length : n;
+ length = length + 1;
+ return strdup_alloc(str, length, file, line);
+}
+
+
+void* cpputest_calloc_location(size_t num, size_t size, const char* file, size_t line)
{
void* mem = cpputest_malloc_location(num * size, file, line);
if (mem)
@@ -171,12 +250,12 @@ void* cpputest_calloc_location(size_t num, size_t size, const char* file, int li
return mem;
}
-void* cpputest_realloc_location(void* memory, size_t size, const char* file, int line)
+void* cpputest_realloc_location(void* memory, size_t size, const char* file, size_t line)
{
return cpputest_realloc_location_with_leak_detection(memory, size, file, line);
}
-void cpputest_free_location(void* buffer, const char* file, int line)
+void cpputest_free_location(void* buffer, const char* file, size_t line)
{
cpputest_free_location_with_leak_detection(buffer, file, line);
}
diff --git a/src/CppUTest/TestMemoryAllocator.cpp b/src/CppUTest/TestMemoryAllocator.cpp
index 28f77adc0..71e3a7ca6 100644
--- a/src/CppUTest/TestMemoryAllocator.cpp
+++ b/src/CppUTest/TestMemoryAllocator.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -33,14 +33,14 @@
static char* checkedMalloc(size_t size)
{
char* mem = (char*) PlatformSpecificMalloc(size);
- if (mem == 0)
+ if (mem == NULLPTR)
FAIL("malloc returned null pointer");
return mem;
}
-static TestMemoryAllocator* currentNewAllocator = 0;
-static TestMemoryAllocator* currentNewArrayAllocator = 0;
-static TestMemoryAllocator* currentMallocAllocator = 0;
+static TestMemoryAllocator* currentNewAllocator = NULLPTR;
+static TestMemoryAllocator* currentNewArrayAllocator = NULLPTR;
+static TestMemoryAllocator* currentMallocAllocator = NULLPTR;
void setCurrentNewAllocator(TestMemoryAllocator* allocator)
{
@@ -49,7 +49,7 @@ void setCurrentNewAllocator(TestMemoryAllocator* allocator)
TestMemoryAllocator* getCurrentNewAllocator()
{
- if (currentNewAllocator == 0) setCurrentNewAllocatorToDefault();
+ if (currentNewAllocator == NULLPTR) setCurrentNewAllocatorToDefault();
return currentNewAllocator;
}
@@ -71,7 +71,7 @@ void setCurrentNewArrayAllocator(TestMemoryAllocator* allocator)
TestMemoryAllocator* getCurrentNewArrayAllocator()
{
- if (currentNewArrayAllocator == 0) setCurrentNewArrayAllocatorToDefault();
+ if (currentNewArrayAllocator == NULLPTR) setCurrentNewArrayAllocatorToDefault();
return currentNewArrayAllocator;
}
@@ -93,7 +93,7 @@ void setCurrentMallocAllocator(TestMemoryAllocator* allocator)
TestMemoryAllocator* getCurrentMallocAllocator()
{
- if (currentMallocAllocator == 0) setCurrentMallocAllocatorToDefault();
+ if (currentMallocAllocator == NULLPTR) setCurrentMallocAllocatorToDefault();
return currentMallocAllocator;
}
@@ -110,6 +110,25 @@ TestMemoryAllocator* defaultMallocAllocator()
/////////////////////////////////////////////
+GlobalMemoryAllocatorStash::GlobalMemoryAllocatorStash()
+ : originalMallocAllocator(NULLPTR), originalNewAllocator(NULLPTR), originalNewArrayAllocator(NULLPTR)
+{
+}
+
+void GlobalMemoryAllocatorStash::save()
+{
+ originalMallocAllocator = getCurrentMallocAllocator();
+ originalNewAllocator = getCurrentNewAllocator();
+ originalNewArrayAllocator = getCurrentNewArrayAllocator();
+}
+
+void GlobalMemoryAllocatorStash::restore()
+{
+ if (originalMallocAllocator) setCurrentMallocAllocator(originalMallocAllocator);
+ if (originalNewAllocator) setCurrentNewAllocator(originalNewAllocator);
+ if (originalNewArrayAllocator) setCurrentNewArrayAllocator(originalNewArrayAllocator);
+}
+
TestMemoryAllocator::TestMemoryAllocator(const char* name_str, const char* alloc_name_str, const char* free_name_str)
: name_(name_str), alloc_name_(alloc_name_str), free_name_(free_name_str), hasBeenDestroyed_(false)
{
@@ -137,43 +156,92 @@ char* TestMemoryAllocator::allocMemoryLeakNode(size_t size)
void TestMemoryAllocator::freeMemoryLeakNode(char* memory)
{
- free_memory(memory, "MemoryLeakNode", 1);
+ free_memory(memory, 0, "MemoryLeakNode", 1);
}
-char* TestMemoryAllocator::alloc_memory(size_t size, const char*, int)
+char* TestMemoryAllocator::alloc_memory(size_t size, const char*, size_t)
{
return checkedMalloc(size);
}
-void TestMemoryAllocator::free_memory(char* memory, const char*, int)
+void TestMemoryAllocator::free_memory(char* memory, size_t, const char*, size_t)
{
PlatformSpecificFree(memory);
}
-const char* TestMemoryAllocator::name()
+
+const char* TestMemoryAllocator::name() const
{
return name_;
}
-const char* TestMemoryAllocator::alloc_name()
+const char* TestMemoryAllocator::alloc_name() const
{
return alloc_name_;
}
-const char* TestMemoryAllocator::free_name()
+const char* TestMemoryAllocator::free_name() const
{
return free_name_;
}
+TestMemoryAllocator* TestMemoryAllocator::actualAllocator()
+{
+ return this;
+}
+
+MemoryLeakAllocator::MemoryLeakAllocator(TestMemoryAllocator* originalAllocator)
+ : originalAllocator_(originalAllocator)
+{
+}
+
+MemoryLeakAllocator::~MemoryLeakAllocator()
+{
+}
+
+char* MemoryLeakAllocator::alloc_memory(size_t size, const char* file, size_t line)
+{
+ return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(originalAllocator_, size, file, line);
+}
+
+void MemoryLeakAllocator::free_memory(char* memory, size_t, const char* file, size_t line)
+{
+ MemoryLeakWarningPlugin::getGlobalDetector()->deallocMemory(originalAllocator_, memory, file, line);
+}
+
+const char* MemoryLeakAllocator::name() const
+{
+ return "MemoryLeakAllocator";
+}
+
+const char* MemoryLeakAllocator::alloc_name() const
+{
+ return originalAllocator_->alloc_name();
+}
+
+const char* MemoryLeakAllocator::free_name() const
+{
+ return originalAllocator_->free_name();
+}
+
+TestMemoryAllocator* MemoryLeakAllocator::actualAllocator()
+{
+ return originalAllocator_->actualAllocator();
+}
+
CrashOnAllocationAllocator::CrashOnAllocationAllocator() : allocationToCrashOn_(0)
{
}
+CrashOnAllocationAllocator::~CrashOnAllocationAllocator()
+{
+}
+
void CrashOnAllocationAllocator::setNumberToCrashOn(unsigned allocationToCrashOn)
{
allocationToCrashOn_ = allocationToCrashOn;
}
-char* CrashOnAllocationAllocator::alloc_memory(size_t size, const char* file, int line)
+char* CrashOnAllocationAllocator::alloc_memory(size_t size, const char* file, size_t line)
{
if (MemoryLeakWarningPlugin::getGlobalDetector()->getCurrentAllocationNumber() == allocationToCrashOn_)
UT_CRASH();
@@ -182,12 +250,16 @@ char* CrashOnAllocationAllocator::alloc_memory(size_t size, const char* file, in
}
-char* NullUnknownAllocator::alloc_memory(size_t /*size*/, const char*, int)
+NullUnknownAllocator::~NullUnknownAllocator()
{
- return 0;
}
-void NullUnknownAllocator::free_memory(char* /*memory*/, const char*, int)
+char* NullUnknownAllocator::alloc_memory(size_t /*size*/, const char*, size_t)
+{
+ return NULLPTR;
+}
+
+void NullUnknownAllocator::free_memory(char* /*memory*/, size_t, const char*, size_t)
{
}
@@ -209,7 +281,7 @@ class LocationToFailAllocNode
int allocNumberToFail_;
int actualAllocNumber_;
const char* file_;
- int line_;
+ size_t line_;
LocationToFailAllocNode* next_;
void failAtAllocNumber(int number, LocationToFailAllocNode* next)
@@ -218,7 +290,7 @@ class LocationToFailAllocNode
allocNumberToFail_ = number;
}
- void failNthAllocAt(int allocationNumber, const char* file, int line, LocationToFailAllocNode* next)
+ void failNthAllocAt(int allocationNumber, const char* file, size_t line, LocationToFailAllocNode* next)
{
init(next);
allocNumberToFail_ = allocationNumber;
@@ -226,7 +298,7 @@ class LocationToFailAllocNode
line_ = line;
}
- bool shouldFail(int allocationNumber, const char* file, int line)
+ bool shouldFail(int allocationNumber, const char* file, size_t line)
{
if (file_ && SimpleString::StrCmp(file, file_) == 0 && line == line_) {
actualAllocNumber_++;
@@ -238,19 +310,23 @@ class LocationToFailAllocNode
}
private:
- void init(LocationToFailAllocNode* next = NULL)
+ void init(LocationToFailAllocNode* next = NULLPTR)
{
allocNumberToFail_ = 0;
actualAllocNumber_ = 0;
- file_ = NULL;
+ file_ = NULLPTR;
line_ = 0;
next_ = next;
}
};
+FailableMemoryAllocator::~FailableMemoryAllocator()
+{
+}
+
FailableMemoryAllocator::FailableMemoryAllocator(const char* name_str, const char* alloc_name_str, const char* free_name_str)
-: TestMemoryAllocator(name_str, alloc_name_str, free_name_str), head_(NULL), currentAllocNumber_(0)
+: TestMemoryAllocator(name_str, alloc_name_str, free_name_str), head_(NULLPTR), currentAllocNumber_(0)
{
}
@@ -261,26 +337,26 @@ void FailableMemoryAllocator::failAllocNumber(int number)
head_ = newNode;
}
-void FailableMemoryAllocator::failNthAllocAt(int allocationNumber, const char* file, int line)
+void FailableMemoryAllocator::failNthAllocAt(int allocationNumber, const char* file, size_t line)
{
LocationToFailAllocNode* newNode = (LocationToFailAllocNode*) (void*) allocMemoryLeakNode(sizeof(LocationToFailAllocNode));
newNode->failNthAllocAt(allocationNumber, file, line, head_);
head_ = newNode;
}
-char* FailableMemoryAllocator::alloc_memory(size_t size, const char* file, int line)
+char* FailableMemoryAllocator::alloc_memory(size_t size, const char* file, size_t line)
{
currentAllocNumber_++;
LocationToFailAllocNode* current = head_;
- LocationToFailAllocNode* previous = NULL;
+ LocationToFailAllocNode* previous = NULLPTR;
while (current) {
if (current->shouldFail(currentAllocNumber_, file, line)) {
if (previous) previous->next_ = current->next_;
else head_ = current->next_;
- free_memory((char*) current, __FILE__, __LINE__);
- return NULL;
+ free_memory((char*) current, size, __FILE__, __LINE__);
+ return NULLPTR;
}
previous = current;
current = current->next_;
@@ -295,17 +371,16 @@ char* FailableMemoryAllocator::allocMemoryLeakNode(size_t size)
void FailableMemoryAllocator::checkAllFailedAllocsWereDone()
{
- if (head_) {
- UtestShell* currentTest = UtestShell::getCurrent();
- SimpleString failText;
- if (head_->file_)
- failText = StringFromFormat("Expected failing alloc at %s:%d was never done", head_->file_, head_->line_);
- else
- failText = StringFromFormat("Expected allocation number %d was never done", head_->allocNumberToFail_);
+ if (head_) {
+ UtestShell* currentTest = UtestShell::getCurrent();
+ SimpleString failText;
+ if (head_->file_)
+ failText = StringFromFormat("Expected failing alloc at %s:%d was never done", head_->file_, (int) head_->line_);
+ else
+ failText = StringFromFormat("Expected allocation number %d was never done", (int) head_->allocNumberToFail_);
- currentTest->failWith(FailFailure(currentTest, currentTest->getName().asCharString(),
- currentTest->getLineNumber(), failText), TestTerminatorWithoutExceptions());
- }
+ currentTest->failWith(FailFailure(currentTest, currentTest->getName().asCharString(), currentTest->getLineNumber(), failText));
+ }
}
void FailableMemoryAllocator::clearFailedAllocs()
@@ -313,9 +388,405 @@ void FailableMemoryAllocator::clearFailedAllocs()
LocationToFailAllocNode* current = head_;
while (current) {
head_ = current->next_;
- free_memory((char*) current, __FILE__, __LINE__);
+ free_memory((char*) current, 0, __FILE__, __LINE__);
current = head_;
}
currentAllocNumber_ = 0;
}
+struct MemoryAccountantAllocationNode
+{
+ size_t size_;
+ size_t allocations_;
+ size_t deallocations_;
+ size_t maxAllocations_;
+ size_t currentAllocations_;
+ MemoryAccountantAllocationNode* next_;
+};
+
+MemoryAccountantAllocationNode* MemoryAccountant::createNewAccountantAllocationNode(size_t size, MemoryAccountantAllocationNode* next) const
+{
+ MemoryAccountantAllocationNode* node = (MemoryAccountantAllocationNode*) (void*) allocator_->alloc_memory(sizeof(MemoryAccountantAllocationNode), __FILE__, __LINE__);
+ node->size_ = size;
+ node->allocations_ = 0;
+ node->deallocations_ = 0;
+ node->maxAllocations_ = 0;
+ node->currentAllocations_ = 0;
+ node->next_ = next;
+ return node;
+}
+
+void MemoryAccountant::destroyAccountantAllocationNode(MemoryAccountantAllocationNode* node) const
+{
+ allocator_->free_memory((char*) node, sizeof(*node), __FILE__, __LINE__);
+}
+
+MemoryAccountant::MemoryAccountant()
+ : head_(NULLPTR), allocator_(defaultMallocAllocator()), useCacheSizes_(false)
+{
+}
+
+MemoryAccountant::~MemoryAccountant()
+{
+ clear();
+}
+
+void MemoryAccountant::createCacheSizeNodes(size_t sizes[], size_t length)
+{
+ for (size_t i = 0; i < length; i++)
+ findOrCreateNodeOfSize(sizes[i]);
+
+ if (head_ == NULLPTR)
+ head_ = createNewAccountantAllocationNode(0, NULLPTR);
+ else {
+ for (MemoryAccountantAllocationNode* lastNode = head_; lastNode; lastNode = lastNode->next_) {
+ if (lastNode->next_ == NULLPTR) {
+ lastNode->next_ = createNewAccountantAllocationNode(0, NULLPTR);
+ break;
+ }
+ }
+ }
+}
+
+
+void MemoryAccountant::useCacheSizes(size_t sizes[], size_t length)
+{
+ if (head_)
+ FAIL("MemoryAccountant: Cannot set cache sizes as allocations already occured!");
+
+ createCacheSizeNodes(sizes, length);
+ useCacheSizes_ = true;
+}
+
+void MemoryAccountant::setAllocator(TestMemoryAllocator* allocator)
+{
+ allocator_ = allocator;
+}
+
+void MemoryAccountant::clear()
+{
+ MemoryAccountantAllocationNode* node = head_;
+ MemoryAccountantAllocationNode* to_be_deleted = NULLPTR;
+ while (node) {
+ to_be_deleted = node;
+ node = node->next_;
+ destroyAccountantAllocationNode(to_be_deleted);
+ }
+ head_ = NULLPTR;
+}
+
+MemoryAccountantAllocationNode* MemoryAccountant::findNodeOfSize(size_t size) const
+{
+ if (useCacheSizes_) {
+ for (MemoryAccountantAllocationNode* node = head_; node; node = node->next_) {
+ if (((size > node->size_) && (node->next_ == NULLPTR))
+ || ((size <= node->size_) &&
+ !((node->next_->size_ != 0) && (node->next_->size_ <= size))))
+ return node;
+ }
+ }
+ else
+ for (MemoryAccountantAllocationNode* node = head_; node; node = node->next_)
+ if (node->size_ == size)
+ return node;
+ return NULLPTR;
+}
+
+MemoryAccountantAllocationNode* MemoryAccountant::findOrCreateNodeOfSize(size_t size)
+{
+ if (useCacheSizes_)
+ return findNodeOfSize(size);
+
+ if (head_ && head_->size_ > size)
+ head_ = createNewAccountantAllocationNode(size, head_);
+
+ for (MemoryAccountantAllocationNode* node = head_; node; node = node->next_) {
+ if (node->size_ == size)
+ return node;
+ if (node->next_ == NULLPTR || node->next_->size_ > size)
+ node->next_ = createNewAccountantAllocationNode(size, node->next_);
+ }
+ head_ = createNewAccountantAllocationNode(size, head_);
+ return head_;
+}
+
+void MemoryAccountant::alloc(size_t size)
+{
+ MemoryAccountantAllocationNode* node = findOrCreateNodeOfSize(size);
+ node->allocations_++;
+ node->currentAllocations_++;
+ node->maxAllocations_ = (node->currentAllocations_ > node->maxAllocations_) ? node->currentAllocations_ : node->maxAllocations_;
+}
+
+void MemoryAccountant::dealloc(size_t size)
+{
+ MemoryAccountantAllocationNode* node = findOrCreateNodeOfSize(size);
+ node->deallocations_++;
+ if (node->currentAllocations_)
+ node->currentAllocations_--;
+}
+
+size_t MemoryAccountant::totalAllocationsOfSize(size_t size) const
+{
+ MemoryAccountantAllocationNode* node = findNodeOfSize(size);
+ if (node)
+ return node->allocations_;
+ return 0;
+}
+
+size_t MemoryAccountant::totalDeallocationsOfSize(size_t size) const
+{
+ MemoryAccountantAllocationNode* node = findNodeOfSize(size);
+ if (node)
+ return node->deallocations_;
+ return 0;
+}
+
+size_t MemoryAccountant::maximumAllocationAtATimeOfSize(size_t size) const
+{
+ MemoryAccountantAllocationNode* node = findNodeOfSize(size);
+ if (node)
+ return node->maxAllocations_;
+ return 0;
+}
+
+size_t MemoryAccountant::totalAllocations() const
+{
+ size_t theTotalAllocations = 0;
+
+ for (MemoryAccountantAllocationNode* node = head_; node; node = node->next_)
+ theTotalAllocations += node->allocations_;
+
+ return theTotalAllocations;
+}
+
+size_t MemoryAccountant::totalDeallocations() const
+{
+ size_t theTotalDeallocations = 0;
+
+ for (MemoryAccountantAllocationNode* node = head_; node; node = node->next_)
+ theTotalDeallocations += node->deallocations_;
+
+ return theTotalDeallocations;
+}
+
+SimpleString MemoryAccountant::reportNoAllocations() const
+{
+ return SimpleString("CppUTest Memory Accountant has not noticed any allocations or deallocations. Sorry\n");
+}
+
+SimpleString MemoryAccountant::reportTitle() const
+{
+ if (useCacheSizes_)
+ return "CppUTest Memory Accountant report (with cache sizes):\n";
+ return "CppUTest Memory Accountant report:\n";
+}
+
+SimpleString MemoryAccountant::reportHeader() const
+{
+ if (useCacheSizes_)
+ return "Cache size # allocations # deallocations max # allocations at one time\n";
+ return "Allocation size # allocations # deallocations max # allocations at one time\n";
+}
+
+#define MEMORY_ACCOUNTANT_ROW_FORMAT "%s %5d %5d %5d\n"
+
+SimpleString MemoryAccountant::reportFooter() const
+{
+ return SimpleString(" Thank you for your business\n");
+}
+
+SimpleString MemoryAccountant::stringSize(size_t size) const
+{
+ return (size == 0) ? StringFrom("other") : StringFromFormat("%5d", (int) size);
+}
+
+SimpleString MemoryAccountant::report() const
+{
+ if (head_ == NULLPTR)
+ return reportNoAllocations();
+
+ SimpleString accountantReport = reportTitle() + reportHeader();
+
+ for (MemoryAccountantAllocationNode* node = head_; node; node = node->next_)
+ accountantReport += StringFromFormat(MEMORY_ACCOUNTANT_ROW_FORMAT, stringSize(node->size_).asCharString(), (int) node->allocations_, (int) node->deallocations_, (int) node->maxAllocations_);
+
+ return accountantReport + reportFooter();
+}
+
+AccountingTestMemoryAllocator::AccountingTestMemoryAllocator(MemoryAccountant& accountant, TestMemoryAllocator* origAllocator)
+ : accountant_(accountant), originalAllocator_(origAllocator), head_(NULLPTR)
+{
+}
+
+AccountingTestMemoryAllocator::~AccountingTestMemoryAllocator()
+{
+}
+
+struct AccountingTestMemoryAllocatorMemoryNode
+{
+ char* memory_;
+ size_t size_;
+ AccountingTestMemoryAllocatorMemoryNode* next_;
+};
+
+void AccountingTestMemoryAllocator::addMemoryToMemoryTrackingToKeepTrackOfSize(char* memory, size_t size)
+{
+ AccountingTestMemoryAllocatorMemoryNode* node = (AccountingTestMemoryAllocatorMemoryNode*) (void*) originalAllocator_->alloc_memory(sizeof(AccountingTestMemoryAllocatorMemoryNode), __FILE__, __LINE__);
+ node->memory_ = memory;
+ node->size_ = size;
+ node->next_ = head_;
+ head_ = node;
+}
+
+size_t AccountingTestMemoryAllocator::removeNextNodeAndReturnSize(AccountingTestMemoryAllocatorMemoryNode* node)
+{
+ AccountingTestMemoryAllocatorMemoryNode* foundNode = node->next_;
+ node->next_ = node->next_->next_;
+
+ size_t size = foundNode->size_;
+ originalAllocator_->free_memory((char*) foundNode, size, __FILE__, __LINE__);
+ return size;
+}
+
+size_t AccountingTestMemoryAllocator::removeHeadAndReturnSize()
+{
+ AccountingTestMemoryAllocatorMemoryNode* foundNode = head_;
+ head_ = head_->next_;
+
+ size_t size = foundNode->size_;
+ originalAllocator_->free_memory((char*) foundNode, size, __FILE__, __LINE__);
+ return size;
+}
+
+size_t AccountingTestMemoryAllocator::removeMemoryFromTrackingAndReturnAllocatedSize(char* memory)
+{
+ if (head_ && head_->memory_ == memory)
+ return removeHeadAndReturnSize();
+
+ for (AccountingTestMemoryAllocatorMemoryNode* node = head_; node; node = node->next_) {
+ if (node->next_ && node->next_->memory_ == memory)
+ return removeNextNodeAndReturnSize(node);
+ }
+
+ return 0;
+}
+
+char* AccountingTestMemoryAllocator::alloc_memory(size_t size, const char* file, size_t line)
+{
+ accountant_.alloc(size);
+ char* memory = originalAllocator_->alloc_memory(size, file, line);
+ addMemoryToMemoryTrackingToKeepTrackOfSize(memory, size);
+ return memory;
+}
+
+void AccountingTestMemoryAllocator::free_memory(char* memory, size_t, const char* file, size_t line)
+{
+ size_t size = removeMemoryFromTrackingAndReturnAllocatedSize(memory);
+ accountant_.dealloc(size);
+ originalAllocator_->free_memory(memory, size, file, line);
+}
+
+TestMemoryAllocator* AccountingTestMemoryAllocator::actualAllocator()
+{
+ return originalAllocator_->actualAllocator();
+}
+
+TestMemoryAllocator* AccountingTestMemoryAllocator::originalAllocator()
+{
+ return originalAllocator_;
+}
+
+const char* AccountingTestMemoryAllocator::alloc_name() const
+{
+ return originalAllocator_->alloc_name();
+}
+
+const char* AccountingTestMemoryAllocator::free_name() const
+{
+ return originalAllocator_->free_name();
+}
+
+GlobalMemoryAccountant::GlobalMemoryAccountant()
+ : mallocAllocator_(NULLPTR), newAllocator_(NULLPTR), newArrayAllocator_(NULLPTR)
+{
+}
+
+GlobalMemoryAccountant::~GlobalMemoryAccountant()
+{
+ restoreMemoryAllocators();
+ delete mallocAllocator_;
+ delete newAllocator_;
+ delete newArrayAllocator_;
+}
+
+void GlobalMemoryAccountant::useCacheSizes(size_t sizes[], size_t length)
+{
+ accountant_.useCacheSizes(sizes, length);
+}
+
+void GlobalMemoryAccountant::start()
+{
+ if (mallocAllocator_ != NULLPTR)
+ FAIL("Global allocator start called twice!");
+
+ mallocAllocator_ = new AccountingTestMemoryAllocator(accountant_, getCurrentMallocAllocator());
+ newAllocator_ = new AccountingTestMemoryAllocator(accountant_, getCurrentNewAllocator());
+ newArrayAllocator_ = new AccountingTestMemoryAllocator(accountant_, getCurrentNewArrayAllocator());
+
+ accountant_.setAllocator(getCurrentMallocAllocator());
+
+ setCurrentMallocAllocator(mallocAllocator_);
+ setCurrentNewAllocator(newAllocator_);
+ setCurrentNewArrayAllocator(newArrayAllocator_);
+}
+
+void GlobalMemoryAccountant::restoreMemoryAllocators()
+{
+ if (getCurrentMallocAllocator() == mallocAllocator_)
+ setCurrentMallocAllocator(mallocAllocator_->originalAllocator());
+
+ if (getCurrentNewAllocator() == newAllocator_)
+ setCurrentNewAllocator(newAllocator_->originalAllocator());
+
+ if (getCurrentNewArrayAllocator() == newArrayAllocator_)
+ setCurrentNewArrayAllocator(newArrayAllocator_->originalAllocator());
+}
+
+void GlobalMemoryAccountant::stop()
+{
+ if (mallocAllocator_ == NULLPTR)
+ FAIL("GlobalMemoryAccount: Stop called without starting");
+
+ if (getCurrentMallocAllocator() != mallocAllocator_)
+ FAIL("GlobalMemoryAccountant: Malloc memory allocator has been changed while accounting for memory");
+
+ if (getCurrentNewAllocator() != newAllocator_)
+ FAIL("GlobalMemoryAccountant: New memory allocator has been changed while accounting for memory");
+
+ if (getCurrentNewArrayAllocator() != newArrayAllocator_)
+ FAIL("GlobalMemoryAccountant: New Array memory allocator has been changed while accounting for memory");
+
+ restoreMemoryAllocators();
+}
+
+SimpleString GlobalMemoryAccountant::report()
+{
+ return accountant_.report();
+}
+
+TestMemoryAllocator* GlobalMemoryAccountant::getMallocAllocator()
+{
+ return mallocAllocator_;
+}
+
+TestMemoryAllocator* GlobalMemoryAccountant::getNewAllocator()
+{
+ return newAllocator_;
+}
+
+TestMemoryAllocator* GlobalMemoryAccountant::getNewArrayAllocator()
+{
+ return newArrayAllocator_;
+}
+
diff --git a/src/CppUTest/TestOutput.cpp b/src/CppUTest/TestOutput.cpp
index 113884ea7..cb4ced54e 100644
--- a/src/CppUTest/TestOutput.cpp
+++ b/src/CppUTest/TestOutput.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -24,7 +24,6 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
#include "CppUTest/TestHarness.h"
#include "CppUTest/TestOutput.h"
#include "CppUTest/PlatformSpecificFunctions.h"
@@ -45,7 +44,7 @@ TestOutput::WorkingEnvironment TestOutput::getWorkingEnvironment()
TestOutput::TestOutput() :
- dotCount_(0), verbose_(false), color_(false), progressIndication_(".")
+ dotCount_(0), verbose_(level_quiet), color_(false), progressIndication_(".")
{
}
@@ -53,9 +52,9 @@ TestOutput::~TestOutput()
{
}
-void TestOutput::verbose()
+void TestOutput::verbose(VerbosityLevel level)
{
- verbose_ = true;
+ verbose_ = level;
}
void TestOutput::color()
@@ -73,6 +72,11 @@ void TestOutput::print(long n)
print(StringFrom(n).asCharString());
}
+void TestOutput::print(size_t n)
+{
+ print(StringFrom(n).asCharString());
+}
+
void TestOutput::printDouble(double d)
{
print(StringFrom(d).asCharString());
@@ -92,7 +96,7 @@ TestOutput& operator<<(TestOutput& p, long int i)
void TestOutput::printCurrentTestStarted(const UtestShell& test)
{
- if (verbose_) print(test.getFormattedName().asCharString());
+ if (verbose_ > level_quiet) print(test.getFormattedName().asCharString());
if (test.willRun()) {
setProgressIndicator(".");
@@ -104,7 +108,7 @@ void TestOutput::printCurrentTestStarted(const UtestShell& test)
void TestOutput::printCurrentTestEnded(const TestResult& res)
{
- if (verbose_) {
+ if (verbose_ > level_quiet) {
print(" - ");
print(res.getCurrentTestTotalExecutionTime());
print(" ms\n");
@@ -140,13 +144,20 @@ void TestOutput::printCurrentGroupEnded(const TestResult& /*res*/)
void TestOutput::printTestsEnded(const TestResult& result)
{
print("\n");
- if (result.getFailureCount() > 0) {
+ const bool isFailure = result.isFailure();
+ const size_t failureCount = result.getFailureCount();
+ if (isFailure) {
if (color_) {
print("\033[31;1m");
}
print("Errors (");
- print(result.getFailureCount());
- print(" failures, ");
+ if (failureCount > 0) {
+ print(failureCount);
+ print(" failures, ");
+ }
+ else {
+ print("ran nothing, ");
+ }
}
else {
if (color_) {
@@ -169,10 +180,16 @@ void TestOutput::printTestsEnded(const TestResult& result)
if (color_) {
print("\033[m");
}
+ if (isFailure && failureCount == 0) {
+ print("\nNote: test run failed because no tests were run or ignored. Assuming something went wrong. "
+ "This often happens because of linking errors or typos in test filter.");
+ }
print("\n\n");
+
+ dotCount_ = 0;
}
-void TestOutput::printTestRun(int number, int total)
+void TestOutput::printTestRun(size_t number, size_t total)
{
if (total > 1) {
print("Test run ");
@@ -220,7 +237,7 @@ void TestOutput::printFailureMessage(SimpleString reason)
print("\n\n");
}
-void TestOutput::printErrorInFileOnLineFormattedForWorkingEnvironment(SimpleString file, int lineNumber)
+void TestOutput::printErrorInFileOnLineFormattedForWorkingEnvironment(SimpleString file, size_t lineNumber)
{
if (TestOutput::getWorkingEnvironment() == TestOutput::visualStudio)
printVisualStudioErrorInFileOnLine(file, lineNumber);
@@ -228,7 +245,7 @@ void TestOutput::printErrorInFileOnLineFormattedForWorkingEnvironment(SimpleStri
printEclipseErrorInFileOnLine(file, lineNumber);
}
-void TestOutput::printEclipseErrorInFileOnLine(SimpleString file, int lineNumber)
+void TestOutput::printEclipseErrorInFileOnLine(SimpleString file, size_t lineNumber)
{
print("\n");
print(file.asCharString());
@@ -238,7 +255,7 @@ void TestOutput::printEclipseErrorInFileOnLine(SimpleString file, int lineNumber
print(" error:");
}
-void TestOutput::printVisualStudioErrorInFileOnLine(SimpleString file, int lineNumber)
+void TestOutput::printVisualStudioErrorInFileOnLine(SimpleString file, size_t lineNumber)
{
print("\n");
print(file.asCharString());
@@ -248,12 +265,16 @@ void TestOutput::printVisualStudioErrorInFileOnLine(SimpleString file, int lineN
print(" error:");
}
+void TestOutput::printVeryVerbose(const char* str)
+{
+ if(verbose_ == level_veryVerbose)
+ printBuffer(str);
+}
+
+
void ConsoleTestOutput::printBuffer(const char* s)
{
- while (*s) {
- PlatformSpecificPutchar(*s);
- s++;
- }
+ PlatformSpecificFPuts(s, PlatformSpecificStdOut);
flush();
}
@@ -267,7 +288,7 @@ StringBufferTestOutput::~StringBufferTestOutput()
}
CompositeTestOutput::CompositeTestOutput()
- : outputOne_(NULL), outputTwo_(NULL)
+ : outputOne_(NULLPTR), outputTwo_(NULLPTR)
{
}
@@ -325,10 +346,10 @@ void CompositeTestOutput::printCurrentGroupEnded(const TestResult& res)
if (outputTwo_) outputTwo_->printCurrentGroupEnded(res);
}
-void CompositeTestOutput::verbose()
+void CompositeTestOutput::verbose(VerbosityLevel level)
{
- if (outputOne_) outputOne_->verbose();
- if (outputTwo_) outputTwo_->verbose();
+ if (outputOne_) outputOne_->verbose(level);
+ if (outputTwo_) outputTwo_->verbose(level);
}
void CompositeTestOutput::color()
@@ -355,6 +376,12 @@ void CompositeTestOutput::print(long number)
if (outputTwo_) outputTwo_->print(number);
}
+void CompositeTestOutput::print(size_t number)
+{
+ if (outputOne_) outputOne_->print(number);
+ if (outputTwo_) outputTwo_->print(number);
+}
+
void CompositeTestOutput::printDouble(double number)
{
if (outputOne_) outputOne_->printDouble(number);
@@ -373,6 +400,12 @@ void CompositeTestOutput::setProgressIndicator(const char* indicator)
if (outputTwo_) outputTwo_->setProgressIndicator(indicator);
}
+void CompositeTestOutput::printVeryVerbose(const char* str)
+{
+ if (outputOne_) outputOne_->printVeryVerbose(str);
+ if (outputTwo_) outputTwo_->printVeryVerbose(str);
+}
+
void CompositeTestOutput::flush()
{
if (outputOne_) outputOne_->flush();
diff --git a/src/CppUTest/TestPlugin.cpp b/src/CppUTest/TestPlugin.cpp
index 9f83fee28..29aa38bcf 100644
--- a/src/CppUTest/TestPlugin.cpp
+++ b/src/CppUTest/TestPlugin.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -62,10 +62,10 @@ void TestPlugin::runAllPostTestAction(UtestShell& test, TestResult& result)
bool TestPlugin::parseAllArguments(int ac, char** av, int index)
{
- return parseAllArguments(ac, const_cast (av), index);
+ return parseAllArguments(ac, const_cast (av), index);
}
-bool TestPlugin::parseAllArguments(int ac, const char** av, int index)
+bool TestPlugin::parseAllArguments(int ac, const char *const *av, int index)
{
if (parseArguments(ac, av, index)) return true;
if (next_) return next_->parseAllArguments(ac, av, index);
@@ -90,7 +90,7 @@ TestPlugin* TestPlugin::getNext()
}
TestPlugin* TestPlugin::removePluginByName(const SimpleString& name)
{
- TestPlugin* removed = 0;
+ TestPlugin* removed = NULLPTR;
if (next_ && next_->getName() == name) {
removed = next_;
next_ = next_->next_;
@@ -150,7 +150,7 @@ void SetPointerPlugin::postTestAction(UtestShell& /*test*/, TestResult& /*result
//////// NullPlugin
NullTestPlugin::NullTestPlugin() :
- TestPlugin(0)
+ TestPlugin(NULLPTR)
{
}
diff --git a/src/CppUTest/TestRegistry.cpp b/src/CppUTest/TestRegistry.cpp
old mode 100755
new mode 100644
index 26c049859..542ab51a8
--- a/src/CppUTest/TestRegistry.cpp
+++ b/src/CppUTest/TestRegistry.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -27,10 +27,10 @@
#include "CppUTest/TestHarness.h"
#include "CppUTest/TestRegistry.h"
+#include "CppUTest/PlatformSpecificFunctions.h"
TestRegistry::TestRegistry() :
- tests_(NULL), nameFilters_(NULL), groupFilters_(NULL), firstPlugin_(NullTestPlugin::instance()), runInSeperateProcess_(false), currentRepetition_(0), runIgnored_(false)
-
+ tests_(NULLPTR), nameFilters_(NULLPTR), groupFilters_(NULLPTR), firstPlugin_(NullTestPlugin::instance()), runInSeperateProcess_(false), currentRepetition_(0), runIgnored_(false)
{
}
@@ -48,7 +48,7 @@ void TestRegistry::runAllTests(TestResult& result)
bool groupStart = true;
result.testsStarted();
- for (UtestShell *test = tests_; test != NULL; test = test->getNext()) {
+ for (UtestShell *test = tests_; test != NULLPTR; test = test->getNext()) {
if (runInSeperateProcess_) test->setRunInSeperateProcess();
if (runIgnored_) test->setRunIgnored();
@@ -77,7 +77,7 @@ void TestRegistry::listTestGroupNames(TestResult& result)
{
SimpleString groupList;
- for (UtestShell *test = tests_; test != NULL; test = test->getNext()) {
+ for (UtestShell *test = tests_; test != NULLPTR; test = test->getNext()) {
SimpleString gname;
gname += "#";
gname += test->getGroup();
@@ -100,7 +100,7 @@ void TestRegistry::listTestGroupAndCaseNames(TestResult& result)
{
SimpleString groupAndNameList;
- for (UtestShell *test = tests_; test != NULL; test = test->getNext()) {
+ for (UtestShell *test = tests_; test != NULLPTR; test = test->getNext()) {
if (testShouldRun(test, result)) {
SimpleString groupAndName;
groupAndName += "#";
@@ -123,22 +123,42 @@ void TestRegistry::listTestGroupAndCaseNames(TestResult& result)
result.print(groupAndNameList.asCharString());
}
+void TestRegistry::listTestLocations(TestResult& result)
+{
+ SimpleString testLocations;
+
+ for (UtestShell *test = tests_; test != NULLPTR; test = test->getNext()) {
+ SimpleString testLocation;
+ testLocation += test->getGroup();
+ testLocation += ".";
+ testLocation += test->getName();
+ testLocation += ".";
+ testLocation += test->getFile();
+ testLocation += ".";
+ testLocation += StringFromFormat("%d\n",(int) test->getLineNumber());
+
+ testLocations += testLocation;
+ }
+
+ result.print(testLocations.asCharString());
+}
+
bool TestRegistry::endOfGroup(UtestShell* test)
{
return (!test || !test->getNext() || test->getGroup() != test->getNext()->getGroup());
}
-int TestRegistry::countTests()
+size_t TestRegistry::countTests()
{
return tests_ ? tests_->countTests() : 0;
}
-TestRegistry* TestRegistry::currentRegistry_ = 0;
+TestRegistry* TestRegistry::currentRegistry_ = NULLPTR;
TestRegistry* TestRegistry::getCurrentRegistry()
{
static TestRegistry registry;
- return (currentRegistry_ == 0) ? ®istry : currentRegistry_;
+ return (currentRegistry_ == NULLPTR) ? ®istry : currentRegistry_;
}
void TestRegistry::setCurrentRegistry(TestRegistry* registry)
@@ -148,7 +168,7 @@ void TestRegistry::setCurrentRegistry(TestRegistry* registry)
void TestRegistry::unDoLastAddTest()
{
- tests_ = tests_ ? tests_->getNext() : NULL;
+ tests_ = tests_ ? tests_->getNext() : NULLPTR;
}
@@ -227,6 +247,20 @@ UtestShell* TestRegistry::getFirstTest()
return tests_;
}
+void TestRegistry::shuffleTests(size_t seed)
+{
+ UtestShellPointerArray array(getFirstTest());
+ array.shuffle(seed);
+ tests_ = array.getFirstTest();
+}
+
+void TestRegistry::reverseTests()
+{
+ UtestShellPointerArray array(getFirstTest());
+ array.reverse();
+ tests_ = array.getFirstTest();
+}
+
UtestShell* TestRegistry::getTestWithNext(UtestShell* test)
{
UtestShell* current = tests_;
@@ -243,7 +277,7 @@ UtestShell* TestRegistry::findTestWithName(const SimpleString& name)
return current;
current = current->getNext();
}
- return NULL;
+ return NULLPTR;
}
UtestShell* TestRegistry::findTestWithGroup(const SimpleString& group)
@@ -254,6 +288,6 @@ UtestShell* TestRegistry::findTestWithGroup(const SimpleString& group)
return current;
current = current->getNext();
}
- return NULL;
+ return NULLPTR;
}
diff --git a/src/CppUTest/TestResult.cpp b/src/CppUTest/TestResult.cpp
index 90c215d69..37ff57f84 100644
--- a/src/CppUTest/TestResult.cpp
+++ b/src/CppUTest/TestResult.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -44,19 +44,19 @@ TestResult::~TestResult()
void TestResult::currentGroupStarted(UtestShell* test)
{
output_.printCurrentGroupStarted(*test);
- currentGroupTimeStarted_ = GetPlatformSpecificTimeInMillis();
+ currentGroupTimeStarted_ = (size_t) GetPlatformSpecificTimeInMillis();
}
void TestResult::currentGroupEnded(UtestShell* /*test*/)
{
- currentGroupTotalExecutionTime_ = GetPlatformSpecificTimeInMillis() - currentGroupTimeStarted_;
+ currentGroupTotalExecutionTime_ = (size_t) GetPlatformSpecificTimeInMillis() - currentGroupTimeStarted_;
output_.printCurrentGroupEnded(*this);
}
void TestResult::currentTestStarted(UtestShell* test)
{
output_.printCurrentTestStarted(*test);
- currentTestTimeStarted_ = GetPlatformSpecificTimeInMillis();
+ currentTestTimeStarted_ = (size_t) GetPlatformSpecificTimeInMillis();
}
void TestResult::print(const char* text)
@@ -64,9 +64,14 @@ void TestResult::print(const char* text)
output_.print(text);
}
+void TestResult::printVeryVerbose(const char* text)
+{
+ output_.printVeryVerbose(text);
+}
+
void TestResult::currentTestEnded(UtestShell* /*test*/)
{
- currentTestTotalExecutionTime_ = GetPlatformSpecificTimeInMillis() - currentTestTimeStarted_;
+ currentTestTotalExecutionTime_ = (size_t) GetPlatformSpecificTimeInMillis() - currentTestTimeStarted_;
output_.printCurrentTestEnded(*this);
}
@@ -104,33 +109,33 @@ void TestResult::countIgnored()
void TestResult::testsStarted()
{
- timeStarted_ = GetPlatformSpecificTimeInMillis();
+ timeStarted_ = (size_t) GetPlatformSpecificTimeInMillis();
output_.printTestsStarted();
}
void TestResult::testsEnded()
{
- long timeEnded = GetPlatformSpecificTimeInMillis();
+ size_t timeEnded = (size_t) GetPlatformSpecificTimeInMillis();
totalExecutionTime_ = timeEnded - timeStarted_;
output_.printTestsEnded(*this);
}
-long TestResult::getTotalExecutionTime() const
+size_t TestResult::getTotalExecutionTime() const
{
return totalExecutionTime_;
}
-void TestResult::setTotalExecutionTime(long exTime)
+void TestResult::setTotalExecutionTime(size_t exTime)
{
totalExecutionTime_ = exTime;
}
-long TestResult::getCurrentTestTotalExecutionTime() const
+size_t TestResult::getCurrentTestTotalExecutionTime() const
{
return currentTestTotalExecutionTime_;
}
-long TestResult::getCurrentGroupTotalExecutionTime() const
+size_t TestResult::getCurrentGroupTotalExecutionTime() const
{
return currentGroupTotalExecutionTime_;
}
diff --git a/src/CppUTest/TestTestingFixture.cpp b/src/CppUTest/TestTestingFixture.cpp
index 9e7d9b938..a5e73d33e 100644
--- a/src/CppUTest/TestTestingFixture.cpp
+++ b/src/CppUTest/TestTestingFixture.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -30,19 +30,165 @@
bool TestTestingFixture::lineOfCodeExecutedAfterCheck = false;
+TestTestingFixture::TestTestingFixture()
+{
+ output_ = new StringBufferTestOutput();
+ result_ = new TestResult(*output_);
+ genTest_ = new ExecFunctionTestShell();
+ registry_ = new TestRegistry();
+ ownsExecFunction_ = false;
+
+ registry_->setCurrentRegistry(registry_);
+ registry_->addTest(genTest_);
+
+ lineOfCodeExecutedAfterCheck = false;
+}
+
+void TestTestingFixture::flushOutputAndResetResult()
+{
+ output_->flush();
+ delete result_;
+ result_ = new TestResult(*output_);
+}
+
+TestTestingFixture::~TestTestingFixture()
+{
+ registry_->setCurrentRegistry(NULLPTR);
+ clearExecFunction();
+ delete registry_;
+ delete result_;
+ delete output_;
+ delete genTest_;
+}
+
+void TestTestingFixture::clearExecFunction()
+{
+ if (genTest_->testFunction_ && ownsExecFunction_)
+ delete genTest_->testFunction_;
+}
+
+void TestTestingFixture::addTest(UtestShell * test)
+{
+ registry_->addTest(test);
+}
+
+void TestTestingFixture::setTestFunction(void(*testFunction)())
+{
+ clearExecFunction();
+
+ genTest_->testFunction_ = new ExecFunctionWithoutParameters(testFunction);
+ ownsExecFunction_ = true;
+}
+
+void TestTestingFixture::setTestFunction(ExecFunction* testFunction)
+{
+ clearExecFunction();
+
+ genTest_->testFunction_ = testFunction;
+
+ ownsExecFunction_ = false;
+}
+
+void TestTestingFixture::setSetup(void(*setupFunction)())
+{
+ genTest_->setup_ = setupFunction;
+}
+
+void TestTestingFixture::setTeardown(void(*teardownFunction)())
+{
+ genTest_->teardown_ = teardownFunction;
+}
+
+void TestTestingFixture::installPlugin(TestPlugin* plugin)
+{
+ registry_->installPlugin(plugin);
+}
+
+void TestTestingFixture::setRunTestsInSeperateProcess()
+{
+ registry_->setRunTestsInSeperateProcess();
+}
+
+void TestTestingFixture::setOutputVerbose()
+{
+ output_->verbose(TestOutput::level_verbose);
+}
+
+void TestTestingFixture::runTestWithMethod(void(*method)())
+{
+ setTestFunction(method);
+ runAllTests();
+}
+
+void TestTestingFixture::runAllTests()
+{
+ registry_->runAllTests(*result_);
+}
+
+size_t TestTestingFixture::getFailureCount()
+{
+ return result_->getFailureCount();
+}
+
+size_t TestTestingFixture::getCheckCount()
+{
+ return result_->getCheckCount();
+}
+
+size_t TestTestingFixture::getTestCount()
+{
+ return result_->getTestCount();
+}
+
+size_t TestTestingFixture::getIgnoreCount()
+{
+ return result_->getIgnoredCount();
+}
+
+TestRegistry* TestTestingFixture::getRegistry()
+{
+ return registry_;
+}
+
+bool TestTestingFixture::hasTestFailed()
+{
+ return genTest_->hasFailed();
+}
+
+void TestTestingFixture::assertPrintContains(const SimpleString& contains)
+{
+ STRCMP_CONTAINS(contains.asCharString(), getOutput().asCharString());
+}
+
+void TestTestingFixture::assertPrintContainsNot(const SimpleString& contains)
+{
+ CHECK(! getOutput().contains(contains));
+}
+
+
+const SimpleString& TestTestingFixture::getOutput()
+{
+ return output_->getOutput();
+}
+
+size_t TestTestingFixture::getRunCount()
+{
+ return result_->getRunCount();
+}
+
void TestTestingFixture::lineExecutedAfterCheck()
{
- lineOfCodeExecutedAfterCheck = true;
+ lineOfCodeExecutedAfterCheck = true;
}
-void TestTestingFixture::checkTestFailsWithProperTestLocation(const char* text, const char* file, int line)
+void TestTestingFixture::checkTestFailsWithProperTestLocation(const char* text, const char* file, size_t line)
{
- if (getFailureCount() != 1)
- FAIL_LOCATION(StringFromFormat("Expected one test failure, but got %d amount of test failures", getFailureCount()).asCharString(), file, line);
+ if (getFailureCount() != 1)
+ FAIL_LOCATION(StringFromFormat("Expected one test failure, but got %d amount of test failures", (int) getFailureCount()).asCharString(), file, line);
- STRCMP_CONTAINS_LOCATION(text, output_->getOutput().asCharString(), "", file, line);
+ STRCMP_CONTAINS_LOCATION(text, output_->getOutput().asCharString(), "", file, line);
- if (lineOfCodeExecutedAfterCheck)
- FAIL_LOCATION("The test should jump/throw on failure and not execute the next line. However, the next line was executed.", file, line)
+ if (lineOfCodeExecutedAfterCheck)
+ FAIL_LOCATION("The test should jump/throw on failure and not execute the next line. However, the next line was executed.", file, line);
}
diff --git a/src/CppUTest/Utest.cpp b/src/CppUTest/Utest.cpp
old mode 100755
new mode 100644
index 14a025182..d74a87c79
--- a/src/CppUTest/Utest.cpp
+++ b/src/CppUTest/Utest.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -30,6 +30,10 @@
#include "CppUTest/PlatformSpecificFunctions.h"
#include "CppUTest/TestOutput.h"
+#if defined(__GNUC__) && __GNUC__ >= 11
+# define NEEDS_DISABLE_NULL_WARNING
+#endif /* GCC >= 11 */
+
bool doubles_equal(double d1, double d2, double threshold)
{
if (PlatformSpecificIsNan(d1) || PlatformSpecificIsNan(d2) || PlatformSpecificIsNan(threshold))
@@ -55,7 +59,7 @@ class OutsideTestRunnerUTest: public UtestShell
{
return defaultTestResult;
}
- virtual ~OutsideTestRunnerUTest()
+ virtual ~OutsideTestRunnerUTest() CPPUTEST_DESTRUCTOR_OVERRIDE
{
}
private:
@@ -131,17 +135,29 @@ extern "C" {
/******************************** */
+static const NormalTestTerminator normalTestTerminator = NormalTestTerminator();
+static const CrashingTestTerminator crashingTestTerminator = CrashingTestTerminator();
+static const TestTerminatorWithoutExceptions normalTestTerminatorWithoutExceptions = TestTerminatorWithoutExceptions();
+static const CrashingTestTerminatorWithoutExceptions crashingTestTerminatorWithoutExceptions = CrashingTestTerminatorWithoutExceptions();
+
+const TestTerminator *UtestShell::currentTestTerminator_ = &normalTestTerminator;
+const TestTerminator *UtestShell::currentTestTerminatorWithoutExceptions_ = &normalTestTerminatorWithoutExceptions;
+
+bool UtestShell::rethrowExceptions_ = false;
+
+/******************************** */
+
UtestShell::UtestShell() :
- group_("UndefinedTestGroup"), name_("UndefinedTest"), file_("UndefinedFile"), lineNumber_(0), next_(NULL), isRunAsSeperateProcess_(false), hasFailed_(false)
+ group_("UndefinedTestGroup"), name_("UndefinedTest"), file_("UndefinedFile"), lineNumber_(0), next_(NULLPTR), isRunAsSeperateProcess_(false), hasFailed_(false)
{
}
-UtestShell::UtestShell(const char* groupName, const char* testName, const char* fileName, int lineNumber) :
- group_(groupName), name_(testName), file_(fileName), lineNumber_(lineNumber), next_(NULL), isRunAsSeperateProcess_(false), hasFailed_(false)
+UtestShell::UtestShell(const char* groupName, const char* testName, const char* fileName, size_t lineNumber) :
+ group_(groupName), name_(testName), file_(fileName), lineNumber_(lineNumber), next_(NULLPTR), isRunAsSeperateProcess_(false), hasFailed_(false)
{
}
-UtestShell::UtestShell(const char* groupName, const char* testName, const char* fileName, int lineNumber, UtestShell* nextTest) :
+UtestShell::UtestShell(const char* groupName, const char* testName, const char* fileName, size_t lineNumber, UtestShell* nextTest) :
group_(groupName), name_(testName), file_(fileName), lineNumber_(lineNumber), next_(nextTest), isRunAsSeperateProcess_(false), hasFailed_(false)
{
}
@@ -150,14 +166,7 @@ UtestShell::~UtestShell()
{
}
-// LCOV_EXCL_START - actually covered but not in .gcno due to race condition
-static void defaultCrashMethod()
-{
- UtestShell* ptr = (UtestShell*) 0x0; ptr->countTests();
-}
-// LCOV_EXCL_STOP
-
-static void (*pleaseCrashMeRightNow) () = defaultCrashMethod;
+static void (*pleaseCrashMeRightNow) () = PlatformSpecificAbort;
void UtestShell::setCrashMethod(void (*crashme)())
{
@@ -166,7 +175,7 @@ void UtestShell::setCrashMethod(void (*crashme)())
void UtestShell::resetCrashMethod()
{
- pleaseCrashMeRightNow = defaultCrashMethod;
+ pleaseCrashMeRightNow = PlatformSpecificAbort;
}
void UtestShell::crash()
@@ -177,6 +186,7 @@ void UtestShell::crash()
void UtestShell::runOneTest(TestPlugin* plugin, TestResult& result)
{
hasFailed_ = false;
+ result.countRun();
HelperTestRunInfo runInfo(this, plugin, &result);
if (isRunInSeperateProcess())
PlatformSpecificSetJmp(helperDoRunOneTestSeperateProcess, &runInfo);
@@ -196,24 +206,49 @@ void UtestShell::destroyTest(Utest* test)
void UtestShell::runOneTestInCurrentProcess(TestPlugin* plugin, TestResult& result)
{
+ result.printVeryVerbose("\n-- before runAllPreTestAction: ");
plugin->runAllPreTestAction(*this, result);
+ result.printVeryVerbose("\n-- after runAllPreTestAction: ");
//save test context, so that test class can be tested
UtestShell* savedTest = UtestShell::getCurrent();
TestResult* savedResult = UtestShell::getTestResult();
- result.countRun();
UtestShell::setTestResult(&result);
UtestShell::setCurrentTest(this);
- Utest* testToRun = createTest();
- testToRun->run();
- destroyTest(testToRun);
+ Utest* testToRun = NULLPTR;
- UtestShell::setCurrentTest(savedTest);
- UtestShell::setTestResult(savedResult);
+#if CPPUTEST_HAVE_EXCEPTIONS
+ try
+ {
+#endif
+ result.printVeryVerbose("\n---- before createTest: ");
+ testToRun = createTest();
+ result.printVeryVerbose("\n---- after createTest: ");
+ result.printVeryVerbose("\n------ before runTest: ");
+ testToRun->run();
+ result.printVeryVerbose("\n------ after runTest: ");
+
+ UtestShell::setCurrentTest(savedTest);
+ UtestShell::setTestResult(savedResult);
+#if CPPUTEST_HAVE_EXCEPTIONS
+ }
+ catch(...)
+ {
+ destroyTest(testToRun);
+ throw;
+ }
+#endif
+
+ result.printVeryVerbose("\n---- before destroyTest: ");
+ destroyTest(testToRun);
+ result.printVeryVerbose("\n---- after destroyTest: ");
+
+ result.printVeryVerbose("\n-- before runAllPostTestAction: ");
plugin->runAllPostTestAction(*this, result);
+ result.printVeryVerbose("\n-- after runAllPostTestAction: ");
}
UtestShell *UtestShell::getNext() const
@@ -227,7 +262,7 @@ UtestShell* UtestShell::addTest(UtestShell *test)
return this;
}
-int UtestShell::countTests()
+size_t UtestShell::countTests()
{
return next_ ? next_->countTests() + 1 : 1;
}
@@ -295,7 +330,7 @@ void UtestShell::setFileName(const char* fileName)
file_ = fileName;
}
-void UtestShell::setLineNumber(int lineNumber)
+void UtestShell::setLineNumber(size_t lineNumber)
{
lineNumber_ = lineNumber;
}
@@ -315,16 +350,16 @@ const SimpleString UtestShell::getFile() const
return SimpleString(file_);
}
-int UtestShell::getLineNumber() const
+size_t UtestShell::getLineNumber() const
{
return lineNumber_;
}
bool UtestShell::match(const char* target, const TestFilter* filters) const
{
- if(filters == NULL) return true;
+ if(filters == NULLPTR) return true;
- for(; filters != NULL; filters = filters->getNext())
+ for(; filters != NULLPTR; filters = filters->getNext())
if(filters->match(target)) return true;
return false;
@@ -337,102 +372,107 @@ bool UtestShell::shouldRun(const TestFilter* groupFilters, const TestFilter* nam
void UtestShell::failWith(const TestFailure& failure)
{
- failWith(failure, NormalTestTerminator());
+ failWith(failure, getCurrentTestTerminator());
} // LCOV_EXCL_LINE
void UtestShell::failWith(const TestFailure& failure, const TestTerminator& terminator)
{
- hasFailed_ = true;
- getTestResult()->addFailure(failure);
+ addFailure(failure);
terminator.exitCurrentTest();
} // LCOV_EXCL_LINE
+void UtestShell::addFailure(const TestFailure& failure)
+{
+ hasFailed_ = true;
+ getTestResult()->addFailure(failure);
+}
+
void UtestShell::exitTest(const TestTerminator& terminator)
{
terminator.exitCurrentTest();
} // LCOV_EXCL_LINE
-void UtestShell::assertTrue(bool condition, const char *checkString, const char *conditionString, const char* text, const char *fileName, int lineNumber, const TestTerminator& testTerminator)
+void UtestShell::assertTrue(bool condition, const char *checkString, const char *conditionString, const char* text, const char *fileName, size_t lineNumber, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
if (!condition)
failWith(CheckFailure(this, fileName, lineNumber, checkString, conditionString, text), testTerminator);
}
-void UtestShell::fail(const char *text, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+void UtestShell::fail(const char *text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
failWith(FailFailure(this, fileName, lineNumber, text), testTerminator);
} // LCOV_EXCL_LINE
-void UtestShell::assertCstrEqual(const char* expected, const char* actual, const char* text, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+void UtestShell::assertCstrEqual(const char* expected, const char* actual, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
- if (actual == 0 && expected == 0) return;
- if (actual == 0 || expected == 0)
+ if (actual == NULLPTR && expected == NULLPTR) return;
+ if (actual == NULLPTR || expected == NULLPTR)
failWith(StringEqualFailure(this, fileName, lineNumber, expected, actual, text), testTerminator);
if (SimpleString::StrCmp(expected, actual) != 0)
failWith(StringEqualFailure(this, fileName, lineNumber, expected, actual, text), testTerminator);
}
-void UtestShell::assertCstrNEqual(const char* expected, const char* actual, size_t length, const char* text, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+void UtestShell::assertCstrNEqual(const char* expected, const char* actual, size_t length, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
- if (actual == 0 && expected == 0) return;
- if (actual == 0 || expected == 0)
+ if (actual == NULLPTR && expected == NULLPTR) return;
+ if (actual == NULLPTR || expected == NULLPTR)
failWith(StringEqualFailure(this, fileName, lineNumber, expected, actual, text), testTerminator);
if (SimpleString::StrNCmp(expected, actual, length) != 0)
failWith(StringEqualFailure(this, fileName, lineNumber, expected, actual, text), testTerminator);
}
-void UtestShell::assertCstrNoCaseEqual(const char* expected, const char* actual, const char* text, const char* fileName, int lineNumber)
+void UtestShell::assertCstrNoCaseEqual(const char* expected, const char* actual, const char* text, const char* fileName, size_t lineNumber)
{
getTestResult()->countCheck();
- if (actual == 0 && expected == 0) return;
- if (actual == 0 || expected == 0)
+ if (actual == NULLPTR && expected == NULLPTR) return;
+ if (actual == NULLPTR || expected == NULLPTR)
failWith(StringEqualNoCaseFailure(this, fileName, lineNumber, expected, actual, text));
if (!SimpleString(expected).equalsNoCase(actual))
failWith(StringEqualNoCaseFailure(this, fileName, lineNumber, expected, actual, text));
}
-void UtestShell::assertCstrContains(const char* expected, const char* actual, const char* text, const char* fileName, int lineNumber)
+void UtestShell::assertCstrContains(const char* expected, const char* actual, const char* text, const char* fileName, size_t lineNumber)
{
getTestResult()->countCheck();
- if (actual == 0 && expected == 0) return;
- if(actual == 0 || expected == 0)
+ if (actual == NULLPTR && expected == NULLPTR) return;
+ if (actual == NULLPTR || expected == NULLPTR)
failWith(ContainsFailure(this, fileName, lineNumber, expected, actual, text));
if (!SimpleString(actual).contains(expected))
failWith(ContainsFailure(this, fileName, lineNumber, expected, actual, text));
}
-void UtestShell::assertCstrNoCaseContains(const char* expected, const char* actual, const char* text, const char* fileName, int lineNumber)
+void UtestShell::assertCstrNoCaseContains(const char* expected, const char* actual, const char* text, const char* fileName, size_t lineNumber)
{
getTestResult()->countCheck();
- if (actual == 0 && expected == 0) return;
- if(actual == 0 || expected == 0)
+ if (actual == NULLPTR && expected == NULLPTR) return;
+ if (actual == NULLPTR || expected == NULLPTR)
failWith(ContainsFailure(this, fileName, lineNumber, expected, actual, text));
if (!SimpleString(actual).containsNoCase(expected))
failWith(ContainsFailure(this, fileName, lineNumber, expected, actual, text));
}
-void UtestShell::assertLongsEqual(long expected, long actual, const char* text, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+void UtestShell::assertLongsEqual(long expected, long actual, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
if (expected != actual)
failWith(LongsEqualFailure (this, fileName, lineNumber, expected, actual, text), testTerminator);
}
-void UtestShell::assertUnsignedLongsEqual(unsigned long expected, unsigned long actual, const char* text, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+void UtestShell::assertUnsignedLongsEqual(unsigned long expected, unsigned long actual, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
if (expected != actual)
failWith(UnsignedLongsEqualFailure (this, fileName, lineNumber, expected, actual, text), testTerminator);
}
-void UtestShell::assertLongLongsEqual(cpputest_longlong expected, cpputest_longlong actual, const char* text, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+void UtestShell::assertLongLongsEqual(cpputest_longlong expected, cpputest_longlong actual, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
-#ifdef CPPUTEST_USE_LONG_LONG
+#if CPPUTEST_USE_LONG_LONG
if (expected != actual)
failWith(LongLongsEqualFailure(this, fileName, lineNumber, expected, actual, text), testTerminator);
#else
@@ -442,10 +482,10 @@ void UtestShell::assertLongLongsEqual(cpputest_longlong expected, cpputest_longl
#endif
}
-void UtestShell::assertUnsignedLongLongsEqual(cpputest_ulonglong expected, cpputest_ulonglong actual, const char* text, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+void UtestShell::assertUnsignedLongLongsEqual(cpputest_ulonglong expected, cpputest_ulonglong actual, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
-#ifdef CPPUTEST_USE_LONG_LONG
+#if CPPUTEST_USE_LONG_LONG
if (expected != actual)
failWith(UnsignedLongLongsEqualFailure(this, fileName, lineNumber, expected, actual, text), testTerminator);
#else
@@ -455,60 +495,67 @@ void UtestShell::assertUnsignedLongLongsEqual(cpputest_ulonglong expected, cpput
#endif
}
-void UtestShell::assertSignedBytesEqual(signed char expected, signed char actual, const char* text, const char *fileName, int lineNumber, const TestTerminator& testTerminator)
+void UtestShell::assertSignedBytesEqual(signed char expected, signed char actual, const char* text, const char *fileName, size_t lineNumber, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
if (expected != actual)
failWith(SignedBytesEqualFailure (this, fileName, lineNumber, expected, actual, text), testTerminator);
}
-void UtestShell::assertPointersEqual(const void* expected, const void* actual, const char* text, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+void UtestShell::assertPointersEqual(const void* expected, const void* actual, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
if (expected != actual)
failWith(EqualsFailure(this, fileName, lineNumber, StringFrom(expected), StringFrom(actual), text), testTerminator);
}
-void UtestShell::assertFunctionPointersEqual(void (*expected)(), void (*actual)(), const char* text, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+void UtestShell::assertFunctionPointersEqual(void (*expected)(), void (*actual)(), const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
if (expected != actual)
failWith(EqualsFailure(this, fileName, lineNumber, StringFrom(expected), StringFrom(actual), text), testTerminator);
}
-void UtestShell::assertDoublesEqual(double expected, double actual, double threshold, const char* text, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
+void UtestShell::assertDoublesEqual(double expected, double actual, double threshold, const char* text, const char* fileName, size_t lineNumber, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
if (!doubles_equal(expected, actual, threshold))
failWith(DoublesEqualFailure(this, fileName, lineNumber, expected, actual, threshold, text), testTerminator);
}
-void UtestShell::assertBinaryEqual(const void *expected, const void *actual, size_t length, const char* text, const char *fileName, int lineNumber, const TestTerminator& testTerminator)
+void UtestShell::assertBinaryEqual(const void *expected, const void *actual, size_t length, const char* text, const char *fileName, size_t lineNumber, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
- if (actual == 0 && expected == 0) return;
- if (actual == 0 || expected == 0)
+ if (length == 0) return;
+ if (actual == NULLPTR && expected == NULLPTR) return;
+ if (actual == NULLPTR || expected == NULLPTR)
failWith(BinaryEqualFailure(this, fileName, lineNumber, (const unsigned char *) expected, (const unsigned char *) actual, length, text), testTerminator);
if (SimpleString::MemCmp(expected, actual, length) != 0)
failWith(BinaryEqualFailure(this, fileName, lineNumber, (const unsigned char *) expected, (const unsigned char *) actual, length, text), testTerminator);
}
-void UtestShell::assertBitsEqual(unsigned long expected, unsigned long actual, unsigned long mask, size_t byteCount, const char* text, const char *fileName, int lineNumber, const TestTerminator& testTerminator)
+void UtestShell::assertBitsEqual(unsigned long expected, unsigned long actual, unsigned long mask, size_t byteCount, const char* text, const char *fileName, size_t lineNumber, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
if ((expected & mask) != (actual & mask))
failWith(BitsEqualFailure(this, fileName, lineNumber, expected, actual, mask, byteCount, text), testTerminator);
}
-void UtestShell::assertEquals(bool failed, const char* expected, const char* actual, const char* text, const char* file, int line, const TestTerminator& testTerminator)
+void UtestShell::assertEquals(bool failed, const char* expected, const char* actual, const char* text, const char* file, size_t line, const TestTerminator& testTerminator)
{
getTestResult()->countCheck();
if (failed)
failWith(CheckEqualFailure(this, file, line, expected, actual, text), testTerminator);
}
+void UtestShell::assertCompare(bool comparison, const char *checkString, const char *comparisonString, const char *text, const char *fileName, size_t lineNumber, const TestTerminator &testTerminator)
+{
+ getTestResult()->countCheck();
+ if (!comparison)
+ failWith(ComparisonFailure(this, fileName, lineNumber, checkString, comparisonString, text), testTerminator);
+}
-void UtestShell::print(const char *text, const char* fileName, int lineNumber)
+void UtestShell::print(const char *text, const char* fileName, size_t lineNumber)
{
SimpleString stringToPrint = "\n";
stringToPrint += fileName;
@@ -519,13 +566,18 @@ void UtestShell::print(const char *text, const char* fileName, int lineNumber)
getTestResult()->print(stringToPrint.asCharString());
}
-void UtestShell::print(const SimpleString& text, const char* fileName, int lineNumber)
+void UtestShell::print(const SimpleString& text, const char* fileName, size_t lineNumber)
{
print(text.asCharString(), fileName, lineNumber);
}
-TestResult* UtestShell::testResult_ = NULL;
-UtestShell* UtestShell::currentTest_ = NULL;
+void UtestShell::printVeryVerbose(const char* text)
+{
+ getTestResult()->printVeryVerbose(text);
+}
+
+TestResult* UtestShell::testResult_ = NULLPTR;
+UtestShell* UtestShell::currentTest_ = NULLPTR;
void UtestShell::setTestResult(TestResult* result)
{
@@ -539,18 +591,49 @@ void UtestShell::setCurrentTest(UtestShell* test)
TestResult* UtestShell::getTestResult()
{
- if (testResult_ == NULL)
+ if (testResult_ == NULLPTR)
return &OutsideTestRunnerUTest::instance().getTestResult();
return testResult_;
}
UtestShell* UtestShell::getCurrent()
{
- if (currentTest_ == NULL)
+ if (currentTest_ == NULLPTR)
return &OutsideTestRunnerUTest::instance();
return currentTest_;
}
+const TestTerminator &UtestShell::getCurrentTestTerminator()
+{
+ return *currentTestTerminator_;
+}
+
+const TestTerminator &UtestShell::getCurrentTestTerminatorWithoutExceptions()
+{
+ return *currentTestTerminatorWithoutExceptions_;
+}
+
+void UtestShell::setCrashOnFail()
+{
+ currentTestTerminator_ = &crashingTestTerminator;
+ currentTestTerminatorWithoutExceptions_ = &crashingTestTerminatorWithoutExceptions;
+}
+
+void UtestShell::restoreDefaultTestTerminator()
+{
+ currentTestTerminator_ = &normalTestTerminator;
+ currentTestTerminatorWithoutExceptions_ = &normalTestTerminatorWithoutExceptions;
+}
+
+void UtestShell::setRethrowExceptions(bool rethrowExceptions)
+{
+ rethrowExceptions_ = rethrowExceptions;
+}
+
+bool UtestShell::isRethrowingExceptions()
+{
+ return rethrowExceptions_;
+}
ExecFunctionTestShell::~ExecFunctionTestShell()
{
@@ -566,28 +649,77 @@ Utest::~Utest()
{
}
-#if CPPUTEST_USE_STD_CPP_LIB
+#if CPPUTEST_HAVE_EXCEPTIONS
void Utest::run()
{
+ UtestShell* current = UtestShell::getCurrent();
+ int jumpResult = 0;
try {
- if (PlatformSpecificSetJmp(helperDoTestSetup, this)) {
+ current->printVeryVerbose("\n-------- before setup: ");
+ jumpResult = PlatformSpecificSetJmp(helperDoTestSetup, this);
+ current->printVeryVerbose("\n-------- after setup: ");
+
+ if (jumpResult) {
+ current->printVeryVerbose("\n---------- before body: ");
PlatformSpecificSetJmp(helperDoTestBody, this);
+ current->printVeryVerbose("\n---------- after body: ");
}
}
catch (CppUTestFailedException&)
{
PlatformSpecificRestoreJumpBuffer();
}
+#if CPPUTEST_USE_STD_CPP_LIB
+ catch (const std::exception &e)
+ {
+ current->addFailure(UnexpectedExceptionFailure(current, e));
+ PlatformSpecificRestoreJumpBuffer();
+ if (current->isRethrowingExceptions())
+ {
+ throw;
+ }
+ }
+#endif
+ catch (...)
+ {
+ current->addFailure(UnexpectedExceptionFailure(current));
+ PlatformSpecificRestoreJumpBuffer();
+ if (current->isRethrowingExceptions())
+ {
+ throw;
+ }
+ }
try {
+ current->printVeryVerbose("\n-------- before teardown: ");
PlatformSpecificSetJmp(helperDoTestTeardown, this);
+ current->printVeryVerbose("\n-------- after teardown: ");
}
catch (CppUTestFailedException&)
{
PlatformSpecificRestoreJumpBuffer();
}
-
+#if CPPUTEST_USE_STD_CPP_LIB
+ catch (const std::exception &e)
+ {
+ current->addFailure(UnexpectedExceptionFailure(current, e));
+ PlatformSpecificRestoreJumpBuffer();
+ if (current->isRethrowingExceptions())
+ {
+ throw;
+ }
+ }
+#endif
+ catch (...)
+ {
+ current->addFailure(UnexpectedExceptionFailure(current));
+ PlatformSpecificRestoreJumpBuffer();
+ if (current->isRethrowingExceptions())
+ {
+ throw;
+ }
+ }
}
#else
@@ -622,7 +754,7 @@ TestTerminator::~TestTerminator()
void NormalTestTerminator::exitCurrentTest() const
{
- #if CPPUTEST_USE_STD_CPP_LIB
+ #if CPPUTEST_HAVE_EXCEPTIONS
throw CppUTestFailedException();
#else
TestTerminatorWithoutExceptions().exitCurrentTest();
@@ -642,6 +774,51 @@ TestTerminatorWithoutExceptions::~TestTerminatorWithoutExceptions()
{
}
+void CrashingTestTerminator::exitCurrentTest() const
+{
+ UtestShell::crash();
+ NormalTestTerminator::exitCurrentTest();
+}
+
+CrashingTestTerminator::~CrashingTestTerminator()
+{
+}
+
+void CrashingTestTerminatorWithoutExceptions::exitCurrentTest() const
+{
+ UtestShell::crash();
+ TestTerminatorWithoutExceptions::exitCurrentTest();
+}
+
+CrashingTestTerminatorWithoutExceptions::~CrashingTestTerminatorWithoutExceptions()
+{
+}
+
+//////////////////// ExecFunction
+//
+ExecFunction::ExecFunction()
+{
+}
+
+ExecFunction::~ExecFunction()
+{
+}
+
+ExecFunctionWithoutParameters::ExecFunctionWithoutParameters(void(*testFunction)())
+ : testFunction_(testFunction)
+{
+}
+
+ExecFunctionWithoutParameters::~ExecFunctionWithoutParameters()
+{
+}
+
+void ExecFunctionWithoutParameters::exec()
+{
+ if (testFunction_)
+ testFunction_();
+}
+
//////////////////// ExecFunctionTest
ExecFunctionTest::ExecFunctionTest(ExecFunctionTestShell* shell)
@@ -651,7 +828,7 @@ ExecFunctionTest::ExecFunctionTest(ExecFunctionTestShell* shell)
void ExecFunctionTest::testBody()
{
- if (shell_->testFunction_) shell_->testFunction_();
+ if (shell_->testFunction_) shell_->testFunction_->exec();
}
void ExecFunctionTest::setup()
@@ -669,7 +846,7 @@ IgnoredUtestShell::IgnoredUtestShell(): runIgnored_(false)
{
}
-IgnoredUtestShell::IgnoredUtestShell(const char* groupName, const char* testName, const char* fileName, int lineNumber) :
+IgnoredUtestShell::IgnoredUtestShell(const char* groupName, const char* testName, const char* fileName, size_t lineNumber) :
UtestShell(groupName, testName, fileName, lineNumber), runIgnored_(false)
{
}
@@ -708,10 +885,89 @@ void IgnoredUtestShell::setRunIgnored()
runIgnored_ = true;
}
+//////////////////// UtestShellPointerArray
+
+UtestShellPointerArray::UtestShellPointerArray(UtestShell* firstTest)
+ : arrayOfTests_(NULLPTR), count_(0)
+{
+ count_ = (firstTest) ? firstTest->countTests() : 0;
+ if (count_ == 0) return;
+
+ arrayOfTests_ = new UtestShell*[count_];
+
+ UtestShell*currentTest = firstTest;
+ for (size_t i = 0; i < count_; i++)
+ {
+ arrayOfTests_[i] = currentTest;
+ currentTest = currentTest->getNext();
+ }
+}
+
+UtestShellPointerArray::~UtestShellPointerArray()
+{
+ delete [] arrayOfTests_;
+}
+
+void UtestShellPointerArray::swap(size_t index1, size_t index2)
+{
+ UtestShell* e2 = arrayOfTests_[index2];
+ UtestShell* e1 = arrayOfTests_[index1];
+ arrayOfTests_[index1] = e2;
+ arrayOfTests_[index2] = e1;
+}
+
+void UtestShellPointerArray::shuffle(size_t seed)
+{
+ if (count_ == 0) return;
+
+ PlatformSpecificSrand((unsigned int) seed);
+
+ for (size_t i = count_ - 1; i >= 1; --i)
+ {
+ if (count_ == 0) return;
+
+ const size_t j = ((size_t)PlatformSpecificRand()) % (i + 1); // distribution biased by modulo, but good enough for shuffling
+ swap(i, j);
+ }
+ relinkTestsInOrder();
+}
+
+void UtestShellPointerArray::reverse()
+{
+ if (count_ == 0) return;
+
+ size_t halfCount = count_ / 2;
+ for (size_t i = 0; i < halfCount; i++)
+ {
+ size_t j = count_ - i - 1;
+ swap(i, j);
+ }
+ relinkTestsInOrder();
+}
+
+void UtestShellPointerArray::relinkTestsInOrder()
+{
+ UtestShell *tests = NULLPTR;
+ for (size_t i = 0; i < count_; i++)
+ tests = arrayOfTests_[count_ - i - 1]->addTest(tests);
+}
+
+UtestShell* UtestShellPointerArray::getFirstTest() const
+{
+ return get(0);
+}
+
+UtestShell* UtestShellPointerArray::get(size_t index) const
+{
+ if (index >= count_) return NULLPTR;
+ return arrayOfTests_[index];
+}
+
+
////////////// TestInstaller ////////////
-TestInstaller::TestInstaller(UtestShell& shell, const char* groupName, const char* testName, const char* fileName, int lineNumber)
+TestInstaller::TestInstaller(UtestShell& shell, const char* groupName, const char* testName, const char* fileName, size_t lineNumber)
{
shell.setGroupName(groupName);
shell.setTestName(testName);
diff --git a/src/CppUTestExt/CMakeLists.txt b/src/CppUTestExt/CMakeLists.txt
index 749be7a9e..ec0f27586 100644
--- a/src/CppUTestExt/CMakeLists.txt
+++ b/src/CppUTestExt/CMakeLists.txt
@@ -1,48 +1,62 @@
-set(CppUTestExt_src
- CodeMemoryReportFormatter.cpp
- IEEE754ExceptionsPlugin.cpp
- MemoryReporterPlugin.cpp
- MockFailure.cpp
- MockSupportPlugin.cpp
- MockActualCall.cpp
- MockSupport_c.cpp
- MemoryReportAllocator.cpp
- MockExpectedCall.cpp
- MockNamedValue.cpp
- OrderedTest.cpp
- MemoryReportFormatter.cpp
- MockExpectedCallsList.cpp
- MockSupport.cpp
+add_library(CppUTestExt STATIC
+ CodeMemoryReportFormatter.cpp
+ GTest.cpp
+ IEEE754ExceptionsPlugin.cpp
+ MemoryReporterPlugin.cpp
+ MockFailure.cpp
+ MockSupportPlugin.cpp
+ MockActualCall.cpp
+ MockSupport_c.cpp
+ MemoryReportAllocator.cpp
+ MockExpectedCall.cpp
+ MockNamedValue.cpp
+ OrderedTest.cpp
+ MemoryReportFormatter.cpp
+ MockExpectedCallsList.cpp
+ MockSupport.cpp
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/CodeMemoryReportFormatter.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/IEEE754ExceptionsPlugin.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/MemoryReportAllocator.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/MockExpectedCall.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/MockCheckedExpectedCall.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/MockExpectedCallsList.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/MockSupportPlugin.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/MemoryReportFormatter.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/MockFailure.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/MockSupport.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/MockSupport_c.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/GMock.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/GTest.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/GTestSupport.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/MemoryReporterPlugin.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/OrderedTest.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/GTestConvertor.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/MockActualCall.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/MockCheckedActualCall.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/MockNamedValue.h
+ ${PROJECT_SOURCE_DIR}/include/CppUTestExt/MockSupport.h
)
-set(CppUTestExt_headers
- ${CppUTestRootDirectory}/include/CppUTestExt/CodeMemoryReportFormatter.h
- ${CppUTestRootDirectory}/include/CppUTestExt/IEEE754ExceptionsPlugin.h
- ${CppUTestRootDirectory}/include/CppUTestExt/MemoryReportAllocator.h
- ${CppUTestRootDirectory}/include/CppUTestExt/MockExpectedCall.h
- ${CppUTestRootDirectory}/include/CppUTestExt/MockCheckedExpectedCall.h
- ${CppUTestRootDirectory}/include/CppUTestExt/MockExpectedCallsList.h
- ${CppUTestRootDirectory}/include/CppUTestExt/MockSupportPlugin.h
- ${CppUTestRootDirectory}/include/CppUTestExt/MemoryReportFormatter.h
- ${CppUTestRootDirectory}/include/CppUTestExt/MockFailure.h
- ${CppUTestRootDirectory}/include/CppUTestExt/MockSupport.h
- ${CppUTestRootDirectory}/include/CppUTestExt/MockSupport_c.h
- ${CppUTestRootDirectory}/include/CppUTestExt/GMock.h
- ${CppUTestRootDirectory}/include/CppUTestExt/GTest.h
- ${CppUTestRootDirectory}/include/CppUTestExt/MemoryReporterPlugin.h
- ${CppUTestRootDirectory}/include/CppUTestExt/OrderedTest.h
- ${CppUTestRootDirectory}/include/CppUTestExt/GTestConvertor.h
- ${CppUTestRootDirectory}/include/CppUTestExt/MockActualCall.h
- ${CppUTestRootDirectory}/include/CppUTestExt/MockCheckedActualCall.h
- ${CppUTestRootDirectory}/include/CppUTestExt/MockNamedValue.h
- ${CppUTestRootDirectory}/include/CppUTestExt/MockSupport.h
+target_link_libraries(CppUTestExt PUBLIC CppUTest)
+
+#[[Arrange for the include directory to be added to the include paths of any CMake target depending on CppUTestExt.]]
+target_include_directories(CppUTestExt
+ PUBLIC
+ $
+ $
)
-add_library(CppUTestExt STATIC ${CppUTestExt_src} ${CppUTestExt_headers})
-target_link_libraries(CppUTestExt ${CPPUNIT_EXTERNAL_LIBRARIES})
-install(FILES ${CppUTestExt_headers} DESTINATION include/CppUTestExt)
-install(TARGETS CppUTestExt
- EXPORT CppUTestTargets
- RUNTIME DESTINATION bin
- LIBRARY DESTINATION lib
- ARCHIVE DESTINATION lib)
+add_library(CppUTest::CppUTestExt ALIAS CppUTestExt)
+
+if(PROJECT_IS_TOP_LEVEL)
+ install(
+ TARGETS CppUTestExt
+ EXPORT CppUTestTargets
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ )
+ install(
+ DIRECTORY "${PROJECT_SOURCE_DIR}/include/CppUTestExt"
+ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
+ )
+endif()
diff --git a/src/CppUTestExt/CodeMemoryReportFormatter.cpp b/src/CppUTestExt/CodeMemoryReportFormatter.cpp
index ff210374c..57c1e4f96 100644
--- a/src/CppUTestExt/CodeMemoryReportFormatter.cpp
+++ b/src/CppUTestExt/CodeMemoryReportFormatter.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -34,7 +34,7 @@
#define MAX_VARIABLE_NAME_LINE_PART 10
#define MAX_VARIABLE_NAME_FILE_PART 53
#define MAX_VARIABLE_NAME_SEPERATOR_PART 1
-#define MAX_VARIABLE_NAME_LENGTH MAX_VARIABLE_NAME_FILE_PART + MAX_VARIABLE_NAME_SEPERATOR_PART + MAX_VARIABLE_NAME_LINE_PART
+#define MAX_VARIABLE_NAME_LENGTH (MAX_VARIABLE_NAME_FILE_PART + MAX_VARIABLE_NAME_SEPERATOR_PART + MAX_VARIABLE_NAME_LINE_PART)
struct CodeReportingAllocationNode
{
@@ -44,7 +44,7 @@ struct CodeReportingAllocationNode
};
CodeMemoryReportFormatter::CodeMemoryReportFormatter(TestMemoryAllocator* internalAllocator)
- : codeReportingList_(NULL), internalAllocator_(internalAllocator)
+ : codeReportingList_(NULLPTR), internalAllocator_(internalAllocator)
{
}
@@ -58,7 +58,7 @@ void CodeMemoryReportFormatter::clearReporting()
while (codeReportingList_) {
CodeReportingAllocationNode* oldNode = codeReportingList_;
codeReportingList_ = codeReportingList_->next_;
- internalAllocator_->free_memory((char*) oldNode, __FILE__, __LINE__);
+ internalAllocator_->free_memory((char*) oldNode, 0, __FILE__, __LINE__);
}
}
@@ -90,13 +90,13 @@ static SimpleString extractFileNameFromPath(const char* file)
return fileNameOnly;
}
-SimpleString CodeMemoryReportFormatter::createVariableNameFromFileLineInfo(const char *file, int line)
+SimpleString CodeMemoryReportFormatter::createVariableNameFromFileLineInfo(const char *file, size_t line)
{
SimpleString fileNameOnly = extractFileNameFromPath(file);
fileNameOnly.replace(".", "_");
for (int i = 1; i < 100; i++) {
- SimpleString variableName = StringFromFormat("%s_%d_%d", fileNameOnly.asCharString(), line, i);
+ SimpleString variableName = StringFromFormat("%s_%d_%d", fileNameOnly.asCharString(), (int) line, i);
if (!variableExists(variableName))
return variableName;
}
@@ -127,19 +127,19 @@ SimpleString CodeMemoryReportFormatter::getAllocationString(TestMemoryAllocator*
return StringFromFormat("void* %s = malloc(%lu);", variableName.asCharString(), (unsigned long) size);
}
-SimpleString CodeMemoryReportFormatter::getDeallocationString(TestMemoryAllocator* allocator, const SimpleString& variableName, const char* file, int line)
+SimpleString CodeMemoryReportFormatter::getDeallocationString(TestMemoryAllocator* allocator, const SimpleString& variableName, const char* file, size_t line)
{
if (isNewAllocator(allocator))
- return StringFromFormat("delete [] %s; /* using %s at %s:%d */", variableName.asCharString(), allocator->free_name(), file, line);
+ return StringFromFormat("delete [] %s; /* using %s at %s:%d */", variableName.asCharString(), allocator->free_name(), file, (int) line);
else
- return StringFromFormat("free(%s); /* at %s:%d */", variableName.asCharString(), file, line);
+ return StringFromFormat("free(%s); /* at %s:%d */", variableName.asCharString(), file, (int) line);
}
void CodeMemoryReportFormatter::report_test_start(TestResult* result, UtestShell& test)
{
clearReporting();
result->print(StringFromFormat("*/\nTEST(%s_memoryReport, %s)\n{ /* at %s:%d */\n",
- test.getGroup().asCharString(), test.getName().asCharString(), test.getFile().asCharString(), test.getLineNumber()).asCharString());
+ test.getGroup().asCharString(), test.getName().asCharString(), test.getFile().asCharString(), (int) test.getLineNumber()).asCharString());
}
void CodeMemoryReportFormatter::report_test_end(TestResult* result, UtestShell&)
@@ -153,19 +153,19 @@ void CodeMemoryReportFormatter::report_testgroup_start(TestResult* result, Utest
test.getGroup().asCharString()).asCharString());
}
-void CodeMemoryReportFormatter::report_alloc_memory(TestResult* result, TestMemoryAllocator* allocator, size_t size, char* memory, const char* file, int line)
+void CodeMemoryReportFormatter::report_alloc_memory(TestResult* result, TestMemoryAllocator* allocator, size_t size, char* memory, const char* file, size_t line)
{
SimpleString variableName = createVariableNameFromFileLineInfo(file, line);
result->print(StringFromFormat("\t%s\n", getAllocationString(allocator, variableName, size).asCharString()).asCharString());
addNodeToList(variableName.asCharString(), memory, codeReportingList_);
}
-void CodeMemoryReportFormatter::report_free_memory(TestResult* result, TestMemoryAllocator* allocator, char* memory, const char* file, int line)
+void CodeMemoryReportFormatter::report_free_memory(TestResult* result, TestMemoryAllocator* allocator, char* memory, const char* file, size_t line)
{
SimpleString variableName;
CodeReportingAllocationNode* node = findNode(memory);
- if (memory == NULL) variableName = "NULL";
+ if (memory == NULLPTR) variableName = "NULL";
else variableName = node->variableName_;
result->print(StringFromFormat("\t%s\n", getDeallocationString(allocator, variableName, file, line).asCharString()).asCharString());
diff --git a/src/CppUTestExt/GTest.cpp b/src/CppUTestExt/GTest.cpp
new file mode 100644
index 000000000..919866c39
--- /dev/null
+++ b/src/CppUTestExt/GTest.cpp
@@ -0,0 +1,9 @@
+
+#include "CppUTest/TestHarness.h"
+#include "CppUTestExt/GTestSupport.h"
+
+void CppuTestGTestIgnoreLeaksInTest()
+{
+ IGNORE_ALL_LEAKS_IN_TEST();
+}
+
diff --git a/src/CppUTestExt/IEEE754ExceptionsPlugin.cpp b/src/CppUTestExt/IEEE754ExceptionsPlugin.cpp
index 9f0ec9b38..5b84a4862 100644
--- a/src/CppUTestExt/IEEE754ExceptionsPlugin.cpp
+++ b/src/CppUTestExt/IEEE754ExceptionsPlugin.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -28,7 +28,7 @@
#include "CppUTest/TestHarness.h"
#include "CppUTestExt/IEEE754ExceptionsPlugin.h"
-#ifdef CPPUTEST_HAVE_FENV
+#if CPPUTEST_HAVE_FENV
extern "C" {
#include
@@ -100,4 +100,54 @@ void IEEE754ExceptionsPlugin::ieee754Check(UtestShell& test, TestResult& result,
}
}
+#else
+
+
+bool IEEE754ExceptionsPlugin::inexactDisabled_ = true;
+
+IEEE754ExceptionsPlugin::IEEE754ExceptionsPlugin(const SimpleString& name)
+ : TestPlugin(name)
+{
+}
+
+void IEEE754ExceptionsPlugin::preTestAction(UtestShell&, TestResult&)
+{
+}
+
+void IEEE754ExceptionsPlugin::postTestAction(UtestShell&, TestResult&)
+{
+}
+
+void IEEE754ExceptionsPlugin::disableInexact()
+{
+}
+
+void IEEE754ExceptionsPlugin::enableInexact()
+{
+}
+
+bool IEEE754ExceptionsPlugin::checkIeee754OverflowExceptionFlag()
+{
+ return false;
+}
+
+bool IEEE754ExceptionsPlugin::checkIeee754UnderflowExceptionFlag()
+{
+ return false;
+}
+
+bool IEEE754ExceptionsPlugin::checkIeee754InexactExceptionFlag()
+{
+ return false;
+}
+
+bool IEEE754ExceptionsPlugin::checkIeee754DivByZeroExceptionFlag()
+{
+ return false;
+}
+
+void IEEE754ExceptionsPlugin::ieee754Check(UtestShell&, TestResult&, int, const char*)
+{
+}
+
#endif
diff --git a/src/CppUTestExt/MemoryReportAllocator.cpp b/src/CppUTestExt/MemoryReportAllocator.cpp
index 30c27c1cf..f51b932ab 100644
--- a/src/CppUTestExt/MemoryReportAllocator.cpp
+++ b/src/CppUTestExt/MemoryReportAllocator.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -29,7 +29,7 @@
#include "CppUTestExt/MemoryReportAllocator.h"
#include "CppUTestExt/MemoryReportFormatter.h"
-MemoryReportAllocator::MemoryReportAllocator() : result_(NULL), realAllocator_(NULL), formatter_(NULL)
+MemoryReportAllocator::MemoryReportAllocator() : result_(NULLPTR), realAllocator_(NULLPTR), formatter_(NULLPTR)
{
}
@@ -37,17 +37,17 @@ MemoryReportAllocator::~MemoryReportAllocator()
{
}
-const char* MemoryReportAllocator::name()
+const char* MemoryReportAllocator::name() const
{
- return realAllocator_->name();
+ return "MemoryReporterAllocator";
}
-const char* MemoryReportAllocator::alloc_name()
+const char* MemoryReportAllocator::alloc_name() const
{
return realAllocator_->alloc_name();
}
-const char* MemoryReportAllocator::free_name()
+const char* MemoryReportAllocator::free_name() const
{
return realAllocator_->free_name();
}
@@ -62,6 +62,11 @@ TestMemoryAllocator* MemoryReportAllocator::getRealAllocator()
return realAllocator_;
}
+TestMemoryAllocator* MemoryReportAllocator::actualAllocator()
+{
+ return realAllocator_->actualAllocator();
+}
+
void MemoryReportAllocator::setTestResult(TestResult* result)
{
result_ = result;
@@ -72,7 +77,7 @@ void MemoryReportAllocator::setFormatter(MemoryReportFormatter* formatter)
formatter_ = formatter;
}
-char* MemoryReportAllocator::alloc_memory(size_t size, const char* file, int line)
+char* MemoryReportAllocator::alloc_memory(size_t size, const char* file, size_t line)
{
char* memory = realAllocator_->alloc_memory(size, file, line);
if (result_ && formatter_)
@@ -80,9 +85,9 @@ char* MemoryReportAllocator::alloc_memory(size_t size, const char* file, int lin
return memory;
}
-void MemoryReportAllocator::free_memory(char* memory, const char* file, int line)
+void MemoryReportAllocator::free_memory(char* memory, size_t size, const char* file, size_t line)
{
- realAllocator_->free_memory(memory, file, line);
+ realAllocator_->free_memory(memory, size, file, line);
if (result_ && formatter_)
formatter_->report_free_memory(result_, this, memory, file, line);
}
diff --git a/src/CppUTestExt/MemoryReportFormatter.cpp b/src/CppUTestExt/MemoryReportFormatter.cpp
index ec912e76a..13833e5d6 100644
--- a/src/CppUTestExt/MemoryReportFormatter.cpp
+++ b/src/CppUTestExt/MemoryReportFormatter.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -47,14 +47,14 @@ void NormalMemoryReportFormatter::report_test_end(TestResult* result, UtestShell
result->print(StringFromFormat("ENDTEST(%s, %s)\n", test.getGroup().asCharString(), test.getName().asCharString()).asCharString());
}
-void NormalMemoryReportFormatter::report_alloc_memory(TestResult* result, TestMemoryAllocator* allocator, size_t size, char* memory, const char* file, int line)
+void NormalMemoryReportFormatter::report_alloc_memory(TestResult* result, TestMemoryAllocator* allocator, size_t size, char* memory, const char* file, size_t line)
{
- result->print(StringFromFormat("\tAllocation using %s of size: %lu pointer: %p at %s:%d\n", allocator->alloc_name(), (unsigned long) size, (void*) memory, file, line).asCharString());
+ result->print(StringFromFormat("\tAllocation using %s of size: %lu pointer: %p at %s:%d\n", allocator->alloc_name(), (unsigned long) size, (void*) memory, file, (int) line).asCharString());
}
-void NormalMemoryReportFormatter::report_free_memory(TestResult* result, TestMemoryAllocator* allocator, char* memory, const char* file, int line)
+void NormalMemoryReportFormatter::report_free_memory(TestResult* result, TestMemoryAllocator* allocator, char* memory, const char* file, size_t line)
{
- result->print(StringFromFormat("\tDeallocation using %s of pointer: %p at %s:%d\n", allocator->free_name(), (void*) memory, file, line).asCharString());
+ result->print(StringFromFormat("\tDeallocation using %s of pointer: %p at %s:%d\n", allocator->free_name(), (void*) memory, file, (int) line).asCharString());
}
void NormalMemoryReportFormatter::report_testgroup_start(TestResult* result, UtestShell& test)
diff --git a/src/CppUTestExt/MemoryReporterPlugin.cpp b/src/CppUTestExt/MemoryReporterPlugin.cpp
index e4206e004..8b81f5dc8 100644
--- a/src/CppUTestExt/MemoryReporterPlugin.cpp
+++ b/src/CppUTestExt/MemoryReporterPlugin.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -31,7 +31,7 @@
#include "CppUTestExt/CodeMemoryReportFormatter.h"
MemoryReporterPlugin::MemoryReporterPlugin()
- : TestPlugin("MemoryReporterPlugin"), formatter_(NULL)
+ : TestPlugin("MemoryReporterPlugin"), formatter_(NULLPTR)
{
}
@@ -41,7 +41,7 @@ MemoryReporterPlugin::~MemoryReporterPlugin()
destroyMemoryFormatter(formatter_);
}
-bool MemoryReporterPlugin::parseArguments(int /* ac */, const char** av, int index)
+bool MemoryReporterPlugin::parseArguments(int /* ac */, const char *const *av, int index)
{
SimpleString argument (av[index]);
if (argument.contains("-pmemoryreport=")) {
@@ -62,7 +62,7 @@ MemoryReportFormatter* MemoryReporterPlugin::createMemoryFormatter(const SimpleS
else if (type == "code") {
return new CodeMemoryReportFormatter(defaultMallocAllocator());
}
- return NULL;
+ return NULLPTR;
}
void MemoryReporterPlugin::destroyMemoryFormatter(MemoryReportFormatter* formatter)
@@ -95,6 +95,20 @@ void MemoryReporterPlugin::removeGlobalMemoryReportAllocators()
setCurrentMallocAllocator(mallocAllocator.getRealAllocator());
}
+MemoryReportAllocator* MemoryReporterPlugin::getMallocAllocator()
+{
+ return &mallocAllocator;
+}
+
+MemoryReportAllocator* MemoryReporterPlugin::getNewAllocator()
+{
+ return &newAllocator;
+}
+
+MemoryReportAllocator* MemoryReporterPlugin::getNewArrayAllocator()
+{
+ return &newArrayAllocator;
+}
void MemoryReporterPlugin::initializeAllocator(MemoryReportAllocator* allocator, TestResult & result)
{
@@ -104,7 +118,7 @@ void MemoryReporterPlugin::initializeAllocator(MemoryReportAllocator* allocator,
void MemoryReporterPlugin::preTestAction(UtestShell& test, TestResult& result)
{
- if (formatter_ == NULL) return;
+ if (formatter_ == NULLPTR) return;
initializeAllocator(&mallocAllocator, result);
initializeAllocator(&newAllocator, result);
@@ -122,11 +136,11 @@ void MemoryReporterPlugin::preTestAction(UtestShell& test, TestResult& result)
void MemoryReporterPlugin::postTestAction(UtestShell& test, TestResult& result)
{
- if (formatter_ == NULL) return;
+ if (formatter_ == NULLPTR) return;
removeGlobalMemoryReportAllocators();
formatter_->report_test_end(&result, test);
- if (test.getNext() == NULL || test.getNext()->getGroup() != currentTestGroup_)
+ if (test.getNext() == NULLPTR || test.getNext()->getGroup() != currentTestGroup_)
formatter_->report_testgroup_end(&result, test);
}
diff --git a/src/CppUTestExt/MockActualCall.cpp b/src/CppUTestExt/MockActualCall.cpp
index 0cfef9a2c..319e20a60 100644
--- a/src/CppUTestExt/MockActualCall.cpp
+++ b/src/CppUTestExt/MockActualCall.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -49,10 +49,11 @@ SimpleString MockCheckedActualCall::getName() const
return functionName_;
}
-MockCheckedActualCall::MockCheckedActualCall(int callOrder, MockFailureReporter* reporter, const MockExpectedCallsList& allExpectations)
- : callOrder_(callOrder), reporter_(reporter), state_(CALL_SUCCEED), fulfilledExpectation_(NULL), allExpectations_(allExpectations), outputParameterExpectations_(NULL)
+MockCheckedActualCall::MockCheckedActualCall(unsigned int callOrder, MockFailureReporter* reporter, const MockExpectedCallsList& allExpectations)
+ : callOrder_(callOrder), reporter_(reporter), state_(CALL_SUCCEED), expectationsChecked_(false), matchingExpectation_(NULLPTR),
+ allExpectations_(allExpectations), outputParameterExpectations_(NULLPTR)
{
- unfulfilledExpectations_.addUnfulfilledExpectations(allExpectations);
+ potentiallyMatchingExpectations_.addPotentiallyMatchingExpectations(allExpectations);
}
MockCheckedActualCall::~MockCheckedActualCall()
@@ -78,7 +79,7 @@ void MockCheckedActualCall::failTest(const MockFailure& failure)
}
}
-void MockCheckedActualCall::finalizeOutputParameters(MockCheckedExpectedCall* expectedCall)
+void MockCheckedActualCall::copyOutputParameters(MockCheckedExpectedCall* expectedCall)
{
for (MockOutputParametersListNode* p = outputParameterExpectations_; p; p = p->next_)
{
@@ -86,7 +87,7 @@ void MockCheckedActualCall::finalizeOutputParameters(MockCheckedExpectedCall* ex
MockNamedValueCopier* copier = outputParameter.getCopier();
if (copier)
{
- copier->copy(p->ptr_, outputParameter.getObjectPointer());
+ copier->copy(p->ptr_, outputParameter.getConstObjectPointer());
}
else if ((outputParameter.getType() == "const void*") && (p->type_ == "void*"))
{
@@ -103,15 +104,19 @@ void MockCheckedActualCall::finalizeOutputParameters(MockCheckedExpectedCall* ex
}
}
-void MockCheckedActualCall::finalizeCallWhenFulfilled()
+void MockCheckedActualCall::completeCallWhenMatchIsFound()
{
- if (unfulfilledExpectations_.hasFulfilledExpectationsWithoutIgnoredParameters()) {
- finalizeOutputParameters(unfulfilledExpectations_.getOneFulfilledExpectationWithIgnoredParameters());
- }
+ // Expectations that don't ignore parameters have higher fulfillment preference than those that ignore parameters
- if (unfulfilledExpectations_.hasFulfilledExpectations()) {
- fulfilledExpectation_ = unfulfilledExpectations_.removeOneFulfilledExpectation();
+ matchingExpectation_ = potentiallyMatchingExpectations_.removeFirstFinalizedMatchingExpectation();
+ if (matchingExpectation_) {
+ copyOutputParameters(matchingExpectation_);
callHasSucceeded();
+ } else {
+ MockCheckedExpectedCall* matchingExpectationWithIgnoredParameters = potentiallyMatchingExpectations_.getFirstMatchingExpectation();
+ if (matchingExpectationWithIgnoredParameters) {
+ copyOutputParameters(matchingExpectationWithIgnoredParameters);
+ }
}
}
@@ -120,37 +125,34 @@ void MockCheckedActualCall::callHasSucceeded()
setState(CALL_SUCCEED);
}
-void MockCheckedActualCall::callIsInProgress()
+void MockCheckedActualCall::discardCurrentlyMatchingExpectations()
{
- setState(CALL_IN_PROGRESS);
- if (fulfilledExpectation_)
+ if (matchingExpectation_)
{
- fulfilledExpectation_->resetExpectation();
- fulfilledExpectation_ = NULL;
+ matchingExpectation_->resetActualCallMatchingState();
+ matchingExpectation_ = NULLPTR;
}
- unfulfilledExpectations_.onlyKeepUnfulfilledExpectations();
+ potentiallyMatchingExpectations_.onlyKeepUnmatchingExpectations();
}
MockActualCall& MockCheckedActualCall::withName(const SimpleString& name)
{
setName(name);
- callIsInProgress();
+ setState(CALL_IN_PROGRESS);
- unfulfilledExpectations_.onlyKeepExpectationsRelatedTo(name);
- if (unfulfilledExpectations_.isEmpty()) {
+ potentiallyMatchingExpectations_.onlyKeepExpectationsRelatedTo(name);
+ if (potentiallyMatchingExpectations_.isEmpty()) {
MockUnexpectedCallHappenedFailure failure(getTest(), name, allExpectations_);
failTest(failure);
return *this;
}
- unfulfilledExpectations_.callWasMade(callOrder_);
-
- finalizeCallWhenFulfilled();
+ completeCallWhenMatchIsFound();
return *this;
}
-MockActualCall& MockCheckedActualCall::withCallOrder(int)
+MockActualCall& MockCheckedActualCall::withCallOrder(unsigned int)
{
return *this;
}
@@ -162,18 +164,19 @@ void MockCheckedActualCall::checkInputParameter(const MockNamedValue& actualPara
return;
}
- callIsInProgress();
+ setState(CALL_IN_PROGRESS);
+ discardCurrentlyMatchingExpectations();
- unfulfilledExpectations_.onlyKeepExpectationsWithInputParameter(actualParameter);
+ potentiallyMatchingExpectations_.onlyKeepExpectationsWithInputParameter(actualParameter);
- if (unfulfilledExpectations_.isEmpty()) {
+ if (potentiallyMatchingExpectations_.isEmpty()) {
MockUnexpectedInputParameterFailure failure(getTest(), getName(), actualParameter, allExpectations_);
failTest(failure);
return;
}
- unfulfilledExpectations_.parameterWasPassed(actualParameter.getName());
- finalizeCallWhenFulfilled();
+ potentiallyMatchingExpectations_.parameterWasPassed(actualParameter.getName());
+ completeCallWhenMatchIsFound();
}
void MockCheckedActualCall::checkOutputParameter(const MockNamedValue& outputParameter)
@@ -183,18 +186,19 @@ void MockCheckedActualCall::checkOutputParameter(const MockNamedValue& outputPar
return;
}
- callIsInProgress();
+ setState(CALL_IN_PROGRESS);
+ discardCurrentlyMatchingExpectations();
- unfulfilledExpectations_.onlyKeepExpectationsWithOutputParameter(outputParameter);
+ potentiallyMatchingExpectations_.onlyKeepExpectationsWithOutputParameter(outputParameter);
- if (unfulfilledExpectations_.isEmpty()) {
+ if (potentiallyMatchingExpectations_.isEmpty()) {
MockUnexpectedOutputParameterFailure failure(getTest(), getName(), outputParameter, allExpectations_);
failTest(failure);
return;
}
- unfulfilledExpectations_.outputParameterWasPassed(outputParameter.getName());
- finalizeCallWhenFulfilled();
+ potentiallyMatchingExpectations_.outputParameterWasPassed(outputParameter.getName());
+ completeCallWhenMatchIsFound();
}
MockActualCall& MockCheckedActualCall::withBoolParameter(const SimpleString& name, bool value)
@@ -237,6 +241,40 @@ MockActualCall& MockCheckedActualCall::withLongIntParameter(const SimpleString&
return *this;
}
+#if CPPUTEST_USE_LONG_LONG
+
+MockActualCall& MockCheckedActualCall::withUnsignedLongLongIntParameter(const SimpleString& name, cpputest_ulonglong value)
+{
+ MockNamedValue actualParameter(name);
+ actualParameter.setValue(value);
+ checkInputParameter(actualParameter);
+ return *this;
+}
+
+MockActualCall& MockCheckedActualCall::withLongLongIntParameter(const SimpleString& name, cpputest_longlong value)
+{
+ MockNamedValue actualParameter(name);
+ actualParameter.setValue(value);
+ checkInputParameter(actualParameter);
+ return *this;
+}
+
+#else
+
+MockActualCall& MockCheckedActualCall::withUnsignedLongLongIntParameter(const SimpleString&, cpputest_ulonglong)
+{
+ FAIL("Unsigned Long Long type is not supported");
+ return *this;
+}
+
+MockActualCall& MockCheckedActualCall::withLongLongIntParameter(const SimpleString&, cpputest_longlong)
+{
+ FAIL("Long Long type is not supported");
+ return *this;
+}
+
+#endif
+
MockActualCall& MockCheckedActualCall::withDoubleParameter(const SimpleString& name, double value)
{
MockNamedValue actualParameter(name);
@@ -288,9 +326,9 @@ MockActualCall& MockCheckedActualCall::withMemoryBufferParameter(const SimpleStr
MockActualCall& MockCheckedActualCall::withParameterOfType(const SimpleString& type, const SimpleString& name, const void* value)
{
MockNamedValue actualParameter(name);
- actualParameter.setObjectPointer(type, value);
+ actualParameter.setConstObjectPointer(type, value);
- if (actualParameter.getComparator() == NULL) {
+ if (actualParameter.getComparator() == NULLPTR) {
MockNoWayToCompareCustomTypeFailure failure(getTest(), type);
failTest(failure);
return *this;
@@ -315,7 +353,7 @@ MockActualCall& MockCheckedActualCall::withOutputParameterOfType(const SimpleStr
addOutputParameter(name, type, output);
MockNamedValue outputParameter(name);
- outputParameter.setObjectPointer(type, output);
+ outputParameter.setConstObjectPointer(type, output);
checkOutputParameter(outputParameter);
return *this;
@@ -333,24 +371,34 @@ bool MockCheckedActualCall::hasFailed() const
void MockCheckedActualCall::checkExpectations()
{
- if (state_ != CALL_IN_PROGRESS)
- {
- unfulfilledExpectations_.resetExpectations();
+ if(expectationsChecked_) {
+ return;
+ }
+
+ expectationsChecked_ = true;
+
+ if (state_ != CALL_IN_PROGRESS) {
+ if(state_ == CALL_SUCCEED) {
+ matchingExpectation_->callWasMade(callOrder_);
+ }
+ potentiallyMatchingExpectations_.resetActualCallMatchingState();
return;
}
- if (! unfulfilledExpectations_.hasUnfulfilledExpectations())
- FAIL("Actual call is in progress. Checking expectations. But no unfulfilled expectations. Cannot happen.") // LCOV_EXCL_LINE
+ if (potentiallyMatchingExpectations_.hasFinalizedMatchingExpectations())
+ FAIL("Actual call is in progress, but there are finalized matching expectations when checking expectations. This cannot happen."); // LCOV_EXCL_LINE
- fulfilledExpectation_ = unfulfilledExpectations_.removeOneFulfilledExpectationWithIgnoredParameters();
- if (fulfilledExpectation_) {
+ matchingExpectation_ = potentiallyMatchingExpectations_.removeFirstMatchingExpectation();
+ if (matchingExpectation_) {
+ matchingExpectation_->finalizeActualCallMatch();
callHasSucceeded();
- unfulfilledExpectations_.resetExpectations();
+ matchingExpectation_->callWasMade(callOrder_);
+ potentiallyMatchingExpectations_.resetActualCallMatchingState();
return;
}
- if (unfulfilledExpectations_.hasUnfulfilledExpectationsBecauseOfMissingParameters()) {
- MockExpectedParameterDidntHappenFailure failure(getTest(), getName(), allExpectations_);
+ if (potentiallyMatchingExpectations_.hasUnmatchingExpectationsBecauseOfMissingParameters()) {
+ MockExpectedParameterDidntHappenFailure failure(getTest(), getName(), allExpectations_, potentiallyMatchingExpectations_);
failTest(failure);
}
else {
@@ -367,8 +415,8 @@ void MockCheckedActualCall::setState(ActualCallState state)
MockNamedValue MockCheckedActualCall::returnValue()
{
checkExpectations();
- if (fulfilledExpectation_)
- return fulfilledExpectation_->returnValue();
+ if (matchingExpectation_)
+ return matchingExpectation_->returnValue();
return MockNamedValue("no return value");
}
@@ -424,6 +472,64 @@ long int MockCheckedActualCall::returnLongIntValueOrDefault(long int default_val
return returnLongIntValue();
}
+#if CPPUTEST_USE_LONG_LONG
+
+cpputest_ulonglong MockCheckedActualCall::returnUnsignedLongLongIntValue()
+{
+ return returnValue().getUnsignedLongLongIntValue();
+}
+
+cpputest_ulonglong MockCheckedActualCall::returnUnsignedLongLongIntValueOrDefault(cpputest_ulonglong default_value)
+{
+ if (!hasReturnValue()) {
+ return default_value;
+ }
+ return returnUnsignedLongLongIntValue();
+}
+
+cpputest_longlong MockCheckedActualCall::returnLongLongIntValue()
+{
+ return returnValue().getLongLongIntValue();
+}
+
+cpputest_longlong MockCheckedActualCall::returnLongLongIntValueOrDefault(cpputest_longlong default_value)
+{
+ if (!hasReturnValue()) {
+ return default_value;
+ }
+ return returnLongLongIntValue();
+}
+
+#else
+
+cpputest_ulonglong MockCheckedActualCall::returnUnsignedLongLongIntValue()
+{
+ FAIL("Unsigned Long Long type is not supported");
+ cpputest_ulonglong ret = {};
+ return ret;
+}
+
+cpputest_ulonglong MockCheckedActualCall::returnUnsignedLongLongIntValueOrDefault(cpputest_ulonglong default_value)
+{
+ FAIL("Unsigned Long Long type is not supported");
+ return default_value;
+}
+
+cpputest_longlong MockCheckedActualCall::returnLongLongIntValue()
+{
+ FAIL("Long Long type is not supported");
+ cpputest_longlong ret = {};
+ return ret;
+}
+
+cpputest_longlong MockCheckedActualCall::returnLongLongIntValueOrDefault(cpputest_longlong default_value)
+{
+ FAIL("Long Long type is not supported");
+ return default_value;
+}
+
+#endif
+
double MockCheckedActualCall::returnDoubleValue()
{
return returnValue().getDoubleValue();
@@ -509,19 +615,27 @@ bool MockCheckedActualCall::hasReturnValue()
MockActualCall& MockCheckedActualCall::onObject(const void* objectPtr)
{
- callIsInProgress();
+ if(hasFailed()) {
+ return *this;
+ }
- unfulfilledExpectations_.onlyKeepExpectationsOnObject(objectPtr);
+ // Currently matching expectations are not discarded because the passed object
+ // is ignored if not specifically set in the expectation
- if (unfulfilledExpectations_.isEmpty()) {
+ potentiallyMatchingExpectations_.onlyKeepExpectationsOnObject(objectPtr);
+
+ if ((!matchingExpectation_) && potentiallyMatchingExpectations_.isEmpty()) {
MockUnexpectedObjectFailure failure(getTest(), getName(), objectPtr, allExpectations_);
failTest(failure);
return *this;
}
- unfulfilledExpectations_.wasPassedToObject();
+ potentiallyMatchingExpectations_.wasPassedToObject();
+
+ if (!matchingExpectation_) {
+ completeCallWhenMatchIsFound();
+ }
- finalizeCallWhenFulfilled();
return *this;
}
@@ -529,7 +643,7 @@ void MockCheckedActualCall::addOutputParameter(const SimpleString& name, const S
{
MockOutputParametersListNode* newNode = new MockOutputParametersListNode(name, type, ptr);
- if (outputParameterExpectations_ == NULL)
+ if (outputParameterExpectations_ == NULLPTR)
outputParameterExpectations_ = newNode;
else {
MockOutputParametersListNode* lastNode = outputParameterExpectations_;
@@ -541,7 +655,7 @@ void MockCheckedActualCall::addOutputParameter(const SimpleString& name, const S
void MockCheckedActualCall::cleanUpOutputParameterList()
{
MockOutputParametersListNode* current = outputParameterExpectations_;
- MockOutputParametersListNode* toBeDeleted = NULL;
+ MockOutputParametersListNode* toBeDeleted = NULLPTR;
while (current) {
toBeDeleted = current;
@@ -566,7 +680,7 @@ MockActualCall& MockActualCallTrace::withName(const SimpleString& name)
return *this;
}
-MockActualCall& MockActualCallTrace::withCallOrder(int callOrder)
+MockActualCall& MockActualCallTrace::withCallOrder(unsigned int callOrder)
{
traceBuffer_ += " withCallOrder:";
traceBuffer_ += StringFrom(callOrder);
@@ -590,31 +704,63 @@ MockActualCall& MockActualCallTrace::withBoolParameter(const SimpleString& name,
MockActualCall& MockActualCallTrace::withUnsignedIntParameter(const SimpleString& name, unsigned int value)
{
addParameterName(name);
- traceBuffer_ += StringFrom(value);
+ traceBuffer_ += StringFrom(value) + " " + BracketsFormattedHexStringFrom(value);
return *this;
}
MockActualCall& MockActualCallTrace::withIntParameter(const SimpleString& name, int value)
{
addParameterName(name);
- traceBuffer_ += StringFrom(value);
+ traceBuffer_ += StringFrom(value) + " " + BracketsFormattedHexStringFrom(value);
return *this;
}
MockActualCall& MockActualCallTrace::withUnsignedLongIntParameter(const SimpleString& name, unsigned long int value)
{
addParameterName(name);
- traceBuffer_ += StringFrom(value);
+ traceBuffer_ += StringFrom(value) + " " + BracketsFormattedHexStringFrom(value);
return *this;
}
MockActualCall& MockActualCallTrace::withLongIntParameter(const SimpleString& name, long int value)
{
addParameterName(name);
- traceBuffer_ += StringFrom(value);
+ traceBuffer_ += StringFrom(value) + " " + BracketsFormattedHexStringFrom(value);
return *this;
}
+#if CPPUTEST_USE_LONG_LONG
+
+MockActualCall& MockActualCallTrace::withUnsignedLongLongIntParameter(const SimpleString& name, cpputest_ulonglong value)
+{
+ addParameterName(name);
+ traceBuffer_ += StringFrom(value) + " " + BracketsFormattedHexStringFrom(value);
+ return *this;
+}
+
+MockActualCall& MockActualCallTrace::withLongLongIntParameter(const SimpleString& name, cpputest_longlong value)
+{
+ addParameterName(name);
+ traceBuffer_ += StringFrom(value) + " " + BracketsFormattedHexStringFrom(value);
+ return *this;
+}
+
+#else
+
+MockActualCall& MockActualCallTrace::withUnsignedLongLongIntParameter(const SimpleString&, cpputest_ulonglong)
+{
+ FAIL("Unsigned Long Long type is not supported");
+ return *this;
+}
+
+MockActualCall& MockActualCallTrace::withLongLongIntParameter(const SimpleString&, cpputest_longlong)
+{
+ FAIL("Long Long type is not supported");
+ return *this;
+}
+
+#endif
+
MockActualCall& MockActualCallTrace::withDoubleParameter(const SimpleString& name, double value)
{
addParameterName(name);
@@ -709,9 +855,63 @@ unsigned long int MockActualCallTrace::returnUnsignedLongIntValueOrDefault(unsig
long int MockActualCallTrace::returnLongIntValueOrDefault(long int)
{
- return returnLongIntValue();
+ return 0;
}
+#if CPPUTEST_USE_LONG_LONG
+
+cpputest_longlong MockActualCallTrace::returnLongLongIntValue()
+{
+ return 0;
+}
+
+cpputest_ulonglong MockActualCallTrace::returnUnsignedLongLongIntValue()
+{
+ return 0;
+}
+
+cpputest_ulonglong MockActualCallTrace::returnUnsignedLongLongIntValueOrDefault(cpputest_ulonglong)
+{
+ return 0;
+}
+
+cpputest_longlong MockActualCallTrace::returnLongLongIntValueOrDefault(cpputest_longlong)
+{
+ return 0;
+}
+
+#else
+
+cpputest_longlong MockActualCallTrace::returnLongLongIntValue()
+{
+ FAIL("Long Long type is not supported");
+ cpputest_longlong ret = {};
+ return ret;
+}
+
+cpputest_ulonglong MockActualCallTrace::returnUnsignedLongLongIntValue()
+{
+ FAIL("Unsigned Long Long type is not supported");
+ cpputest_ulonglong ret = {};
+ return ret;
+}
+
+cpputest_ulonglong MockActualCallTrace::returnUnsignedLongLongIntValueOrDefault(cpputest_ulonglong)
+{
+ FAIL("Unsigned Long Long type is not supported");
+ cpputest_ulonglong ret = {};
+ return ret;
+}
+
+cpputest_longlong MockActualCallTrace::returnLongLongIntValueOrDefault(cpputest_longlong)
+{
+ FAIL("Long Long type is not supported");
+ cpputest_longlong ret = {};
+ return ret;
+}
+
+#endif
+
bool MockActualCallTrace::returnBoolValue()
{
return false;
@@ -744,17 +944,17 @@ unsigned int MockActualCallTrace::returnUnsignedIntValue()
void * MockActualCallTrace::returnPointerValue()
{
- return NULL;
+ return NULLPTR;
}
const void * MockActualCallTrace::returnConstPointerValue()
{
- return NULL;
+ return NULLPTR;
}
void (*MockActualCallTrace::returnFunctionPointerValue())()
{
- return NULL;
+ return NULLPTR;
}
const void * MockActualCallTrace::returnConstPointerValueOrDefault(const void *)
@@ -809,10 +1009,19 @@ const char* MockActualCallTrace::getTraceOutput()
return traceBuffer_.asCharString();
}
+MockActualCallTrace* MockActualCallTrace::instance_ = NULLPTR;
+
MockActualCallTrace& MockActualCallTrace::instance()
{
- static MockActualCallTrace call;
- return call;
+ if (instance_ == NULLPTR)
+ instance_ = new MockActualCallTrace;
+ return *instance_;
+}
+
+void MockActualCallTrace::clearInstance()
+{
+ delete instance_;
+ instance_ = NULLPTR;
}
MockIgnoredActualCall& MockIgnoredActualCall::instance()
diff --git a/src/CppUTestExt/MockExpectedCall.cpp b/src/CppUTestExt/MockExpectedCall.cpp
index e9f3c96d0..2e11e7385 100644
--- a/src/CppUTestExt/MockExpectedCall.cpp
+++ b/src/CppUTestExt/MockExpectedCall.cpp
@@ -13,7 +13,7 @@
* 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 EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''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 BE LIABLE FOR ANY
@@ -52,7 +52,20 @@ SimpleString MockCheckedExpectedCall::getName() const
}
MockCheckedExpectedCall::MockCheckedExpectedCall()
- : ignoreOtherParameters_(false), parametersWereIgnored_(false), callOrder_(0), expectedCallOrder_(NO_EXPECTED_CALL_ORDER), outOfOrder_(true), returnValue_(""), objectPtr_(NULL), wasPassedToObject_(true)
+ : ignoreOtherParameters_(false), isActualCallMatchFinalized_(false),
+ initialExpectedCallOrder_(NO_EXPECTED_CALL_ORDER), finalExpectedCallOrder_(NO_EXPECTED_CALL_ORDER),
+ outOfOrder_(false), returnValue_(""), objectPtr_(NULLPTR), isSpecificObjectExpected_(false), wasPassedToObject_(true),
+ actualCalls_(0), expectedCalls_(1)
+{
+ inputParameters_ = new MockNamedValueList();
+ outputParameters_ = new MockNamedValueList();
+}
+
+MockCheckedExpectedCall::MockCheckedExpectedCall(unsigned int numCalls)
+ : ignoreOtherParameters_(false), isActualCallMatchFinalized_(false),
+ initialExpectedCallOrder_(NO_EXPECTED_CALL_ORDER), finalExpectedCallOrder_(NO_EXPECTED_CALL_ORDER),
+ outOfOrder_(false), returnValue_(""), objectPtr_(NULLPTR), isSpecificObjectExpected_(false), wasPassedToObject_(true),
+ actualCalls_(0), expectedCalls_(numCalls)
{
inputParameters_ = new MockNamedValueList();
outputParameters_ = new MockNamedValueList();
@@ -69,7 +82,6 @@ MockCheckedExpectedCall::~MockCheckedExpectedCall()
MockExpectedCall& MockCheckedExpectedCall::withName(const SimpleString& name)
{
setName(name);
- callOrder_ = NOT_CALLED_YET;
return *this;
}
@@ -113,6 +125,40 @@ MockExpectedCall& MockCheckedExpectedCall::withUnsignedLongIntParameter(const Si
return *this;
}
+#if CPPUTEST_USE_LONG_LONG
+
+MockExpectedCall& MockCheckedExpectedCall::withLongLongIntParameter(const SimpleString& name, cpputest_longlong value)
+{
+ MockNamedValue* newParameter = new MockExpectedFunctionParameter(name);
+ inputParameters_->add(newParameter);
+ newParameter->setValue(value);
+ return *this;
+}
+
+MockExpectedCall& MockCheckedExpectedCall::withUnsignedLongLongIntParameter(const SimpleString& name, cpputest_ulonglong value)
+{
+ MockNamedValue* newParameter = new MockExpectedFunctionParameter(name);
+ inputParameters_->add(newParameter);
+ newParameter->setValue(value);
+ return *this;
+}
+
+#else
+
+MockExpectedCall& MockCheckedExpectedCall::withLongLongIntParameter(const SimpleString&, cpputest_longlong)
+{
+ FAIL("Long Long type is not supported");
+ return *this;
+}
+
+MockExpectedCall& MockCheckedExpectedCall::withUnsignedLongLongIntParameter(const SimpleString&, cpputest_ulonglong)
+{
+ FAIL("Unsigned Long Long type is not supported");
+ return *this;
+}
+
+#endif
+
MockExpectedCall& MockCheckedExpectedCall::withDoubleParameter(const SimpleString& name, double value)
{
MockNamedValue* newParameter = new MockExpectedFunctionParameter(name);
@@ -121,6 +167,14 @@ MockExpectedCall& MockCheckedExpectedCall::withDoubleParameter(const SimpleStrin
return *this;
}
+MockExpectedCall& MockCheckedExpectedCall::withDoubleParameter(const SimpleString& name, double value, double tolerance)
+{
+ MockNamedValue* newParameter = new MockExpectedFunctionParameter(name);
+ inputParameters_->add(newParameter);
+ newParameter->setValue(value, tolerance);
+ return *this;
+}
+
MockExpectedCall& MockCheckedExpectedCall::withStringParameter(const SimpleString& name, const char* value)
{
MockNamedValue* newParameter = new MockExpectedFunctionParameter(name);
@@ -165,7 +219,7 @@ MockExpectedCall& MockCheckedExpectedCall::withParameterOfType(const SimpleStrin
{
MockNamedValue* newParameter = new MockExpectedFunctionParameter(name);
inputParameters_->add(newParameter);
- newParameter->setObjectPointer(type, value);
+ newParameter->setConstObjectPointer(type, value);
return *this;
}
@@ -182,26 +236,31 @@ MockExpectedCall& MockCheckedExpectedCall::withOutputParameterOfTypeReturning(co
{
MockNamedValue* newParameter = new MockExpectedFunctionParameter(name);
outputParameters_->add(newParameter);
- newParameter->setObjectPointer(type, value);
+ newParameter->setConstObjectPointer(type, value);
return *this;
}
+MockExpectedCall& MockCheckedExpectedCall::withUnmodifiedOutputParameter(const SimpleString& name)
+{
+ return withOutputParameterReturning(name, NULLPTR, 0);
+}
+
SimpleString MockCheckedExpectedCall::getInputParameterType(const SimpleString& name)
{
MockNamedValue * p = inputParameters_->getValueByName(name);
- return (p) ? p->getType() : "";
+ return (p) ? p->getType() : StringFrom("");
}
bool MockCheckedExpectedCall::hasInputParameterWithName(const SimpleString& name)
{
MockNamedValue * p = inputParameters_->getValueByName(name);
- return p != NULL;
+ return p != NULLPTR;
}
bool MockCheckedExpectedCall::hasOutputParameterWithName(const SimpleString& name)
{
MockNamedValue * p = outputParameters_->getValueByName(name);
- return p != NULL;
+ return p != NULLPTR;
}
MockNamedValue MockCheckedExpectedCall::getInputParameter(const SimpleString& name)
@@ -216,25 +275,18 @@ MockNamedValue MockCheckedExpectedCall::getOutputParameter(const SimpleString& n
return (p) ? *p : MockNamedValue("");
}
-bool MockCheckedExpectedCall::areParametersFulfilled()
+bool MockCheckedExpectedCall::areParametersMatchingActualCall()
{
MockNamedValueListNode* p;
for (p = inputParameters_->begin(); p; p = p->next())
- if (! item(p)->isFulfilled())
+ if (! item(p)->isMatchingActualCall())
return false;
for (p = outputParameters_->begin(); p; p = p->next())
- if (! item(p)->isFulfilled())
+ if (! item(p)->isMatchingActualCall())
return false;
return true;
}
-bool MockCheckedExpectedCall::areIgnoredParametersFulfilled()
-{
- if (ignoreOtherParameters_)
- return parametersWereIgnored_;
- return true;
-}
-
MockExpectedCall& MockCheckedExpectedCall::ignoreOtherParameters()
{
ignoreOtherParameters_ = true;
@@ -243,29 +295,39 @@ MockExpectedCall& MockCheckedExpectedCall::ignoreOtherParameters()
bool MockCheckedExpectedCall::isFulfilled()
{
- return isFulfilledWithoutIgnoredParameters() && areIgnoredParametersFulfilled();
+ return (actualCalls_ == expectedCalls_);
}
-bool MockCheckedExpectedCall::isFulfilledWithoutIgnoredParameters()
+bool MockCheckedExpectedCall::canMatchActualCalls()
{
- return callOrder_ != NOT_CALLED_YET && areParametersFulfilled() && wasPassedToObject_;
+ return (actualCalls_ < expectedCalls_);
}
+bool MockCheckedExpectedCall::isMatchingActualCallAndFinalized()
+{
+ return isMatchingActualCall() && (!ignoreOtherParameters_ || isActualCallMatchFinalized_);
+}
+
+bool MockCheckedExpectedCall::isMatchingActualCall()
+{
+ return areParametersMatchingActualCall() && wasPassedToObject_;
+}
-void MockCheckedExpectedCall::callWasMade(int callOrder)
+void MockCheckedExpectedCall::callWasMade(unsigned int callOrder)
{
- callOrder_ = callOrder;
- if (expectedCallOrder_ == NO_EXPECTED_CALL_ORDER)
- outOfOrder_ = false;
- else if (callOrder_ == expectedCallOrder_)
- outOfOrder_ = false;
- else
+ actualCalls_++;
+
+ if ( (initialExpectedCallOrder_ != NO_EXPECTED_CALL_ORDER) &&
+ ((callOrder < initialExpectedCallOrder_) || (callOrder > finalExpectedCallOrder_)) ) {
outOfOrder_ = true;
+ }
+
+ resetActualCallMatchingState();
}
-void MockCheckedExpectedCall::parametersWereIgnored()
+void MockCheckedExpectedCall::finalizeActualCallMatch()
{
- parametersWereIgnored_ = true;
+ isActualCallMatchFinalized_ = true;
}
@@ -274,23 +336,24 @@ void MockCheckedExpectedCall::wasPassedToObject()
wasPassedToObject_ = true;
}
-void MockCheckedExpectedCall::resetExpectation()
+void MockCheckedExpectedCall::resetActualCallMatchingState()
{
- callOrder_ = NOT_CALLED_YET;
- wasPassedToObject_ = (objectPtr_ == NULL);
+ wasPassedToObject_ = !isSpecificObjectExpected_;
+ isActualCallMatchFinalized_ = false;
+
MockNamedValueListNode* p;
for (p = inputParameters_->begin(); p; p = p->next())
- item(p)->setFulfilled(false);
+ item(p)->setMatchesActualCall(false);
for (p = outputParameters_->begin(); p; p = p->next())
- item(p)->setFulfilled(false);
+ item(p)->setMatchesActualCall(false);
}
void MockCheckedExpectedCall::inputParameterWasPassed(const SimpleString& name)
{
for (MockNamedValueListNode* p = inputParameters_->begin(); p; p = p->next()) {
if (p->getName() == name)
- item(p)->setFulfilled(true);
+ item(p)->setMatchesActualCall(true);
}
}
@@ -298,14 +361,14 @@ void MockCheckedExpectedCall::outputParameterWasPassed(const SimpleString& name)
{
for (MockNamedValueListNode* p = outputParameters_->begin(); p; p = p->next()) {
if (p->getName() == name)
- item(p)->setFulfilled(true);
+ item(p)->setMatchesActualCall(true);
}
}
SimpleString MockCheckedExpectedCall::getInputParameterValueString(const SimpleString& name)
{
MockNamedValue * p = inputParameters_->getValueByName(name);
- return (p) ? StringFrom(*p) : "failed";
+ return (p) ? StringFrom(*p) : StringFrom("failed");
}
bool MockCheckedExpectedCall::hasInputParameter(const MockNamedValue& parameter)
@@ -323,39 +386,46 @@ bool MockCheckedExpectedCall::hasOutputParameter(const MockNamedValue& parameter
SimpleString MockCheckedExpectedCall::callToString()
{
SimpleString str;
- if (objectPtr_)
+ if (isSpecificObjectExpected_)
str = StringFromFormat("(object address: %p)::", objectPtr_);
str += getName();
str += " -> ";
- if (expectedCallOrder_ != NO_EXPECTED_CALL_ORDER) {
- str += StringFromFormat("expected call order: <%d> -> ", expectedCallOrder_);
+ if (initialExpectedCallOrder_ != NO_EXPECTED_CALL_ORDER) {
+ if (initialExpectedCallOrder_ == finalExpectedCallOrder_) {
+ str += StringFromFormat("expected call order: <%u> -> ", initialExpectedCallOrder_);
+ } else {
+ str += StringFromFormat("expected calls order: <%u..%u> -> ", initialExpectedCallOrder_, finalExpectedCallOrder_);
+ }
}
- if (inputParameters_->begin() == NULL && outputParameters_->begin() == NULL) {
+ if (inputParameters_->begin() == NULLPTR && outputParameters_->begin() == NULLPTR) {
str += (ignoreOtherParameters_) ? "all parameters ignored" : "no parameters";
- return str;
- }
+ } else {
+ MockNamedValueListNode* p;
- MockNamedValueListNode* p;
+ for (p = inputParameters_->begin(); p; p = p->next()) {
+ str += StringFromFormat("%s %s: <%s>", p->getType().asCharString(), p->getName().asCharString(), getInputParameterValueString(p->getName()).asCharString());
+ if (p->next()) str += ", ";
+ }
- for (p = inputParameters_->begin(); p; p = p->next()) {
- str += StringFromFormat("%s %s: <%s>", p->getType().asCharString(), p->getName().asCharString(), getInputParameterValueString(p->getName()).asCharString());
- if (p->next()) str += ", ";
- }
+ if (inputParameters_->begin() && outputParameters_->begin())
+ {
+ str += ", ";
+ }
- if (inputParameters_->begin() && outputParameters_->begin())
- {
- str += ", ";
- }
+ for (p = outputParameters_->begin(); p; p = p->next()) {
+ str += StringFromFormat("%s %s: