git subrepo clone git@github.com:compihu/platform-test-f4-ll.git platforms/platform-test-f4-ll
subrepo: subdir: "platforms/platform-test-f4-ll" merged: "bc41134" upstream: origin: "git@github.com:compihu/platform-test-f4-ll.git" branch: "master" commit: "bc41134" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo" commit: "87ee373"
This commit is contained in:
parent
46ce55c6a0
commit
95af4ce0d8
460 changed files with 84105 additions and 0 deletions
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/CommandLineTestRunner.h"
|
||||
#include "CppUTest/TestMemoryAllocator.h"
|
||||
#include "CppUTest/SimpleStringInternalCache.h"
|
||||
|
||||
#define SHOW_MEMORY_REPORT 0
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int returnValue = 0;
|
||||
GlobalSimpleStringCache stringCache;
|
||||
|
||||
{
|
||||
/* These checks are here to make sure assertions outside test runs don't crash */
|
||||
CHECK(true);
|
||||
LONGS_EQUAL(1, 1);
|
||||
|
||||
#if SHOW_MEMORY_REPORT
|
||||
GlobalMemoryAccountant accountant;
|
||||
accountant.start();
|
||||
#endif
|
||||
|
||||
returnValue = CommandLineTestRunner::RunAllTests(ac, av); /* cover alternate method */
|
||||
|
||||
#if SHOW_MEMORY_REPORT
|
||||
accountant.stop();
|
||||
printf("%s", accountant.report().asCharString());
|
||||
#endif
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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 this in the test main to execute these tests
|
||||
IMPORT_TEST_GROUP( Utest);
|
||||
IMPORT_TEST_GROUP( Failure);
|
||||
IMPORT_TEST_GROUP( TestOutput);
|
||||
IMPORT_TEST_GROUP( SimpleString);
|
||||
IMPORT_TEST_GROUP( TestInstaller);
|
||||
IMPORT_TEST_GROUP( NullTest);
|
||||
IMPORT_TEST_GROUP( MemoryLeakWarningTest);
|
||||
IMPORT_TEST_GROUP( TestHarness_c);
|
||||
IMPORT_TEST_GROUP( CommandLineTestRunner);
|
||||
IMPORT_TEST_GROUP( JUnitOutputTest);
|
||||
IMPORT_TEST_GROUP( MemoryLeakDetectorTest);
|
||||
|
||||
/* In allTest.cpp */
|
||||
IMPORT_TEST_GROUP(CheatSheet);
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
#include "CppUTest/StandardCLibrary.h"
|
||||
|
||||
#if CPPUTEST_USE_STD_C_LIB
|
||||
|
||||
#include "AllocLetTestFree.h"
|
||||
|
||||
typedef struct AllocLetTestFreeStruct
|
||||
{
|
||||
int placeHolderForHiddenStructElements;
|
||||
} AllocLetTestFreeStruct;
|
||||
|
||||
AllocLetTestFree AllocLetTestFree_Create(void)
|
||||
{
|
||||
size_t count = 1;
|
||||
AllocLetTestFree self = (AllocLetTestFree)calloc(count, sizeof(AllocLetTestFreeStruct));
|
||||
return self;
|
||||
}
|
||||
|
||||
void AllocLetTestFree_Destroy(AllocLetTestFree self)
|
||||
{
|
||||
AllocLetTestFree no_use = self;
|
||||
self = NULL;
|
||||
self = no_use;
|
||||
(void)self;
|
||||
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
#ifndef D_AllocLetTestFree_H
|
||||
#define D_AllocLetTestFree_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct AllocLetTestFreeStruct * AllocLetTestFree;
|
||||
|
||||
AllocLetTestFree AllocLetTestFree_Create(void);
|
||||
void AllocLetTestFree_Destroy(AllocLetTestFree);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* D_FakeAllocLetTestFree_H */
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
#include "CppUTest/StandardCLibrary.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "AllocLetTestFree.h"
|
||||
}
|
||||
|
||||
#include "CppUTest/TestHarness.h"
|
||||
|
||||
#if CPPUTEST_USE_STD_C_LIB
|
||||
/*
|
||||
* This test makes sure that memory leak malloc macros are forced into .cpp and .c files
|
||||
*/
|
||||
TEST_GROUP(AllocLetTestFree)
|
||||
{
|
||||
AllocLetTestFree allocLetTestFree;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
allocLetTestFree = AllocLetTestFree_Create();
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
AllocLetTestFree_Destroy(allocLetTestFree);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(AllocLetTestFree, Create)
|
||||
{
|
||||
free(allocLetTestFree);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,42 @@
|
|||
#include "AllocationInCFile.h"
|
||||
#include "CppUTest/MemoryLeakDetectorMallocMacros.h"
|
||||
#include "CppUTest/StandardCLibrary.h"
|
||||
|
||||
/* This file is for simulating overloads of malloc */
|
||||
|
||||
char* mallocAllocation()
|
||||
{
|
||||
return (char*) malloc(10UL);
|
||||
}
|
||||
|
||||
char* strdupAllocation()
|
||||
{
|
||||
#ifdef CPPUTEST_USE_STRDUP_MACROS
|
||||
return strdup("0123456789");
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
char* strndupAllocation()
|
||||
{
|
||||
#ifdef CPPUTEST_USE_STRDUP_MACROS
|
||||
return strndup("0123456789", 10);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void freeAllocation(void* memory)
|
||||
{
|
||||
free(memory);
|
||||
}
|
||||
|
||||
#undef free
|
||||
|
||||
void freeAllocationWithoutMacro(void* memory)
|
||||
{
|
||||
free(memory);
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef ALLOCATIONINCFILE_H
|
||||
#define ALLOCATIONINCFILE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern char* mallocAllocation(void);
|
||||
extern char* strdupAllocation(void);
|
||||
extern char* strndupAllocation(void);
|
||||
extern void freeAllocation(void* memory);
|
||||
extern void freeAllocationWithoutMacro(void* memory);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
/* This file is for emulating allocations in a C++ file.
|
||||
* It is used simulating the use of the memory leak detector on production code in C++
|
||||
*/
|
||||
#undef new
|
||||
#include "CppUTest/MemoryLeakDetectorNewMacros.h"
|
||||
#include "AllocationInCppFile.h"
|
||||
|
||||
char* newAllocation()
|
||||
{
|
||||
return new char;
|
||||
}
|
||||
|
||||
char* newArrayAllocation()
|
||||
{
|
||||
return new char[100];
|
||||
}
|
||||
|
||||
#undef new
|
||||
|
||||
char* newAllocationWithoutMacro()
|
||||
{
|
||||
return new char;
|
||||
}
|
||||
|
||||
char* newArrayAllocationWithoutMacro()
|
||||
{
|
||||
return new char[100];
|
||||
}
|
||||
|
||||
#if CPPUTEST_USE_STD_CPP_LIB
|
||||
|
||||
ClassThatThrowsAnExceptionInTheConstructor::ClassThatThrowsAnExceptionInTheConstructor()
|
||||
{
|
||||
throw 1;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef ALLOCATIONINCPPFILE_H
|
||||
#define ALLOCATIONINCPPFILE_H
|
||||
|
||||
char* newAllocation();
|
||||
char* newArrayAllocation();
|
||||
|
||||
char* newAllocationWithoutMacro();
|
||||
char* newArrayAllocationWithoutMacro();
|
||||
|
||||
#if CPPUTEST_USE_STD_CPP_LIB
|
||||
|
||||
class ClassThatThrowsAnExceptionInTheConstructor
|
||||
{
|
||||
public:
|
||||
ClassThatThrowsAnExceptionInTheConstructor() _no_return_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,61 @@
|
|||
set(CppUTestTests_src
|
||||
AllTests.cpp
|
||||
SetPluginTest.cpp
|
||||
CheatSheetTest.cpp
|
||||
SimpleStringTest.cpp
|
||||
SimpleStringCacheTest.cpp
|
||||
CompatabilityTests.cpp
|
||||
CommandLineArgumentsTest.cpp
|
||||
TestFailureTest.cpp
|
||||
TestFailureNaNTest.cpp
|
||||
CommandLineTestRunnerTest.cpp
|
||||
TestFilterTest.cpp
|
||||
TestHarness_cTest.cpp
|
||||
JUnitOutputTest.cpp
|
||||
TestHarness_cTestCFile.c
|
||||
DummyMemoryLeakDetector.cpp
|
||||
MemoryLeakDetectorTest.cpp
|
||||
TestInstallerTest.cpp
|
||||
AllocLetTestFree.c
|
||||
MemoryOperatorOverloadTest.cpp
|
||||
TestMemoryAllocatorTest.cpp
|
||||
MemoryLeakWarningTest.cpp
|
||||
TestOutputTest.cpp
|
||||
AllocLetTestFreeTest.cpp
|
||||
TestRegistryTest.cpp
|
||||
AllocationInCFile.c
|
||||
PluginTest.cpp
|
||||
TestResultTest.cpp
|
||||
PreprocessorTest.cpp
|
||||
TestUTestMacro.cpp
|
||||
TestUTestStringMacro.cpp
|
||||
AllocationInCppFile.cpp
|
||||
UtestTest.cpp
|
||||
SimpleMutexTest.cpp
|
||||
UtestPlatformTest.cpp
|
||||
TeamCityOutputTest.cpp
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4723")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4723")
|
||||
endif (MSVC)
|
||||
|
||||
if (MINGW)
|
||||
find_package (Threads REQUIRED)
|
||||
set(THREAD_LIB "pthread")
|
||||
endif (MINGW)
|
||||
|
||||
if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "OpenBSD")
|
||||
set (THREADS_HAVE_PTHREAD_ARG 1)
|
||||
find_package (Threads REQUIRED)
|
||||
set (THREAD_LIB "pthread")
|
||||
endif ()
|
||||
|
||||
add_executable(CppUTestTests ${CppUTestTests_src})
|
||||
cpputest_normalize_test_output_location(CppUTestTests)
|
||||
target_link_libraries(CppUTestTests CppUTest ${THREAD_LIB})
|
||||
|
||||
if (TESTS_BUILD_DISCOVER)
|
||||
cpputest_buildtime_discover_tests(CppUTestTests)
|
||||
endif()
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
static void (*real_one) ();
|
||||
static void stub(){}
|
||||
|
||||
/* in CheatSheetTest.cpp */
|
||||
#include "CppUTest/TestHarness.h"
|
||||
|
||||
/* Declare TestGroup with name CheatSheet */
|
||||
TEST_GROUP(CheatSheet)
|
||||
{
|
||||
/* declare a setup method for the test group. Optional. */
|
||||
void setup() _override
|
||||
{
|
||||
/* Set method real_one to stub. Automatically restore in teardown */
|
||||
UT_PTR_SET(real_one, stub);
|
||||
}
|
||||
|
||||
/* Declare a teardown method for the test group. Optional */
|
||||
void teardown() _override
|
||||
{
|
||||
}
|
||||
}; /* Do not forget semicolumn */
|
||||
|
||||
/* Declare one test within the test group */
|
||||
TEST(CheatSheet, TestName)
|
||||
{
|
||||
/* Check two longs are equal */
|
||||
LONGS_EQUAL(1, 1);
|
||||
|
||||
/* Check a condition */
|
||||
CHECK(true == true);
|
||||
|
||||
/* Check a string */
|
||||
STRCMP_EQUAL("HelloWorld", "HelloWorld");
|
||||
}
|
|
@ -0,0 +1,552 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/CommandLineArguments.h"
|
||||
#include "CppUTest/TestRegistry.h"
|
||||
|
||||
class OptionsPlugin: public TestPlugin
|
||||
{
|
||||
public:
|
||||
OptionsPlugin(const SimpleString& name) :
|
||||
TestPlugin(name)
|
||||
{
|
||||
}
|
||||
~OptionsPlugin() _destructor_override
|
||||
{
|
||||
}
|
||||
bool parseArguments(int /*ac*/, const char *const * /*av*/, int /*index*/) _override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_GROUP(CommandLineArguments)
|
||||
{
|
||||
CommandLineArguments* args;
|
||||
OptionsPlugin* plugin;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
plugin = new OptionsPlugin("options");
|
||||
args = NULLPTR;
|
||||
}
|
||||
void teardown() _override
|
||||
{
|
||||
delete args;
|
||||
delete plugin;
|
||||
}
|
||||
|
||||
bool newArgumentParser(int argc, const char *const *argv)
|
||||
{
|
||||
args = new CommandLineArguments(argc, argv);
|
||||
return args->parse(plugin);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(CommandLineArguments, Create)
|
||||
{
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, verboseSetMultipleParameters)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-v" };
|
||||
CHECK(newArgumentParser(2, argv));
|
||||
CHECK(args->isVerbose());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, veryVerbose)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-vv" };
|
||||
CHECK(newArgumentParser(2, argv));
|
||||
CHECK(args->isVeryVerbose());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setColor)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-c" };
|
||||
CHECK(newArgumentParser(2, argv));
|
||||
CHECK(args->isColor());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, repeatSet)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-r3" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
LONGS_EQUAL(3, args->getRepeatCount());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, repeatSetDifferentParameter)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-r", "4" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
LONGS_EQUAL(4, args->getRepeatCount());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, repeatSetDefaultsToTwoAndShuffleDisabled)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-r" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
LONGS_EQUAL(2, args->getRepeatCount());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, reverseEnabled)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-b" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK_TRUE(args->isReversing());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, shuffleDisabledByDefault)
|
||||
{
|
||||
int argc = 1;
|
||||
const char* argv[] = { "tests.exe" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK_FALSE(args->isShuffling());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, shuffleEnabled)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-s" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK_TRUE(args->isShuffling());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, shuffleWithSeedZeroIsOk)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-s0" };
|
||||
CHECK_FALSE(newArgumentParser(argc, argv));
|
||||
CHECK_EQUAL(0, args->getShuffleSeed());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, shuffleEnabledSpecificSeedCase1)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-s999"};
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK_EQUAL(999, args->getShuffleSeed());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, shuffleEnabledSpecificSeedCase2)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-s 888"};
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK_EQUAL(888, args->getShuffleSeed());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, shuffleEnabledSpecificSeedCase3)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-s", "777"};
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK_EQUAL(777, args->getShuffleSeed());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, shuffleBeforeDoesNotDisturbOtherSwitch)
|
||||
{
|
||||
int argc = 4;
|
||||
const char* argv[] = { "tests.exe", "-s", "-sg", "group" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestFilter groupFilter("group");
|
||||
groupFilter.strictMatching();
|
||||
CHECK_EQUAL(groupFilter, *args->getGroupFilters());
|
||||
CHECK_TRUE(args->isShuffling());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, runningTestsInSeperateProcesses)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-p" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK(args->runTestsInSeperateProcess());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setGroupFilter)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-g", "group" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK_EQUAL(TestFilter("group"), *args->getGroupFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setCompleteGroupDotNameFilterInvalidArgument)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-t", "groupname" };
|
||||
CHECK_FALSE(newArgumentParser(argc, argv));
|
||||
}
|
||||
TEST(CommandLineArguments, setCompleteGroupDotNameFilter)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-t", "group.name" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK_EQUAL(TestFilter("group"), *args->getGroupFilters());
|
||||
CHECK_EQUAL(TestFilter("name"), *args->getNameFilters());
|
||||
}
|
||||
|
||||
|
||||
TEST(CommandLineArguments, setGroupFilterSameParameter)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-ggroup" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK_EQUAL(TestFilter("group"), *args->getGroupFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setStrictGroupFilter)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-sg", "group" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestFilter groupFilter("group");
|
||||
groupFilter.strictMatching();
|
||||
CHECK_EQUAL(groupFilter, *args->getGroupFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setStrictGroupFilterSameParameter)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-sggroup" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestFilter groupFilter("group");
|
||||
groupFilter.strictMatching();
|
||||
CHECK_EQUAL(groupFilter, *args->getGroupFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setExcludeGroupFilter)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-xg", "group" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestFilter groupFilter("group");
|
||||
groupFilter.invertMatching();
|
||||
CHECK_EQUAL(groupFilter, *args->getGroupFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setExcludeGroupFilterSameParameter)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-xggroup" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestFilter groupFilter("group");
|
||||
groupFilter.invertMatching();
|
||||
CHECK_EQUAL(groupFilter, *args->getGroupFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setExcludeStrictGroupFilter)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-xsg", "group" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestFilter groupFilter("group");
|
||||
groupFilter.invertMatching();
|
||||
groupFilter.strictMatching();
|
||||
CHECK_EQUAL(groupFilter, *args->getGroupFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setExcludeStrictGroupFilterSameParameter)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-xsggroup" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestFilter groupFilter("group");
|
||||
groupFilter.invertMatching();
|
||||
groupFilter.strictMatching();
|
||||
CHECK_EQUAL(groupFilter, *args->getGroupFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setNameFilter)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-n", "name" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK_EQUAL(TestFilter("name"), *args->getNameFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setNameFilterSameParameter)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-nname" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK_EQUAL(TestFilter("name"), *args->getNameFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setStrictNameFilter)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-sn", "name" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestFilter nameFilter("name");
|
||||
nameFilter.strictMatching();
|
||||
CHECK_EQUAL(nameFilter, *args->getNameFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setStrictNameFilterSameParameter)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-snname" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestFilter nameFilter("name");
|
||||
nameFilter.strictMatching();
|
||||
CHECK_EQUAL(nameFilter, *args->getNameFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setExcludeNameFilter)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-xn", "name" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestFilter nameFilter("name");
|
||||
nameFilter.invertMatching();
|
||||
CHECK_EQUAL(nameFilter, *args->getNameFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setExcludeNameFilterSameParameter)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-xnname" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestFilter nameFilter("name");
|
||||
nameFilter.invertMatching();
|
||||
CHECK_EQUAL(nameFilter, *args->getNameFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setExcludeStrictNameFilter)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-xsn", "name" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestFilter nameFilter("name");
|
||||
nameFilter.invertMatching();
|
||||
nameFilter.strictMatching();
|
||||
CHECK_EQUAL(nameFilter, *args->getNameFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setExcludeStrictNameFilterSameParameter)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-xsnname" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestFilter nameFilter("name");
|
||||
nameFilter.invertMatching();
|
||||
nameFilter.strictMatching();
|
||||
CHECK_EQUAL(nameFilter, *args->getNameFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setTestToRunUsingVerboseOutput)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "TEST(testgroup, testname) - stuff" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
|
||||
TestFilter nameFilter("testname");
|
||||
TestFilter groupFilter("testgroup");
|
||||
nameFilter.strictMatching();
|
||||
groupFilter.strictMatching();
|
||||
CHECK_EQUAL(nameFilter, *args->getNameFilters());
|
||||
CHECK_EQUAL(groupFilter, *args->getGroupFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setTestToRunUsingVerboseOutputOfIgnoreTest)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "IGNORE_TEST(testgroup, testname) - stuff" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
|
||||
TestFilter nameFilter("testname");
|
||||
TestFilter groupFilter("testgroup");
|
||||
nameFilter.strictMatching();
|
||||
groupFilter.strictMatching();
|
||||
CHECK_EQUAL(nameFilter, *args->getNameFilters());
|
||||
CHECK_EQUAL(groupFilter, *args->getGroupFilters());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setNormalOutput)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-onormal" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK(args->isEclipseOutput());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setEclipseOutput)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-oeclipse" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK(args->isEclipseOutput());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setNormalOutputDifferentParameter)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-o", "normal" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK(args->isEclipseOutput());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setJUnitOutputDifferentParameter)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-o", "junit" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK(args->isJUnitOutput());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setTeamCityOutputDifferentParameter)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-o", "teamcity" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK(args->isTeamCityOutput());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setOutputToGarbage)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-o", "garbage" };
|
||||
CHECK(!newArgumentParser(argc, argv));
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setPrintGroups)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-lg" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK(args->isListingTestGroupNames());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setPrintGroupsAndNames)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-ln" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK(args->isListingTestGroupAndCaseNames());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, weirdParamatersReturnsFalse)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-SomethingWeird" };
|
||||
CHECK(!newArgumentParser(argc, argv));
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, printUsage)
|
||||
{
|
||||
STRCMP_EQUAL(
|
||||
"use -h for more extensive help\n"
|
||||
"usage [-h] [-v] [-vv] [-c] [-p] [-lg] [-ln] [-ri] [-r#] [-f]\n"
|
||||
" [-g|sg|xg|xsg groupName]... [-n|sn|xn|xsn testName]... [-t groupName.testName]...\n"
|
||||
" [-b] [-s [randomizerSeed>0]] [\"TEST(groupName, testName)\"]...\n"
|
||||
" [-o{normal, junit, teamcity}] [-k packageName]\n",
|
||||
args->usage());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, helpPrintsTheHelp)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-h" };
|
||||
CHECK(!newArgumentParser(argc, argv));
|
||||
CHECK(args->needHelp());
|
||||
}
|
||||
|
||||
|
||||
TEST(CommandLineArguments, pluginKnowsOption)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-pPluginOption" };
|
||||
TestRegistry::getCurrentRegistry()->installPlugin(plugin);
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestRegistry::getCurrentRegistry()->removePluginByName("options");
|
||||
}
|
||||
|
||||
|
||||
TEST(CommandLineArguments, checkDefaultArguments)
|
||||
{
|
||||
int argc = 1;
|
||||
const char* argv[] = { "tests.exe" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK(!args->isVerbose());
|
||||
LONGS_EQUAL(1, args->getRepeatCount());
|
||||
CHECK(NULLPTR == args->getGroupFilters());
|
||||
CHECK(NULLPTR == args->getNameFilters());
|
||||
CHECK(args->isEclipseOutput());
|
||||
CHECK(SimpleString("") == args->getPackageName());
|
||||
CHECK(!args->isCrashingOnFail());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setPackageName)
|
||||
{
|
||||
int argc = 3;
|
||||
const char* argv[] = { "tests.exe", "-k", "package" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK_EQUAL(SimpleString("package"), args->getPackageName());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, lotsOfGroupsAndTests)
|
||||
{
|
||||
int argc = 10;
|
||||
const char* argv[] = { "tests.exe", "-sggroup1", "-xntest1", "-sggroup2", "-sntest2", "-sntest3", "-sggroup3", "-sntest4", "-sggroup4", "-sntest5" };
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
TestFilter nameFilter("test1");
|
||||
nameFilter.invertMatching();
|
||||
TestFilter groupFilter("group1");
|
||||
groupFilter.strictMatching();
|
||||
CHECK_EQUAL(nameFilter, *args->getNameFilters()->getNext()->getNext()->getNext()->getNext());
|
||||
CHECK_EQUAL(groupFilter, *args->getGroupFilters()->getNext()->getNext()->getNext());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, lastParameterFieldMissing)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-k"};
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK_EQUAL(SimpleString(""), args->getPackageName());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setOptRun)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-ri"};
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK(args->isRunIgnored());
|
||||
}
|
||||
|
||||
TEST(CommandLineArguments, setOptCrashOnFail)
|
||||
{
|
||||
int argc = 2;
|
||||
const char* argv[] = { "tests.exe", "-f"};
|
||||
CHECK(newArgumentParser(argc, argv));
|
||||
CHECK(args->isCrashingOnFail());
|
||||
}
|
|
@ -0,0 +1,455 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/CommandLineTestRunner.h"
|
||||
#include "CppUTest/TestRegistry.h"
|
||||
#include "CppUTest/TestTestingFixture.h"
|
||||
#include "CppUTest/TestPlugin.h"
|
||||
#include "CppUTest/JUnitTestOutput.h"
|
||||
#include "CppUTest/PlatformSpecificFunctions.h"
|
||||
#include "CppUTestExt/MockSupport.h"
|
||||
|
||||
|
||||
class DummyPluginWhichCountsThePlugins : public TestPlugin
|
||||
{
|
||||
public:
|
||||
|
||||
bool returnValue;
|
||||
int amountOfPlugins;
|
||||
|
||||
DummyPluginWhichCountsThePlugins(const SimpleString& name, TestRegistry* registry) :
|
||||
TestPlugin(name), returnValue(true), amountOfPlugins(0), registry_(registry)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool parseArguments(int, const char *const *, int) _override
|
||||
{
|
||||
/* Remove ourselves from the count */
|
||||
amountOfPlugins = registry_->countPlugins() - 1;
|
||||
return returnValue;
|
||||
}
|
||||
private:
|
||||
TestRegistry* registry_;
|
||||
};
|
||||
|
||||
class CommandLineTestRunnerWithStringBufferOutput : public CommandLineTestRunner
|
||||
{
|
||||
public:
|
||||
StringBufferTestOutput* fakeJUnitOutputWhichIsReallyABuffer_;
|
||||
StringBufferTestOutput* fakeConsoleOutputWhichIsReallyABuffer;
|
||||
StringBufferTestOutput* fakeTCOutputWhichIsReallyABuffer;
|
||||
|
||||
CommandLineTestRunnerWithStringBufferOutput(int argc, const char *const *argv, TestRegistry* registry)
|
||||
: CommandLineTestRunner(argc, argv, registry), fakeJUnitOutputWhichIsReallyABuffer_(NULLPTR),
|
||||
fakeConsoleOutputWhichIsReallyABuffer(NULLPTR), fakeTCOutputWhichIsReallyABuffer(NULLPTR)
|
||||
{}
|
||||
|
||||
TestOutput* createConsoleOutput() _override
|
||||
{
|
||||
fakeConsoleOutputWhichIsReallyABuffer = new StringBufferTestOutput;
|
||||
return fakeConsoleOutputWhichIsReallyABuffer;
|
||||
}
|
||||
|
||||
TestOutput* createJUnitOutput(const SimpleString&) _override
|
||||
{
|
||||
fakeJUnitOutputWhichIsReallyABuffer_ = new StringBufferTestOutput;
|
||||
return fakeJUnitOutputWhichIsReallyABuffer_;
|
||||
}
|
||||
|
||||
TestOutput* createTeamCityOutput() _override
|
||||
{
|
||||
fakeTCOutputWhichIsReallyABuffer = new StringBufferTestOutput;
|
||||
return fakeTCOutputWhichIsReallyABuffer;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_GROUP(CommandLineTestRunner)
|
||||
{
|
||||
TestRegistry registry;
|
||||
UtestShell *test1;
|
||||
UtestShell *test2;
|
||||
DummyPluginWhichCountsThePlugins* pluginCountingPlugin;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
test1 = new UtestShell("group1", "test1", "file1", 1);
|
||||
test2 = new UtestShell("group2", "test2", "file2", 2);
|
||||
registry.addTest(test1);
|
||||
pluginCountingPlugin = new DummyPluginWhichCountsThePlugins("PluginCountingPlugin", ®istry);
|
||||
}
|
||||
void teardown() _override
|
||||
{
|
||||
delete pluginCountingPlugin;
|
||||
delete test2;
|
||||
delete test1;
|
||||
}
|
||||
|
||||
SimpleString runAndGetOutput(const int argc, const char* argv[])
|
||||
{
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(argc, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
return commandLineTestRunner.fakeConsoleOutputWhichIsReallyABuffer->getOutput();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(CommandLineTestRunner, OnePluginGetsInstalledDuringTheRunningTheTests)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-psomething"};
|
||||
|
||||
registry.installPlugin(pluginCountingPlugin);
|
||||
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(2, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
registry.removePluginByName("PluginCountingPlugin");
|
||||
|
||||
LONGS_EQUAL(0, registry.countPlugins());
|
||||
LONGS_EQUAL(1, pluginCountingPlugin->amountOfPlugins);
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, NoPluginsAreInstalledAtTheEndOfARunWhenTheArgumentsAreInvalid)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-fdskjnfkds"};
|
||||
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(2, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
|
||||
LONGS_EQUAL(0, registry.countPlugins());
|
||||
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, ReturnsOneWhenTheArgumentsAreInvalid)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-some-invalid=parameter" };
|
||||
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(2, argv, ®istry);
|
||||
int returned = commandLineTestRunner.runAllTestsMain();
|
||||
|
||||
LONGS_EQUAL(1, returned);
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, ReturnsOnePrintsHelpOnHelp)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-h" };
|
||||
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(2, argv, ®istry);
|
||||
int returned = commandLineTestRunner.runAllTestsMain();
|
||||
|
||||
LONGS_EQUAL(1, returned);
|
||||
STRCMP_CONTAINS("Thanks for using CppUTest.", commandLineTestRunner.fakeConsoleOutputWhichIsReallyABuffer->getOutput().asCharString());
|
||||
}
|
||||
|
||||
|
||||
TEST(CommandLineTestRunner, ReturnsZeroWhenNoErrors)
|
||||
{
|
||||
const char* argv[] = { "tests.exe" };
|
||||
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(1, argv, ®istry);
|
||||
int returned = commandLineTestRunner.runAllTestsMain();
|
||||
|
||||
LONGS_EQUAL(0, returned);
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, ReturnsOneWhenNoTestsMatchProvidedFilter)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-g", "NoSuchGroup"};
|
||||
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(3, argv, ®istry);
|
||||
int returned = commandLineTestRunner.runAllTestsMain();
|
||||
|
||||
LONGS_EQUAL(1, returned);
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, TeamcityOutputEnabled)
|
||||
{
|
||||
const char* argv[] = {"tests.exe", "-oteamcity"};
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(2, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
CHECK(commandLineTestRunner.fakeTCOutputWhichIsReallyABuffer != NULLPTR);
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, JunitOutputEnabled)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-ojunit"};
|
||||
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(2, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
CHECK(commandLineTestRunner.fakeJUnitOutputWhichIsReallyABuffer_ != NULLPTR);
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, JunitOutputAndVerboseEnabled)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-ojunit", "-v"};
|
||||
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(3, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
STRCMP_CONTAINS("TEST(group1, test1)", commandLineTestRunner.fakeJUnitOutputWhichIsReallyABuffer_->getOutput().asCharString());
|
||||
STRCMP_CONTAINS("TEST(group1, test1)", commandLineTestRunner.fakeConsoleOutputWhichIsReallyABuffer->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, veryVerboseSetOnOutput)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-vv"};
|
||||
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(2, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
STRCMP_CONTAINS("TEST(group1, test1)", commandLineTestRunner.fakeConsoleOutputWhichIsReallyABuffer->getOutput().asCharString());
|
||||
STRCMP_CONTAINS("destroyTest", commandLineTestRunner.fakeConsoleOutputWhichIsReallyABuffer->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, defaultTestsAreRunInOrderTheyAreInRepository)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-v"};
|
||||
|
||||
registry.addTest(test2);
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(2, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
|
||||
SimpleStringCollection stringCollection;
|
||||
commandLineTestRunner.fakeConsoleOutputWhichIsReallyABuffer->getOutput().split("\n", stringCollection);
|
||||
STRCMP_CONTAINS("test2", stringCollection[0].asCharString());
|
||||
STRCMP_CONTAINS("test1", stringCollection[1].asCharString());
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, testsCanBeRunInReverseOrder)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-v", "-b"};
|
||||
|
||||
registry.addTest(test2);
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(3, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
|
||||
SimpleStringCollection stringCollection;
|
||||
commandLineTestRunner.fakeConsoleOutputWhichIsReallyABuffer->getOutput().split("\n", stringCollection);
|
||||
STRCMP_CONTAINS("test1", stringCollection[0].asCharString());
|
||||
STRCMP_CONTAINS("test2", stringCollection[1].asCharString());
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, listTestGroupNamesShouldWorkProperly)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-lg" };
|
||||
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(2, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
|
||||
STRCMP_CONTAINS("group", commandLineTestRunner.fakeConsoleOutputWhichIsReallyABuffer->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, listTestGroupAndCaseNamesShouldWorkProperly)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-ln" };
|
||||
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(2, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
|
||||
STRCMP_CONTAINS("group1.test1", commandLineTestRunner.fakeConsoleOutputWhichIsReallyABuffer->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, randomShuffleSeedIsPrintedAndRandFuncIsExercised)
|
||||
{
|
||||
// more than 1 item in test list ensures that shuffle algorithm calls rand_()
|
||||
UtestShell *anotherTest = new UtestShell("group", "test2", "file", 1);
|
||||
registry.addTest(anotherTest);
|
||||
|
||||
const char* argv[] = { "tests.exe", "-s"};
|
||||
SimpleString text = runAndGetOutput(2, argv);
|
||||
STRCMP_CONTAINS("shuffling enabled with seed:", text.asCharString());
|
||||
|
||||
delete anotherTest;
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, specificShuffleSeedIsPrintedVerbose)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-s2", "-v"};
|
||||
SimpleString text = runAndGetOutput(3, argv);
|
||||
STRCMP_CONTAINS("shuffling enabled with seed: 2", text.asCharString());
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
typedef PlatformSpecificFile (*FOpenFunc)(const char*, const char*);
|
||||
typedef void (*FPutsFunc)(const char*, PlatformSpecificFile);
|
||||
typedef void (*FCloseFunc)(PlatformSpecificFile);
|
||||
typedef int (*PutcharFunc)(int);
|
||||
}
|
||||
|
||||
struct FakeOutput
|
||||
{
|
||||
FakeOutput() : SaveFOpen(PlatformSpecificFOpen), SaveFPuts(PlatformSpecificFPuts),
|
||||
SaveFClose(PlatformSpecificFClose), SavePutchar(PlatformSpecificPutchar)
|
||||
{
|
||||
installFakes();
|
||||
currentFake = this;
|
||||
}
|
||||
|
||||
~FakeOutput()
|
||||
{
|
||||
currentFake = NULLPTR;
|
||||
restoreOriginals();
|
||||
}
|
||||
|
||||
void installFakes()
|
||||
{
|
||||
PlatformSpecificFOpen = (FOpenFunc)fopen_fake;
|
||||
PlatformSpecificFPuts = (FPutsFunc)fputs_fake;
|
||||
PlatformSpecificFClose = (FCloseFunc)fclose_fake;
|
||||
PlatformSpecificPutchar = (PutcharFunc)putchar_fake;
|
||||
}
|
||||
|
||||
void restoreOriginals()
|
||||
{
|
||||
PlatformSpecificPutchar = SavePutchar;
|
||||
PlatformSpecificFOpen = SaveFOpen;
|
||||
PlatformSpecificFPuts = SaveFPuts;
|
||||
PlatformSpecificFClose = SaveFClose;
|
||||
}
|
||||
|
||||
static PlatformSpecificFile fopen_fake(const char*, const char*)
|
||||
{
|
||||
return (PlatformSpecificFile) NULLPTR;
|
||||
}
|
||||
|
||||
static void fputs_fake(const char* str, PlatformSpecificFile)
|
||||
{
|
||||
currentFake->file += str;
|
||||
}
|
||||
|
||||
static void fclose_fake(PlatformSpecificFile)
|
||||
{
|
||||
}
|
||||
|
||||
static int putchar_fake(int c)
|
||||
{
|
||||
currentFake->console += StringFrom((char)c);
|
||||
return c;
|
||||
}
|
||||
|
||||
SimpleString file;
|
||||
SimpleString console;
|
||||
|
||||
static FakeOutput* currentFake;
|
||||
private:
|
||||
FOpenFunc SaveFOpen;
|
||||
FPutsFunc SaveFPuts;
|
||||
FCloseFunc SaveFClose;
|
||||
PutcharFunc SavePutchar;
|
||||
};
|
||||
|
||||
FakeOutput* FakeOutput::currentFake = NULLPTR;
|
||||
|
||||
TEST(CommandLineTestRunner, realJunitOutputShouldBeCreatedAndWorkProperly)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-ojunit", "-v", "-kpackage", };
|
||||
|
||||
FakeOutput fakeOutput; /* UT_PTR_SET() is not reentrant */
|
||||
|
||||
CommandLineTestRunner commandLineTestRunner(4, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
|
||||
fakeOutput.restoreOriginals();
|
||||
|
||||
STRCMP_CONTAINS("<testcase classname=\"package.group1\" name=\"test1\"", fakeOutput.file.asCharString());
|
||||
STRCMP_CONTAINS("TEST(group1, test1)", fakeOutput.console.asCharString());
|
||||
|
||||
}
|
||||
|
||||
TEST(CommandLineTestRunner, realTeamCityOutputShouldBeCreatedAndWorkProperly)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-oteamcity", "-v", "-kpackage", };
|
||||
|
||||
FakeOutput fakeOutput; /* UT_PTR_SET() is not reentrant */
|
||||
|
||||
CommandLineTestRunner commandLineTestRunner(4, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
|
||||
fakeOutput.restoreOriginals();
|
||||
|
||||
STRCMP_CONTAINS("##teamcity[testSuiteStarted name='group1'", fakeOutput.console.asCharString());
|
||||
STRCMP_CONTAINS("##teamcity[testStarted name='test1'", fakeOutput.console.asCharString());
|
||||
STRCMP_CONTAINS("##teamcity[testFinished name='test1'", fakeOutput.console.asCharString());
|
||||
STRCMP_CONTAINS("##teamcity[testSuiteFinished name='group1'", fakeOutput.console.asCharString());
|
||||
}
|
||||
|
||||
|
||||
class RunIgnoredUtest : public Utest
|
||||
{
|
||||
public:
|
||||
static bool Checker;
|
||||
void testBody() _override
|
||||
{
|
||||
Checker = true;
|
||||
}
|
||||
};
|
||||
|
||||
bool RunIgnoredUtest::Checker = false;
|
||||
|
||||
class RunIgnoredUtestShell : public IgnoredUtestShell
|
||||
{
|
||||
public:
|
||||
RunIgnoredUtestShell(const char* groupName, const char* testName, const char* fileName, size_t lineNumber)
|
||||
: IgnoredUtestShell(groupName, testName, fileName, lineNumber) {}
|
||||
virtual Utest* createTest() _override { return new RunIgnoredUtest; }
|
||||
};
|
||||
|
||||
TEST_GROUP(RunIgnoredTest)
|
||||
{
|
||||
TestRegistry registry;
|
||||
RunIgnoredUtestShell *runIgnoredTest;
|
||||
DummyPluginWhichCountsThePlugins* pluginCountingPlugin;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
runIgnoredTest = new RunIgnoredUtestShell("group", "test", "file", 1);
|
||||
registry.addTest(runIgnoredTest);
|
||||
pluginCountingPlugin = new DummyPluginWhichCountsThePlugins("PluginCountingPlugin", ®istry);
|
||||
}
|
||||
void teardown() _override
|
||||
{
|
||||
delete pluginCountingPlugin;
|
||||
delete runIgnoredTest;
|
||||
RunIgnoredUtest::Checker = false;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(RunIgnoredTest, IgnoreTestWillBeIgnoredIfNoOptionSpecified)
|
||||
{
|
||||
const char* argv[] = { "tests.exe" };
|
||||
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(1, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
|
||||
CHECK_FALSE( RunIgnoredUtest::Checker );
|
||||
}
|
||||
|
||||
TEST(RunIgnoredTest, IgnoreTestWillGetRunIfOptionSpecified)
|
||||
{
|
||||
const char* argv[] = { "tests.exe", "-ri" };
|
||||
|
||||
CommandLineTestRunnerWithStringBufferOutput commandLineTestRunner(2, argv, ®istry);
|
||||
commandLineTestRunner.runAllTestsMain();
|
||||
|
||||
CHECK_TRUE( RunIgnoredUtest::Checker );
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
#include "CppUTest/TestHarness.h"
|
||||
|
||||
#if CPPUTEST_USE_STD_CPP_LIB
|
||||
|
||||
#include <memory>
|
||||
|
||||
TEST_GROUP(StandardCppLibrary)
|
||||
{
|
||||
};
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201402L
|
||||
|
||||
TEST(StandardCppLibrary, UniquePtrConversationToBool)
|
||||
{
|
||||
auto const aNull = std::unique_ptr<int>(nullptr);
|
||||
CHECK_FALSE(aNull);
|
||||
|
||||
auto const notNull = std::make_unique<int>(1);
|
||||
CHECK_TRUE(notNull);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/MemoryLeakDetector.h"
|
||||
#include "DummyMemoryLeakDetector.h"
|
||||
|
||||
DummyMemoryLeakDetector::DummyMemoryLeakDetector(MemoryLeakFailure* reporter) : MemoryLeakDetector(reporter)
|
||||
{
|
||||
memoryLeakDetectorWasDeleted = false;
|
||||
}
|
||||
|
||||
DummyMemoryLeakDetector::~DummyMemoryLeakDetector()
|
||||
{
|
||||
memoryLeakDetectorWasDeleted = true;
|
||||
}
|
||||
|
||||
bool DummyMemoryLeakDetector::wasDeleted()
|
||||
{
|
||||
return memoryLeakDetectorWasDeleted;
|
||||
}
|
||||
|
||||
bool DummyMemoryLeakDetector::memoryLeakDetectorWasDeleted = false;
|
||||
|
||||
DummyMemoryLeakFailure::DummyMemoryLeakFailure()
|
||||
: MemoryLeakFailure()
|
||||
{
|
||||
memoryLeakFailureWasDelete = false;
|
||||
}
|
||||
|
||||
DummyMemoryLeakFailure::~DummyMemoryLeakFailure()
|
||||
{
|
||||
memoryLeakFailureWasDelete = true;
|
||||
}
|
||||
|
||||
bool DummyMemoryLeakFailure::wasDeleted()
|
||||
{
|
||||
return memoryLeakFailureWasDelete;
|
||||
}
|
||||
|
||||
void DummyMemoryLeakFailure::fail(char*)
|
||||
{
|
||||
}
|
||||
|
||||
bool DummyMemoryLeakFailure::memoryLeakFailureWasDelete = false;
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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.
|
||||
*/
|
||||
|
||||
class DummyMemoryLeakDetector : public MemoryLeakDetector
|
||||
{
|
||||
public:
|
||||
DummyMemoryLeakDetector(MemoryLeakFailure* reporter);
|
||||
virtual ~DummyMemoryLeakDetector() _destructor_override;
|
||||
static bool wasDeleted();
|
||||
|
||||
private:
|
||||
static bool memoryLeakDetectorWasDeleted;
|
||||
};
|
||||
|
||||
class DummyMemoryLeakFailure : public MemoryLeakFailure
|
||||
{
|
||||
public:
|
||||
DummyMemoryLeakFailure();
|
||||
|
||||
virtual ~DummyMemoryLeakFailure() _destructor_override;
|
||||
static bool wasDeleted();
|
||||
virtual void fail(char*) _override;
|
||||
|
||||
private:
|
||||
static bool memoryLeakFailureWasDelete;
|
||||
};
|
||||
|
|
@ -0,0 +1,759 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/JUnitTestOutput.h"
|
||||
#include "CppUTest/TestResult.h"
|
||||
#include "CppUTest/PlatformSpecificFunctions.h"
|
||||
#include "CppUTest/SimpleString.h"
|
||||
|
||||
class FileForJUnitOutputTests
|
||||
{
|
||||
SimpleString name_;
|
||||
bool isOpen_;
|
||||
SimpleString buffer_;
|
||||
FileForJUnitOutputTests* next_;
|
||||
|
||||
SimpleStringCollection linesOfFile_;
|
||||
|
||||
public:
|
||||
|
||||
FileForJUnitOutputTests(const SimpleString& filename, FileForJUnitOutputTests* next) :
|
||||
name_(filename), isOpen_(true), next_(next) {}
|
||||
|
||||
FileForJUnitOutputTests* nextFile()
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
SimpleString name()
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
void write(const SimpleString& buffer)
|
||||
{
|
||||
buffer_ += buffer;
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
isOpen_ = false;
|
||||
}
|
||||
|
||||
const char* line(size_t lineNumber)
|
||||
{
|
||||
buffer_.split("\n", linesOfFile_);
|
||||
return linesOfFile_[lineNumber-1].asCharString();
|
||||
|
||||
}
|
||||
|
||||
const char* lineFromTheBack(size_t lineNumberFromTheBack)
|
||||
{
|
||||
return line(amountOfLines() - (lineNumberFromTheBack - 1));
|
||||
}
|
||||
|
||||
size_t amountOfLines()
|
||||
{
|
||||
buffer_.split("\n", linesOfFile_);
|
||||
return linesOfFile_.size();
|
||||
}
|
||||
|
||||
SimpleString content()
|
||||
{
|
||||
return buffer_;
|
||||
}
|
||||
};
|
||||
|
||||
class FileSystemForJUnitTestOutputTests
|
||||
{
|
||||
FileForJUnitOutputTests* firstFile_;
|
||||
|
||||
public:
|
||||
FileSystemForJUnitTestOutputTests() : firstFile_(NULLPTR) {}
|
||||
~FileSystemForJUnitTestOutputTests() { clear(); }
|
||||
|
||||
void clear(void)
|
||||
{
|
||||
while (firstFile_) {
|
||||
FileForJUnitOutputTests* fileToBeDeleted = firstFile_;
|
||||
firstFile_ = firstFile_->nextFile();
|
||||
delete fileToBeDeleted;
|
||||
}
|
||||
}
|
||||
|
||||
FileForJUnitOutputTests* openFile(const SimpleString& filename)
|
||||
{
|
||||
firstFile_ = new FileForJUnitOutputTests(filename, firstFile_);
|
||||
return firstFile_;
|
||||
}
|
||||
|
||||
int amountOfFiles() {
|
||||
int totalAmountOfFiles = 0;
|
||||
for (FileForJUnitOutputTests* current = firstFile_; current != NULLPTR; current = current->nextFile())
|
||||
totalAmountOfFiles++;
|
||||
return totalAmountOfFiles;
|
||||
}
|
||||
|
||||
bool fileExists(const char* filename)
|
||||
{
|
||||
FileForJUnitOutputTests *searchedFile = file(filename);
|
||||
return (searchedFile != NULLPTR);
|
||||
}
|
||||
|
||||
FileForJUnitOutputTests* file(const char* filename)
|
||||
{
|
||||
for (FileForJUnitOutputTests* current = firstFile_; current != NULLPTR; current = current->nextFile())
|
||||
if (current->name() == filename)
|
||||
return current;
|
||||
return NULLPTR;
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
static long millisTime = 0;
|
||||
static const char* theTime = "";
|
||||
|
||||
static long MockGetPlatformSpecificTimeInMillis()
|
||||
{
|
||||
return millisTime;
|
||||
}
|
||||
|
||||
static const char* MockGetPlatformSpecificTimeString()
|
||||
{
|
||||
return theTime;
|
||||
}
|
||||
}
|
||||
|
||||
class JUnitTestOutputTestRunner
|
||||
{
|
||||
TestResult result_;
|
||||
|
||||
const char* currentGroupName_;
|
||||
UtestShell* currentTest_;
|
||||
bool firstTestInGroup_;
|
||||
int timeTheTestTakes_;
|
||||
unsigned int numberOfChecksInTest_;
|
||||
TestFailure* testFailure_;
|
||||
|
||||
public:
|
||||
|
||||
explicit JUnitTestOutputTestRunner(const TestResult& result) :
|
||||
result_(result), currentGroupName_(NULLPTR), currentTest_(NULLPTR), firstTestInGroup_(true), timeTheTestTakes_(0), numberOfChecksInTest_(0), testFailure_(NULLPTR)
|
||||
{
|
||||
millisTime = 0;
|
||||
theTime = "1978-10-03T00:00:00";
|
||||
|
||||
UT_PTR_SET(GetPlatformSpecificTimeInMillis, MockGetPlatformSpecificTimeInMillis);
|
||||
UT_PTR_SET(GetPlatformSpecificTimeString, MockGetPlatformSpecificTimeString);
|
||||
}
|
||||
|
||||
JUnitTestOutputTestRunner& start()
|
||||
{
|
||||
result_.testsStarted();
|
||||
return *this;
|
||||
}
|
||||
|
||||
JUnitTestOutputTestRunner& end()
|
||||
{
|
||||
endOfPreviousTestGroup();
|
||||
delete currentTest_;
|
||||
result_.testsEnded();
|
||||
return *this;
|
||||
}
|
||||
|
||||
JUnitTestOutputTestRunner& endGroupAndClearTest()
|
||||
{
|
||||
endOfPreviousTestGroup();
|
||||
delete currentTest_;
|
||||
currentTest_ = NULLPTR;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void endOfPreviousTestGroup()
|
||||
{
|
||||
runPreviousTest();
|
||||
if (currentTest_) {
|
||||
result_.currentGroupEnded(currentTest_);
|
||||
firstTestInGroup_ = true;
|
||||
}
|
||||
|
||||
currentGroupName_ = NULLPTR;
|
||||
}
|
||||
|
||||
JUnitTestOutputTestRunner& withGroup(const char* groupName)
|
||||
{
|
||||
runPreviousTest();
|
||||
endOfPreviousTestGroup();
|
||||
|
||||
currentGroupName_ = groupName;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JUnitTestOutputTestRunner& withTest(const char* testName)
|
||||
{
|
||||
runPreviousTest();
|
||||
delete currentTest_;
|
||||
|
||||
currentTest_ = new UtestShell(currentGroupName_, testName, "file", 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
JUnitTestOutputTestRunner& withIgnoredTest(const char* testName)
|
||||
{
|
||||
runPreviousTest();
|
||||
delete currentTest_;
|
||||
|
||||
currentTest_ = new IgnoredUtestShell(currentGroupName_, testName, "file", 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
JUnitTestOutputTestRunner& inFile(const char* fileName)
|
||||
{
|
||||
if(currentTest_) {
|
||||
currentTest_->setFileName(fileName);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
JUnitTestOutputTestRunner& onLine(size_t lineNumber)
|
||||
{
|
||||
if(currentTest_) {
|
||||
currentTest_->setLineNumber(lineNumber);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void runPreviousTest()
|
||||
{
|
||||
if (currentTest_ == NULLPTR) return;
|
||||
|
||||
if (firstTestInGroup_) {
|
||||
result_.currentGroupStarted(currentTest_);
|
||||
firstTestInGroup_ = false;
|
||||
}
|
||||
result_.currentTestStarted(currentTest_);
|
||||
|
||||
millisTime += timeTheTestTakes_;
|
||||
for(unsigned int i = 0; i < numberOfChecksInTest_; i++) {
|
||||
result_.countCheck();
|
||||
}
|
||||
numberOfChecksInTest_ = 0;
|
||||
|
||||
if (testFailure_) {
|
||||
result_.addFailure(*testFailure_);
|
||||
delete testFailure_;
|
||||
testFailure_ = NULLPTR;
|
||||
}
|
||||
|
||||
result_.currentTestEnded(currentTest_);
|
||||
}
|
||||
|
||||
JUnitTestOutputTestRunner& thatHasChecks(unsigned int numOfChecks)
|
||||
{
|
||||
numberOfChecksInTest_ = numOfChecks;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JUnitTestOutputTestRunner& thatTakes(int timeElapsed)
|
||||
{
|
||||
timeTheTestTakes_ = timeElapsed;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JUnitTestOutputTestRunner& seconds()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
JUnitTestOutputTestRunner& thatFails(const char* message, const char* file, size_t line)
|
||||
{
|
||||
testFailure_ = new TestFailure( currentTest_, file, line, message);
|
||||
return *this;
|
||||
}
|
||||
|
||||
JUnitTestOutputTestRunner& atTime(const char* newTime)
|
||||
{
|
||||
theTime = newTime;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JUnitTestOutputTestRunner& thatPrints(const char* output)
|
||||
{
|
||||
runPreviousTest();
|
||||
result_.print(output);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
static FileSystemForJUnitTestOutputTests fileSystem;
|
||||
|
||||
static PlatformSpecificFile mockFOpen(const char* filename, const char*)
|
||||
{
|
||||
return fileSystem.openFile(filename);
|
||||
}
|
||||
|
||||
static void mockFPuts(const char* str, PlatformSpecificFile file)
|
||||
{
|
||||
((FileForJUnitOutputTests*)file)->write(str);
|
||||
}
|
||||
|
||||
static void mockFClose(PlatformSpecificFile file)
|
||||
{
|
||||
((FileForJUnitOutputTests*)file)->close();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_GROUP(JUnitOutputTest)
|
||||
{
|
||||
JUnitTestOutput *junitOutput;
|
||||
TestResult *result;
|
||||
JUnitTestOutputTestRunner *testCaseRunner;
|
||||
FileForJUnitOutputTests* outputFile;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
UT_PTR_SET(PlatformSpecificFOpen, mockFOpen);
|
||||
UT_PTR_SET(PlatformSpecificFPuts, mockFPuts);
|
||||
UT_PTR_SET(PlatformSpecificFClose, mockFClose);
|
||||
junitOutput = new JUnitTestOutput();
|
||||
result = new TestResult(*junitOutput);
|
||||
testCaseRunner = new JUnitTestOutputTestRunner(*result);
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
delete testCaseRunner;
|
||||
delete result;
|
||||
delete junitOutput;
|
||||
fileSystem.clear();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(JUnitOutputTest, withOneTestGroupAndOneTestOnlyWriteToOneFile)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("groupname").withTest("testname")
|
||||
.end();
|
||||
|
||||
LONGS_EQUAL(1, fileSystem.amountOfFiles());
|
||||
CHECK(fileSystem.fileExists("cpputest_groupname.xml"));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, withReservedCharactersInPackageOrTestGroupUsesUnderscoresForFileName)
|
||||
{
|
||||
junitOutput->setPackageName("p/a\\c?k%a*g:e|n\"a<m>e.");
|
||||
testCaseRunner->start()
|
||||
.withGroup("g/r\\o?u%p*n:a|m\"e<h>ere").withTest("testname")
|
||||
.end();
|
||||
|
||||
CHECK(fileSystem.fileExists("cpputest_p_a_c_k_a_g_e_n_a_m_e._g_r_o_u_p_n_a_m_e_h_ere.xml"));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, withOneTestGroupAndOneTestOutputsValidXMLFiles)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("groupname").withTest("testname")
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_groupname.xml");
|
||||
STRCMP_EQUAL("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n", outputFile->line(1));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, withOneTestGroupAndOneTestOutputsTestSuiteStartAndEndBlocks)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("groupname").withTest("testname")
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_groupname.xml");
|
||||
STRCMP_EQUAL("<testsuite errors=\"0\" failures=\"0\" hostname=\"localhost\" name=\"groupname\" tests=\"1\" time=\"0.000\" timestamp=\"1978-10-03T00:00:00\">\n", outputFile->line(2));
|
||||
STRCMP_EQUAL("</testsuite>\n", outputFile->lineFromTheBack(1));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, withOneTestGroupAndOneTestFileShouldContainAnEmptyPropertiesBlock)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("groupname").withTest("testname")
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_groupname.xml");
|
||||
STRCMP_EQUAL("<properties>\n", outputFile->line(3));
|
||||
STRCMP_EQUAL("</properties>\n", outputFile->line(4));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, withOneTestGroupAndOneTestFileShouldContainAnEmptyStdoutBlock)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("groupname").withTest("testname")
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_groupname.xml");
|
||||
STRCMP_EQUAL("<system-out></system-out>\n", outputFile->lineFromTheBack(3));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, withOneTestGroupAndOneTestFileShouldContainAnEmptyStderrBlock)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("groupname").withTest("testname")
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_groupname.xml");
|
||||
STRCMP_EQUAL("<system-err></system-err>\n", outputFile->lineFromTheBack(2));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, withOneTestGroupAndOneTestFileShouldContainsATestCaseBlock)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("groupname").withTest("testname")
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_groupname.xml");
|
||||
|
||||
STRCMP_EQUAL("<testcase classname=\"groupname\" name=\"testname\" assertions=\"0\" time=\"0.000\" file=\"file\" line=\"1\">\n", outputFile->line(5));
|
||||
STRCMP_EQUAL("</testcase>\n", outputFile->line(6));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, withOneTestGroupAndTwoTestCasesCreateCorrectTestgroupBlockAndCorrectTestCaseBlock)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("twoTestsGroup").withTest("firstTestName").withTest("secondTestName")
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_twoTestsGroup.xml");
|
||||
|
||||
STRCMP_EQUAL("<testsuite errors=\"0\" failures=\"0\" hostname=\"localhost\" name=\"twoTestsGroup\" tests=\"2\" time=\"0.000\" timestamp=\"1978-10-03T00:00:00\">\n", outputFile->line(2));
|
||||
STRCMP_EQUAL("<testcase classname=\"twoTestsGroup\" name=\"firstTestName\" assertions=\"0\" time=\"0.000\" file=\"file\" line=\"1\">\n", outputFile->line(5));
|
||||
STRCMP_EQUAL("</testcase>\n", outputFile->line(6));
|
||||
STRCMP_EQUAL("<testcase classname=\"twoTestsGroup\" name=\"secondTestName\" assertions=\"0\" time=\"0.000\" file=\"file\" line=\"1\">\n", outputFile->line(7));
|
||||
STRCMP_EQUAL("</testcase>\n", outputFile->line(8));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, withOneTestGroupAndTimeHasElapsedAndTimestampChanged)
|
||||
{
|
||||
testCaseRunner->start().atTime("2013-07-04T22:28:00")
|
||||
.withGroup("timeGroup").withTest("Dummy").thatTakes(10).seconds()
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_timeGroup.xml");
|
||||
|
||||
STRCMP_EQUAL("<testsuite errors=\"0\" failures=\"0\" hostname=\"localhost\" name=\"timeGroup\" tests=\"1\" time=\"0.010\" timestamp=\"2013-07-04T22:28:00\">\n", outputFile->line(2));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, withOneTestGroupAndMultipleTestCasesWithElapsedTime)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("twoTestsGroup")
|
||||
.withTest("firstTestName").thatTakes(10).seconds()
|
||||
.withTest("secondTestName").thatTakes(50).seconds()
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_twoTestsGroup.xml");
|
||||
STRCMP_EQUAL("<testsuite errors=\"0\" failures=\"0\" hostname=\"localhost\" name=\"twoTestsGroup\" tests=\"2\" time=\"0.060\" timestamp=\"1978-10-03T00:00:00\">\n", outputFile->line(2));
|
||||
STRCMP_EQUAL("<testcase classname=\"twoTestsGroup\" name=\"firstTestName\" assertions=\"0\" time=\"0.010\" file=\"file\" line=\"1\">\n", outputFile->line(5));
|
||||
STRCMP_EQUAL("</testcase>\n", outputFile->line(6));
|
||||
STRCMP_EQUAL("<testcase classname=\"twoTestsGroup\" name=\"secondTestName\" assertions=\"0\" time=\"0.050\" file=\"file\" line=\"1\">\n", outputFile->line(7));
|
||||
STRCMP_EQUAL("</testcase>\n", outputFile->line(8));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, withOneTestGroupAndOneFailingTest)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("testGroupWithFailingTest")
|
||||
.withTest("FailingTestName").thatFails("Test failed", "thisfile", 10)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_testGroupWithFailingTest.xml");
|
||||
STRCMP_EQUAL("<testsuite errors=\"0\" failures=\"1\" hostname=\"localhost\" name=\"testGroupWithFailingTest\" tests=\"1\" time=\"0.000\" timestamp=\"1978-10-03T00:00:00\">\n", outputFile->line(2));
|
||||
STRCMP_EQUAL("<testcase classname=\"testGroupWithFailingTest\" name=\"FailingTestName\" assertions=\"0\" time=\"0.000\" file=\"file\" line=\"1\">\n", outputFile->line(5));
|
||||
STRCMP_EQUAL("<failure message=\"thisfile:10: Test failed\" type=\"AssertionFailedError\">\n", outputFile->line(6));
|
||||
STRCMP_EQUAL("</failure>\n", outputFile->line(7));
|
||||
STRCMP_EQUAL("</testcase>\n", outputFile->line(8));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, withTwoTestGroupAndOneFailingTest)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("testGroupWithFailingTest")
|
||||
.withTest("FirstTest")
|
||||
.withTest("FailingTestName").thatFails("Test failed", "thisfile", 10)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_testGroupWithFailingTest.xml");
|
||||
|
||||
STRCMP_EQUAL("<testsuite errors=\"0\" failures=\"1\" hostname=\"localhost\" name=\"testGroupWithFailingTest\" tests=\"2\" time=\"0.000\" timestamp=\"1978-10-03T00:00:00\">\n", outputFile->line(2));
|
||||
STRCMP_EQUAL("<testcase classname=\"testGroupWithFailingTest\" name=\"FailingTestName\" assertions=\"0\" time=\"0.000\" file=\"file\" line=\"1\">\n", outputFile->line(7));
|
||||
STRCMP_EQUAL("<failure message=\"thisfile:10: Test failed\" type=\"AssertionFailedError\">\n", outputFile->line(8));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, testFailureWithLessThanAndGreaterThanInsideIt)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("testGroupWithFailingTest")
|
||||
.withTest("FailingTestName").thatFails("Test <failed>", "thisfile", 10)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_testGroupWithFailingTest.xml");
|
||||
|
||||
STRCMP_EQUAL("<failure message=\"thisfile:10: Test <failed>\" type=\"AssertionFailedError\">\n", outputFile->line(6));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, testFailureWithQuotesInIt)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("testGroupWithFailingTest")
|
||||
.withTest("FailingTestName").thatFails("Test \"failed\"", "thisfile", 10)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_testGroupWithFailingTest.xml");
|
||||
|
||||
STRCMP_EQUAL("<failure message=\"thisfile:10: Test "failed"\" type=\"AssertionFailedError\">\n", outputFile->line(6));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, testFailureWithNewlineInIt)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("testGroupWithFailingTest")
|
||||
.withTest("FailingTestName").thatFails("Test \nfailed", "thisfile", 10)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_testGroupWithFailingTest.xml");
|
||||
|
||||
STRCMP_EQUAL("<failure message=\"thisfile:10: Test {newline}failed\" type=\"AssertionFailedError\">\n", outputFile->line(6));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, testFailureWithDifferentFileAndLine)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("testGroupWithFailingTest")
|
||||
.withTest("FailingTestName").thatFails("Test failed", "importantFile", 999)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_testGroupWithFailingTest.xml");
|
||||
|
||||
STRCMP_EQUAL("<failure message=\"importantFile:999: Test failed\" type=\"AssertionFailedError\">\n", outputFile->line(6));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, testFailureWithAmpersandsAndLessThan)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("testGroupWithFailingTest")
|
||||
.withTest("FailingTestName").thatFails("&object1 < &object2", "importantFile", 999)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_testGroupWithFailingTest.xml");
|
||||
|
||||
STRCMP_EQUAL("<failure message=\"importantFile:999: &object1 < &object2\" type=\"AssertionFailedError\">\n", outputFile->line(6));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, testFailureWithAmpersands)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("testGroupWithFailingTest")
|
||||
.withTest("FailingTestName").thatFails("&object1 != &object2", "importantFile", 999)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_testGroupWithFailingTest.xml");
|
||||
|
||||
STRCMP_EQUAL("<failure message=\"importantFile:999: &object1 != &object2\" type=\"AssertionFailedError\">\n", outputFile->line(6));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, aCoupleOfTestFailures)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("testGroup")
|
||||
.withTest("passingOne")
|
||||
.withTest("FailingTest").thatFails("Failure", "file", 99)
|
||||
.withTest("passingTwo")
|
||||
.withTest("passingThree")
|
||||
.withTest("AnotherFailingTest").thatFails("otherFailure", "anotherFile", 10)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_testGroup.xml");
|
||||
|
||||
STRCMP_EQUAL("<failure message=\"file:99: Failure\" type=\"AssertionFailedError\">\n", outputFile->line(8));
|
||||
STRCMP_EQUAL("<failure message=\"anotherFile:10: otherFailure\" type=\"AssertionFailedError\">\n", outputFile->line(16));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, testFailuresInSeparateGroups)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("testGroup")
|
||||
.withTest("passingOne")
|
||||
.withTest("FailingTest").thatFails("Failure", "file", 99)
|
||||
.withGroup("AnotherGroup")
|
||||
.withTest("AnotherFailingTest").thatFails("otherFailure", "anotherFile", 10)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_testGroup.xml");
|
||||
|
||||
STRCMP_EQUAL("<failure message=\"file:99: Failure\" type=\"AssertionFailedError\">\n", outputFile->line(8));
|
||||
|
||||
outputFile = fileSystem.file("cpputest_AnotherGroup.xml");
|
||||
STRCMP_EQUAL("<failure message=\"anotherFile:10: otherFailure\" type=\"AssertionFailedError\">\n", outputFile->line(8));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, twoTestGroupsWriteToTwoDifferentFiles)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("firstTestGroup")
|
||||
.withTest("testName")
|
||||
.withGroup("secondTestGroup")
|
||||
.withTest("testName")
|
||||
.end();
|
||||
|
||||
CHECK(fileSystem.file("cpputest_firstTestGroup.xml") != NULLPTR);
|
||||
CHECK(fileSystem.file("cpputest_secondTestGroup.xml") != NULLPTR);
|
||||
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, testGroupWithWeirdName)
|
||||
{
|
||||
STRCMP_EQUAL("cpputest_group_weird_name.xml", junitOutput->createFileName("group/weird/name").asCharString());
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, TestCaseBlockWithAPackageName)
|
||||
{
|
||||
junitOutput->setPackageName("packagename");
|
||||
testCaseRunner->start()
|
||||
.withGroup("groupname").withTest("testname")
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_packagename_groupname.xml");
|
||||
|
||||
STRCMP_EQUAL("<testcase classname=\"packagename.groupname\" name=\"testname\" assertions=\"0\" time=\"0.000\" file=\"file\" line=\"1\">\n", outputFile->line(5));
|
||||
STRCMP_EQUAL("</testcase>\n", outputFile->line(6));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, TestCaseBlockForIgnoredTest)
|
||||
{
|
||||
junitOutput->setPackageName("packagename");
|
||||
testCaseRunner->start()
|
||||
.withGroup("groupname").withIgnoredTest("testname")
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_packagename_groupname.xml");
|
||||
|
||||
STRCMP_EQUAL("<testcase classname=\"packagename.groupname\" name=\"testname\" assertions=\"0\" time=\"0.000\" file=\"file\" line=\"1\">\n", outputFile->line(5));
|
||||
STRCMP_EQUAL("<skipped />\n", outputFile->line(6));
|
||||
STRCMP_EQUAL("</testcase>\n", outputFile->line(7));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, TestCaseWithTestLocation)
|
||||
{
|
||||
junitOutput->setPackageName("packagename");
|
||||
testCaseRunner->start()
|
||||
.withGroup("groupname")
|
||||
.withTest("testname").inFile("MySource.c").onLine(159)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_packagename_groupname.xml");
|
||||
|
||||
STRCMP_EQUAL("<testcase classname=\"packagename.groupname\" name=\"testname\" assertions=\"0\" time=\"0.000\" file=\"MySource.c\" line=\"159\">\n", outputFile->line(5));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, MultipleTestCaseWithTestLocations)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("twoTestsGroup")
|
||||
.withTest("firstTestName").inFile("MyFirstSource.c").onLine(846)
|
||||
.withTest("secondTestName").inFile("MySecondSource.c").onLine(513)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_twoTestsGroup.xml");
|
||||
|
||||
STRCMP_EQUAL("<testcase classname=\"twoTestsGroup\" name=\"firstTestName\" assertions=\"0\" time=\"0.000\" file=\"MyFirstSource.c\" line=\"846\">\n", outputFile->line(5));
|
||||
STRCMP_EQUAL("<testcase classname=\"twoTestsGroup\" name=\"secondTestName\" assertions=\"0\" time=\"0.000\" file=\"MySecondSource.c\" line=\"513\">\n", outputFile->line(7));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, TestCaseBlockWithAssertions)
|
||||
{
|
||||
junitOutput->setPackageName("packagename");
|
||||
testCaseRunner->start()
|
||||
.withGroup("groupname")
|
||||
.withTest("testname")
|
||||
.thatHasChecks(24)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_packagename_groupname.xml");
|
||||
|
||||
STRCMP_EQUAL("<testcase classname=\"packagename.groupname\" name=\"testname\" assertions=\"24\" time=\"0.000\" file=\"file\" line=\"1\">\n", outputFile->line(5));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, MultipleTestCaseBlocksWithAssertions)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("twoTestsGroup")
|
||||
.withTest("firstTestName").thatHasChecks(456)
|
||||
.withTest("secondTestName").thatHasChecks(567)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_twoTestsGroup.xml");
|
||||
|
||||
STRCMP_EQUAL("<testcase classname=\"twoTestsGroup\" name=\"firstTestName\" assertions=\"456\" time=\"0.000\" file=\"file\" line=\"1\">\n", outputFile->line(5));
|
||||
STRCMP_EQUAL("<testcase classname=\"twoTestsGroup\" name=\"secondTestName\" assertions=\"567\" time=\"0.000\" file=\"file\" line=\"1\">\n", outputFile->line(7));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, MultipleTestCasesInDifferentGroupsWithAssertions)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("groupOne")
|
||||
.withTest("testA").thatHasChecks(456)
|
||||
.endGroupAndClearTest()
|
||||
.withGroup("groupTwo")
|
||||
.withTest("testB").thatHasChecks(678)
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_groupOne.xml");
|
||||
STRCMP_EQUAL("<testcase classname=\"groupOne\" name=\"testA\" assertions=\"456\" time=\"0.000\" file=\"file\" line=\"1\">\n", outputFile->line(5));
|
||||
|
||||
outputFile = fileSystem.file("cpputest_groupTwo.xml");
|
||||
STRCMP_EQUAL("<testcase classname=\"groupTwo\" name=\"testB\" assertions=\"678\" time=\"0.000\" file=\"file\" line=\"1\">\n", outputFile->line(5));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, UTPRINTOutputInJUnitOutput)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("groupname")
|
||||
.withTest("testname").thatPrints("someoutput")
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_groupname.xml");
|
||||
STRCMP_EQUAL("<system-out>someoutput</system-out>\n", outputFile->lineFromTheBack(3));
|
||||
}
|
||||
|
||||
TEST(JUnitOutputTest, UTPRINTOutputInJUnitOutputWithSpecials)
|
||||
{
|
||||
testCaseRunner->start()
|
||||
.withGroup("groupname")
|
||||
.withTest("testname").thatPrints("The <rain> in \"Spain\"\nGoes \\mainly\\ down the Dr&in\n")
|
||||
.end();
|
||||
|
||||
outputFile = fileSystem.file("cpputest_groupname.xml");
|
||||
STRCMP_EQUAL("<system-out>The <rain> in "Spain"{newline}Goes \\mainly\\ down the Dr&in{newline}</system-out>\n", outputFile->lineFromTheBack(3));
|
||||
}
|
|
@ -0,0 +1,692 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/MemoryLeakDetector.h"
|
||||
#include "CppUTest/TestMemoryAllocator.h"
|
||||
#include "CppUTest/PlatformSpecificFunctions.h"
|
||||
|
||||
class MemoryLeakFailureForTest: public MemoryLeakFailure
|
||||
{
|
||||
public:
|
||||
virtual ~MemoryLeakFailureForTest() _destructor_override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void fail(char* fail_string) _override
|
||||
{
|
||||
*message = fail_string;
|
||||
}
|
||||
|
||||
SimpleString *message;
|
||||
};
|
||||
|
||||
class NewAllocatorForMemoryLeakDetectionTest: public TestMemoryAllocator
|
||||
{
|
||||
public:
|
||||
NewAllocatorForMemoryLeakDetectionTest() :
|
||||
TestMemoryAllocator("Standard New Allocator", "new", "delete"),
|
||||
alloc_called(0), free_called(0)
|
||||
{
|
||||
}
|
||||
|
||||
int alloc_called;
|
||||
int free_called;
|
||||
char* alloc_memory(size_t size, const char*, size_t) _override
|
||||
{
|
||||
alloc_called++;
|
||||
return TestMemoryAllocator::alloc_memory(size, "file", 1);
|
||||
}
|
||||
void free_memory(char* memory, size_t size, const char* file, size_t line) _override
|
||||
{
|
||||
free_called++;
|
||||
TestMemoryAllocator::free_memory(memory, size, file, line);
|
||||
}
|
||||
};
|
||||
|
||||
class AllocatorForMemoryLeakDetectionTest: public TestMemoryAllocator
|
||||
{
|
||||
public:
|
||||
AllocatorForMemoryLeakDetectionTest() :
|
||||
alloc_called(0), free_called(0), allocMemoryLeakNodeCalled(0), freeMemoryLeakNodeCalled(0)
|
||||
{
|
||||
}
|
||||
|
||||
int alloc_called;
|
||||
int free_called;
|
||||
int allocMemoryLeakNodeCalled;
|
||||
int freeMemoryLeakNodeCalled;
|
||||
|
||||
char* alloc_memory(size_t size, const char* file, size_t line) _override
|
||||
{
|
||||
alloc_called++;
|
||||
return TestMemoryAllocator::alloc_memory(size, file, line);
|
||||
}
|
||||
void free_memory(char* memory, size_t size, const char* file, size_t line) _override
|
||||
{
|
||||
free_called++;
|
||||
TestMemoryAllocator::free_memory(memory, size, file, line);
|
||||
}
|
||||
|
||||
char* allocMemoryLeakNode(size_t size) _override
|
||||
{
|
||||
allocMemoryLeakNodeCalled++;
|
||||
return TestMemoryAllocator::alloc_memory(size, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void freeMemoryLeakNode(char* memory) _override
|
||||
{
|
||||
freeMemoryLeakNodeCalled++;
|
||||
TestMemoryAllocator::free_memory(memory, 0, __FILE__, __LINE__);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_GROUP(MemoryLeakDetectorTest)
|
||||
{
|
||||
MemoryLeakDetector* detector;
|
||||
MemoryLeakFailureForTest *reporter;
|
||||
AllocatorForMemoryLeakDetectionTest* testAllocator;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
reporter = new MemoryLeakFailureForTest;
|
||||
detector = new MemoryLeakDetector(reporter);
|
||||
testAllocator = new AllocatorForMemoryLeakDetectionTest;
|
||||
detector->enable();
|
||||
detector->startChecking();
|
||||
reporter->message = new SimpleString();
|
||||
}
|
||||
void teardown() _override
|
||||
{
|
||||
delete reporter->message;
|
||||
delete detector;
|
||||
delete reporter;
|
||||
delete testAllocator;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(MemoryLeakDetectorTest, OneLeak)
|
||||
{
|
||||
char* mem = detector->allocMemory(testAllocator, 3);
|
||||
detector->stopChecking();
|
||||
SimpleString output = detector->report(mem_leak_period_checking);
|
||||
STRCMP_CONTAINS("Memory leak(s) found", output.asCharString());
|
||||
STRCMP_CONTAINS("size: 3", output.asCharString());
|
||||
STRCMP_CONTAINS("alloc", output.asCharString());
|
||||
STRCMP_CONTAINS(StringFromFormat("%p", (void*) mem).asCharString(), output.asCharString());
|
||||
STRCMP_CONTAINS("Total number of leaks", output.asCharString());
|
||||
PlatformSpecificFree(mem);
|
||||
LONGS_EQUAL(1, testAllocator->alloc_called);
|
||||
LONGS_EQUAL(0, testAllocator->free_called);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, sequenceNumbersOfMemoryLeaks)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultNewAllocator(), 1);
|
||||
char* mem2 = detector->allocMemory(defaultNewAllocator(), 2);
|
||||
char* mem3 = detector->allocMemory(defaultNewAllocator(), 3);
|
||||
SimpleString output = detector->report(mem_leak_period_checking);
|
||||
|
||||
STRCMP_CONTAINS("Alloc num (1)", output.asCharString());
|
||||
STRCMP_CONTAINS("Alloc num (2)", output.asCharString());
|
||||
STRCMP_CONTAINS("Alloc num (3)", output.asCharString());
|
||||
|
||||
PlatformSpecificFree(mem);
|
||||
PlatformSpecificFree(mem2);
|
||||
PlatformSpecificFree(mem3);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, memoryDumpOutput)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultNewAllocator(), 6);
|
||||
SimpleString::StrNCpy(mem, "test1", 6);
|
||||
SimpleString output = detector->report(mem_leak_period_checking);
|
||||
|
||||
STRCMP_CONTAINS("Alloc num (1)", output.asCharString());
|
||||
STRCMP_CONTAINS("Leak size: 6 Allocated at", output.asCharString());
|
||||
STRCMP_CONTAINS("Content:", output.asCharString());
|
||||
STRCMP_CONTAINS("0000: 74 65 73 74 31 00 |test1.|", output.asCharString());
|
||||
|
||||
PlatformSpecificFree(mem);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, OneHundredLeaks)
|
||||
{
|
||||
const int amount_alloc = 100;
|
||||
char *mem[amount_alloc];
|
||||
for (int i = 0; i < amount_alloc; i++)
|
||||
mem[i] = detector->allocMemory(defaultMallocAllocator(), 3);
|
||||
detector->stopChecking();
|
||||
|
||||
SimpleString output = detector->report(mem_leak_period_checking);
|
||||
|
||||
STRCMP_CONTAINS("Memory leak(s) found", output.asCharString());
|
||||
STRCMP_CONTAINS("Total number of leaks", output.asCharString());
|
||||
STRCMP_CONTAINS("Memory leak reports about malloc and free", output.asCharString());
|
||||
|
||||
//don't reuse i for vc6 compatibility
|
||||
for (int j = 0; j < amount_alloc; j++)
|
||||
PlatformSpecificFree(mem[j]);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, OneLeakOutsideCheckingPeriod)
|
||||
{
|
||||
detector->stopChecking();
|
||||
char* mem = detector->allocMemory(defaultNewAllocator(), 4);
|
||||
SimpleString output = detector->report(mem_leak_period_all);
|
||||
CHECK(output.contains("Memory leak(s) found"));
|
||||
CHECK(output.contains("size: 4"));
|
||||
CHECK(output.contains("new"));
|
||||
CHECK(output.contains("Total number of leaks"));
|
||||
PlatformSpecificFree(mem);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, NoLeaksWhatsoever)
|
||||
{
|
||||
detector->stopChecking();
|
||||
STRCMP_CONTAINS("No memory leaks", detector->report(mem_leak_period_checking));
|
||||
STRCMP_CONTAINS("No memory leaks", detector->report(mem_leak_period_all));
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, TwoLeaksUsingOperatorNew)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultNewAllocator(), 4);
|
||||
char* mem2 = detector->allocMemory(defaultNewAllocator(), 8);
|
||||
detector->stopChecking();
|
||||
SimpleString output = detector->report(mem_leak_period_checking);
|
||||
LONGS_EQUAL(2, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
CHECK(output.contains("size: 8"));
|
||||
CHECK(output.contains("size: 4"));
|
||||
PlatformSpecificFree(mem);
|
||||
PlatformSpecificFree(mem2);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, OneAllocButNoLeak)
|
||||
{
|
||||
char* mem = detector->allocMemory(testAllocator, 4);
|
||||
detector->deallocMemory(testAllocator, mem);
|
||||
detector->stopChecking();
|
||||
STRCMP_CONTAINS("No memory leaks", detector->report(mem_leak_period_checking));
|
||||
LONGS_EQUAL(1, testAllocator->alloc_called);
|
||||
LONGS_EQUAL(1, testAllocator->free_called);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, TwoAllocOneFreeOneLeak)
|
||||
{
|
||||
char* mem = detector->allocMemory(testAllocator, 4);
|
||||
char* mem2 = detector->allocMemory(testAllocator, 12);
|
||||
detector->deallocMemory(testAllocator, mem);
|
||||
detector->stopChecking();
|
||||
SimpleString output = detector->report(mem_leak_period_checking);
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
CHECK(output.contains("Leak size: 12"));
|
||||
CHECK(!output.contains("Leak size: 4"));
|
||||
PlatformSpecificFree(mem2);
|
||||
LONGS_EQUAL(2, testAllocator->alloc_called);
|
||||
LONGS_EQUAL(1, testAllocator->free_called);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, TwoAllocOneFreeOneLeakReverseOrder)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultNewAllocator(), 4);
|
||||
char* mem2 = detector->allocMemory(defaultNewAllocator(), 12);
|
||||
detector->deallocMemory(defaultNewAllocator(), mem2);
|
||||
detector->stopChecking();
|
||||
SimpleString output = detector->report(mem_leak_period_checking);
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
CHECK(!output.contains("size: 12"));
|
||||
CHECK(output.contains("size: 4"));
|
||||
PlatformSpecificFree(mem);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, DeleteNonAlocatedMemory)
|
||||
{
|
||||
char a;
|
||||
char* pa = &a;
|
||||
detector->deallocMemory(defaultMallocAllocator(), pa, "FREE.c", 100);
|
||||
detector->stopChecking();
|
||||
CHECK(reporter->message->contains("Deallocating non-allocated memory"));
|
||||
CHECK(reporter->message->contains(" allocated at file: <unknown> line: 0 size: 0 type: unknown"));
|
||||
CHECK(reporter->message->contains(" deallocated at file: FREE.c line: 100 type: free"));
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, IgnoreMemoryAllocatedOutsideCheckingPeriod)
|
||||
{
|
||||
detector->stopChecking();
|
||||
char* mem = detector->allocMemory(defaultNewAllocator(), 4);
|
||||
LONGS_EQUAL(0, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
detector->deallocMemory(defaultNewAllocator(), mem);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, IgnoreMemoryAllocatedOutsideCheckingPeriodComplicatedCase)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultNewAllocator(), 4);
|
||||
detector->stopChecking();
|
||||
|
||||
char* mem2 = detector->allocMemory(defaultNewAllocator(), 8);
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
detector->clearAllAccounting(mem_leak_period_checking);
|
||||
PlatformSpecificFree(mem);
|
||||
LONGS_EQUAL(0, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
|
||||
detector->startChecking();
|
||||
char* mem3 = detector->allocMemory(defaultNewAllocator(), 4);
|
||||
detector->stopChecking();
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
LONGS_EQUAL(2, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
|
||||
detector->clearAllAccounting(mem_leak_period_checking);
|
||||
LONGS_EQUAL(0, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
|
||||
detector->clearAllAccounting(mem_leak_period_all);
|
||||
LONGS_EQUAL(0, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
PlatformSpecificFree(mem2);
|
||||
PlatformSpecificFree(mem3);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, OneLeakUsingOperatorNewWithFileLine)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultNewAllocator(), 4, "file.cpp", 1234);
|
||||
detector->stopChecking();
|
||||
SimpleString output = detector->report(mem_leak_period_checking);
|
||||
CHECK(output.contains("file.cpp"));
|
||||
CHECK(output.contains("1234"));
|
||||
PlatformSpecificFree(mem);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, OneAllocAndFreeUsingArrayNew)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultNewArrayAllocator(), 10, "file.cpp", 1234);
|
||||
char* mem2 = detector->allocMemory(defaultNewArrayAllocator(), 12);
|
||||
LONGS_EQUAL(2, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
SimpleString output = detector->report(mem_leak_period_checking);
|
||||
CHECK(output.contains("new []"));
|
||||
detector->deallocMemory(defaultNewArrayAllocator(), mem);
|
||||
detector->deallocMemory(defaultNewArrayAllocator(), mem2);
|
||||
LONGS_EQUAL(0, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
detector->stopChecking();
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, OneAllocAndFree)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultMallocAllocator(), 10, "file.cpp", 1234);
|
||||
char* mem2 = detector->allocMemory(defaultMallocAllocator(), 12);
|
||||
LONGS_EQUAL(2, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
SimpleString output = detector->report(mem_leak_period_checking);
|
||||
CHECK(output.contains("malloc"));
|
||||
detector->deallocMemory(defaultMallocAllocator(), mem);
|
||||
detector->deallocMemory(defaultMallocAllocator(), mem2, "file.c", 5678);
|
||||
LONGS_EQUAL(0, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
detector->stopChecking();
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, OneRealloc)
|
||||
{
|
||||
char* mem1 = detector->allocMemory(testAllocator, 10, "file.cpp", 1234, true);
|
||||
|
||||
char* mem2 = detector->reallocMemory(testAllocator, mem1, 1000, "other.cpp", 5678, true);
|
||||
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
SimpleString output = detector->report(mem_leak_period_checking);
|
||||
CHECK(output.contains("other.cpp"));
|
||||
|
||||
detector->deallocMemory(testAllocator, mem2, true);
|
||||
LONGS_EQUAL(0, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
detector->stopChecking();
|
||||
LONGS_EQUAL(1, testAllocator->alloc_called);
|
||||
LONGS_EQUAL(1, testAllocator->free_called);
|
||||
LONGS_EQUAL(2, testAllocator->allocMemoryLeakNodeCalled);
|
||||
LONGS_EQUAL(2, testAllocator->freeMemoryLeakNodeCalled);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, ReallocNonAllocatedMemory)
|
||||
{
|
||||
char mem1;
|
||||
char* mem2 = detector->reallocMemory(testAllocator, &mem1, 5, "other.cpp", 13, true);
|
||||
detector->deallocMemory(testAllocator, mem2, true);
|
||||
detector->stopChecking();
|
||||
CHECK(reporter->message->contains("Deallocating non-allocated memory\n"));
|
||||
CHECK(reporter->message->contains(" deallocated at file: other.cpp line: 13"));
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, AllocOneTypeFreeAnotherType)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultNewArrayAllocator(), 100, "ALLOC.c", 10);
|
||||
detector->deallocMemory(defaultMallocAllocator(), mem, "FREE.c", 100);
|
||||
detector->stopChecking();
|
||||
CHECK(reporter->message->contains("Allocation/deallocation type mismatch"));
|
||||
CHECK(reporter->message->contains(" allocated at file: ALLOC.c line: 10 size: 100 type: new []"));
|
||||
CHECK(reporter->message->contains(" deallocated at file: FREE.c line: 100 type: free"));
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, AllocOneTypeFreeAnotherTypeWithCheckingDisabled)
|
||||
{
|
||||
detector->disableAllocationTypeChecking();
|
||||
char* mem = detector->allocMemory(defaultNewArrayAllocator(), 100, "ALLOC.c", 10);
|
||||
detector->deallocMemory(defaultNewAllocator(), mem, "FREE.c", 100);
|
||||
detector->stopChecking();
|
||||
STRCMP_EQUAL("", reporter->message->asCharString());
|
||||
detector->enableAllocationTypeChecking();
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, mallocLeakGivesAdditionalWarning)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultMallocAllocator(), 100, "ALLOC.c", 10);
|
||||
detector->stopChecking();
|
||||
SimpleString output = detector->report(mem_leak_period_checking);
|
||||
STRCMP_CONTAINS("Memory leak reports about malloc and free can be caused by allocating using the cpputest version of malloc", output.asCharString());
|
||||
PlatformSpecificFree(mem);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, newLeakDoesNotGiveAdditionalWarning)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultNewAllocator(), 100, "ALLOC.c", 10);
|
||||
detector->stopChecking();
|
||||
SimpleString output = detector->report(mem_leak_period_checking);
|
||||
CHECK(! output.contains("Memory leak reports about malloc and free"));
|
||||
PlatformSpecificFree(mem);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, MarkCheckingPeriodLeaksAsNonCheckingPeriod)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultNewArrayAllocator(), 100);
|
||||
char* mem2 = detector->allocMemory(defaultNewArrayAllocator(), 100);
|
||||
detector->stopChecking();
|
||||
LONGS_EQUAL(2, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
LONGS_EQUAL(2, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
detector->markCheckingPeriodLeaksAsNonCheckingPeriod();
|
||||
LONGS_EQUAL(0, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
LONGS_EQUAL(2, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
PlatformSpecificFree(mem);
|
||||
PlatformSpecificFree(mem2);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, memoryCorruption)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultMallocAllocator(), 10, "ALLOC.c", 10);
|
||||
mem[10] = 'O';
|
||||
mem[11] = 'H';
|
||||
detector->deallocMemory(defaultMallocAllocator(), mem, "FREE.c", 100);
|
||||
detector->stopChecking();
|
||||
CHECK(reporter->message->contains("Memory corruption"));
|
||||
CHECK(reporter->message->contains(" allocated at file: ALLOC.c line: 10 size: 10 type: malloc"));
|
||||
CHECK(reporter->message->contains(" deallocated at file: FREE.c line: 100 type: free"));
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, safelyDeleteNULL)
|
||||
{
|
||||
detector->deallocMemory(defaultNewAllocator(), NULLPTR);
|
||||
STRCMP_EQUAL("", reporter->message->asCharString());
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, periodDisabled)
|
||||
{
|
||||
detector->disable();
|
||||
char* mem = detector->allocMemory(defaultMallocAllocator(), 2);
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_disabled));
|
||||
LONGS_EQUAL(0, detector->totalMemoryLeaks(mem_leak_period_enabled));
|
||||
LONGS_EQUAL(0, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
detector->deallocMemory(defaultMallocAllocator(), mem);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, periodEnabled)
|
||||
{
|
||||
detector->enable();
|
||||
char* mem = detector->allocMemory(defaultMallocAllocator(), 2);
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
LONGS_EQUAL(0, detector->totalMemoryLeaks(mem_leak_period_disabled));
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_enabled));
|
||||
LONGS_EQUAL(0, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
detector->deallocMemory(defaultMallocAllocator(), mem);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, periodChecking)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultMallocAllocator(), 2);
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
LONGS_EQUAL(0, detector->totalMemoryLeaks(mem_leak_period_disabled));
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_enabled));
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
detector->deallocMemory(defaultMallocAllocator(), mem);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, defaultAllocationStageIsZero)
|
||||
{
|
||||
LONGS_EQUAL(0, detector->getCurrentAllocationStage());
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, canFreeNoAllocations)
|
||||
{
|
||||
detector->deallocAllMemoryInCurrentAllocationStage();
|
||||
LONGS_EQUAL(0, detector->getCurrentAllocationStage());
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, increaseAllocationStage)
|
||||
{
|
||||
detector->increaseAllocationStage();
|
||||
LONGS_EQUAL(1, detector->getCurrentAllocationStage());
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, decreaseAllocationStage)
|
||||
{
|
||||
detector->increaseAllocationStage();
|
||||
detector->decreaseAllocationStage();
|
||||
LONGS_EQUAL(0, detector->getCurrentAllocationStage());
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, freeAllMemoryInCurrentAllocationStage)
|
||||
{
|
||||
detector->increaseAllocationStage();
|
||||
detector->allocMemory(defaultMallocAllocator(), 2);
|
||||
detector->allocMemory(defaultMallocAllocator(), 2);
|
||||
detector->deallocAllMemoryInCurrentAllocationStage();
|
||||
LONGS_EQUAL(0, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, freeOnlyTheMemoryInTheAllocationStage)
|
||||
{
|
||||
char* mem = detector->allocMemory(defaultMallocAllocator(), 2);
|
||||
detector->increaseAllocationStage();
|
||||
detector->allocMemory(defaultMallocAllocator(), 2);
|
||||
detector->deallocAllMemoryInCurrentAllocationStage();
|
||||
LONGS_EQUAL(1, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
detector->deallocMemory(defaultMallocAllocator(), mem);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, allocateWithANullAllocatorCausesNoProblems)
|
||||
{
|
||||
char* mem = detector->allocMemory(NullUnknownAllocator::defaultAllocator(), 2);
|
||||
detector->deallocMemory(NullUnknownAllocator::defaultAllocator(), mem);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, invalidateMemory)
|
||||
{
|
||||
unsigned char* mem = (unsigned char*)detector->allocMemory(defaultMallocAllocator(), 2);
|
||||
|
||||
detector->invalidateMemory((char*)mem);
|
||||
CHECK(mem[0] == 0xCD);
|
||||
CHECK(mem[1] == 0xCD);
|
||||
detector->deallocMemory(defaultMallocAllocator(), mem);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakDetectorTest, invalidateMemoryNULLShouldWork)
|
||||
{
|
||||
detector->invalidateMemory(NULLPTR);
|
||||
}
|
||||
|
||||
TEST_GROUP(MemoryLeakDetectorListTest)
|
||||
{
|
||||
};
|
||||
|
||||
TEST(MemoryLeakDetectorListTest, clearAllAccountingIsWorkingProperly)
|
||||
{
|
||||
MemoryLeakDetectorList listForTesting;
|
||||
MemoryLeakDetectorNode node1, node2, node3;
|
||||
node3.period_ = mem_leak_period_disabled;
|
||||
listForTesting.addNewNode(&node1);
|
||||
listForTesting.addNewNode(&node2);
|
||||
listForTesting.addNewNode(&node3);
|
||||
|
||||
listForTesting.clearAllAccounting(mem_leak_period_enabled);
|
||||
|
||||
POINTERS_EQUAL(NULLPTR, listForTesting.getFirstLeak(mem_leak_period_enabled));
|
||||
CHECK(&node3 == listForTesting.getFirstLeak(mem_leak_period_disabled));
|
||||
}
|
||||
|
||||
TEST_GROUP(SimpleStringBuffer)
|
||||
{
|
||||
};
|
||||
|
||||
TEST(SimpleStringBuffer, initialStringIsEmpty)
|
||||
{
|
||||
SimpleStringBuffer buffer;
|
||||
STRCMP_EQUAL("", buffer.toString());
|
||||
}
|
||||
|
||||
TEST(SimpleStringBuffer, simpleTest)
|
||||
{
|
||||
SimpleStringBuffer buffer;
|
||||
buffer.add("Hello");
|
||||
buffer.add(" World");
|
||||
STRCMP_EQUAL("Hello World", buffer.toString());
|
||||
}
|
||||
|
||||
TEST(SimpleStringBuffer, writePastLimit)
|
||||
{
|
||||
SimpleStringBuffer buffer;
|
||||
for (int i = 0; i < SimpleStringBuffer::SIMPLE_STRING_BUFFER_LEN * 2; i++)
|
||||
buffer.add("h");
|
||||
SimpleString str("h", SimpleStringBuffer::SIMPLE_STRING_BUFFER_LEN-1);
|
||||
STRCMP_EQUAL(str.asCharString(), buffer.toString());
|
||||
}
|
||||
|
||||
TEST(SimpleStringBuffer, setWriteLimit)
|
||||
{
|
||||
SimpleStringBuffer buffer;
|
||||
buffer.setWriteLimit(10);
|
||||
for (int i = 0; i < SimpleStringBuffer::SIMPLE_STRING_BUFFER_LEN ; i++)
|
||||
buffer.add("h");
|
||||
SimpleString str("h", 10);
|
||||
STRCMP_EQUAL(str.asCharString(), buffer.toString());
|
||||
}
|
||||
|
||||
TEST(SimpleStringBuffer, setWriteLimitTooHighIsIgnored)
|
||||
{
|
||||
SimpleStringBuffer buffer;
|
||||
buffer.setWriteLimit(SimpleStringBuffer::SIMPLE_STRING_BUFFER_LEN+10);
|
||||
for (int i = 0; i < SimpleStringBuffer::SIMPLE_STRING_BUFFER_LEN+10; i++)
|
||||
buffer.add("h");
|
||||
SimpleString str("h", SimpleStringBuffer::SIMPLE_STRING_BUFFER_LEN-1);
|
||||
STRCMP_EQUAL(str.asCharString(), buffer.toString());
|
||||
}
|
||||
|
||||
TEST(SimpleStringBuffer, resetWriteLimit)
|
||||
{
|
||||
SimpleStringBuffer buffer;
|
||||
buffer.setWriteLimit(10);
|
||||
for (int i = 0; i < SimpleStringBuffer::SIMPLE_STRING_BUFFER_LEN ; i++)
|
||||
buffer.add("h");
|
||||
buffer.resetWriteLimit();
|
||||
buffer.add("%s", SimpleString("h", 10).asCharString());
|
||||
|
||||
SimpleString str("h", 20);
|
||||
STRCMP_EQUAL(str.asCharString(), buffer.toString());
|
||||
}
|
||||
|
||||
TEST(SimpleStringBuffer, addMemoryDumpOneLinePlusOnePartial)
|
||||
{
|
||||
SimpleStringBuffer buffer;
|
||||
buffer.addMemoryDump("deadbeefdeadbeefhopsxx", 22);
|
||||
STRCMP_EQUAL(" 0000: 64 65 61 64 62 65 65 66 64 65 61 64 62 65 65 66 |deadbeefdeadbeef|\n"
|
||||
" 0010: 68 6f 70 73 78 78 |hopsxx|\n",
|
||||
buffer.toString());
|
||||
}
|
||||
|
||||
TEST(SimpleStringBuffer, addMemoryDumpNonPrintable)
|
||||
{
|
||||
SimpleStringBuffer buffer;
|
||||
// Ensure we test edge cases - NUL, 0x1F, 0x7F, 0xFF
|
||||
buffer.addMemoryDump("\x15\x7f\xff\x00\x1ftdd", 8);
|
||||
STRCMP_EQUAL(" 0000: 15 7f ff 00 1f 74 64 64 |.....tdd|\n",
|
||||
buffer.toString());
|
||||
}
|
||||
|
||||
TEST(SimpleStringBuffer, addMemoryDumpOneLine)
|
||||
{
|
||||
SimpleStringBuffer buffer;
|
||||
buffer.addMemoryDump("deadbeefdeadbeef", 16);
|
||||
STRCMP_EQUAL(" 0000: 64 65 61 64 62 65 65 66 64 65 61 64 62 65 65 66 |deadbeefdeadbeef|\n",
|
||||
buffer.toString());
|
||||
}
|
||||
|
||||
TEST(SimpleStringBuffer, addMemoryDumpOneHalfLine)
|
||||
{
|
||||
SimpleStringBuffer buffer;
|
||||
buffer.addMemoryDump("deadbeef", 8);
|
||||
STRCMP_EQUAL(" 0000: 64 65 61 64 62 65 65 66 |deadbeef|\n",
|
||||
buffer.toString());
|
||||
}
|
||||
|
||||
TEST(SimpleStringBuffer, addMemoryDumpOneByte)
|
||||
{
|
||||
SimpleStringBuffer buffer;
|
||||
buffer.addMemoryDump("Z", 1);
|
||||
STRCMP_EQUAL(" 0000: 5a |Z|\n",
|
||||
buffer.toString());
|
||||
}
|
||||
|
||||
TEST(SimpleStringBuffer, addMemoryDumpZeroBytes)
|
||||
{
|
||||
SimpleStringBuffer buffer;
|
||||
buffer.addMemoryDump("", 0);
|
||||
STRCMP_EQUAL("", buffer.toString());
|
||||
}
|
||||
|
||||
TEST_GROUP(ReallocBugReported)
|
||||
{
|
||||
MemoryLeakFailureForTest reporter;
|
||||
};
|
||||
|
||||
TEST(ReallocBugReported, CanSafelyDoAReallocWithANewAllocator)
|
||||
{
|
||||
MemoryLeakDetector detector(&reporter);
|
||||
char* mem = detector.allocMemory(defaultNewAllocator(), 5, "file", 1);
|
||||
mem = detector.reallocMemory(defaultNewAllocator(), mem, 19, "file", 1);
|
||||
detector.deallocMemory(defaultNewAllocator(), mem);
|
||||
}
|
||||
|
||||
TEST(ReallocBugReported, CanSafelyDoAReallocWithAMallocAllocator)
|
||||
{
|
||||
MemoryLeakDetector detector(&reporter);
|
||||
char* mem = detector.allocMemory(defaultMallocAllocator(), 5, "file", 1, true);
|
||||
mem = detector.reallocMemory(defaultMallocAllocator(), mem, 19, "file", 1, true);
|
||||
detector.deallocMemory(defaultMallocAllocator(), mem, true);
|
||||
}
|
|
@ -0,0 +1,520 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/TestRegistry.h"
|
||||
#include "CppUTest/TestOutput.h"
|
||||
#include "CppUTest/MemoryLeakWarningPlugin.h"
|
||||
#include "CppUTest/MemoryLeakDetector.h"
|
||||
#include "CppUTest/TestMemoryAllocator.h"
|
||||
#include "CppUTest/TestTestingFixture.h"
|
||||
#include "CppUTest/TestHarness_c.h"
|
||||
#include "CppUTest/SimpleMutex.h"
|
||||
#include "DummyMemoryLeakDetector.h"
|
||||
|
||||
TEST_GROUP(MemoryLeakWarningLocalDetectorTest)
|
||||
{
|
||||
DummyMemoryLeakFailure dummy;
|
||||
};
|
||||
|
||||
TEST(MemoryLeakWarningLocalDetectorTest, localDetectorReturnsNewGlobalWhenNoneWasSet)
|
||||
{
|
||||
MemoryLeakWarningPlugin memoryLeakWarningPlugin("TestMemoryLeakWarningPlugin", NULLPTR);
|
||||
CHECK(NULLPTR != memoryLeakWarningPlugin.getMemoryLeakDetector());
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningLocalDetectorTest, localDetectorIsTheOneSpecifiedInConstructor)
|
||||
{
|
||||
MemoryLeakDetector localDetector(&dummy);
|
||||
MemoryLeakWarningPlugin memoryLeakWarningPlugin("TestMemoryLeakWarningPlugin", &localDetector);
|
||||
POINTERS_EQUAL(&localDetector, memoryLeakWarningPlugin.getMemoryLeakDetector());
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningLocalDetectorTest, localDetectorIsGlobalDetector)
|
||||
{
|
||||
MemoryLeakDetector* globalDetector = MemoryLeakWarningPlugin::getGlobalDetector();
|
||||
MemoryLeakWarningPlugin memoryLeakWarningPlugin("TestMemoryLeakWarningPlugin", NULLPTR);
|
||||
MemoryLeakDetector* localDetector = memoryLeakWarningPlugin.getMemoryLeakDetector();
|
||||
POINTERS_EQUAL(globalDetector, localDetector);
|
||||
}
|
||||
|
||||
static char* leak1;
|
||||
static long* leak2;
|
||||
|
||||
static MemoryLeakDetector* detector;
|
||||
static MemoryLeakWarningPlugin* memPlugin;
|
||||
static TestMemoryAllocator* allocator;
|
||||
|
||||
TEST_GROUP(MemoryLeakWarningTest)
|
||||
{
|
||||
DummyMemoryLeakFailure dummy;
|
||||
TestTestingFixture* fixture;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
fixture = new TestTestingFixture();
|
||||
detector = new MemoryLeakDetector(&dummy);
|
||||
allocator = new TestMemoryAllocator;
|
||||
memPlugin = new MemoryLeakWarningPlugin("TestMemoryLeakWarningPlugin", detector);
|
||||
fixture->installPlugin(memPlugin);
|
||||
memPlugin->enable();
|
||||
|
||||
leak1 = NULLPTR;
|
||||
leak2 = NULLPTR;
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
detector->deallocMemory(allocator, leak1);
|
||||
detector->deallocMemory(allocator, leak2);
|
||||
|
||||
delete fixture;
|
||||
delete memPlugin;
|
||||
delete detector;
|
||||
delete allocator;
|
||||
}
|
||||
};
|
||||
|
||||
static void _testTwoLeaks()
|
||||
{
|
||||
leak1 = detector->allocMemory(allocator, 10);
|
||||
leak2 = (long*) (void*) detector->allocMemory(allocator, 4);
|
||||
}
|
||||
|
||||
#if CPPUTEST_USE_MEM_LEAK_DETECTION
|
||||
|
||||
TEST(MemoryLeakWarningTest, TwoLeaks)
|
||||
{
|
||||
fixture->setTestFunction(_testTwoLeaks);
|
||||
fixture->runAllTests();
|
||||
|
||||
LONGS_EQUAL(1, fixture->getFailureCount());
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
TEST(MemoryLeakWarningTest, TwoLeaks)
|
||||
{
|
||||
fixture->setTestFunction(_testTwoLeaks);
|
||||
fixture->runAllTests();
|
||||
|
||||
LONGS_EQUAL(0, fixture->getFailureCount());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void _testLeakWarningWithPluginDisabled()
|
||||
{
|
||||
memPlugin->expectLeaksInTest(1);
|
||||
leak1 = (char*) cpputest_malloc_location_with_leak_detection(10, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningTest, LeakWarningWithPluginDisabled)
|
||||
{
|
||||
fixture->setTestFunction(_testLeakWarningWithPluginDisabled);
|
||||
|
||||
MemoryLeakWarningPlugin::saveAndDisableNewDeleteOverloads();
|
||||
|
||||
fixture->runAllTests();
|
||||
|
||||
LONGS_EQUAL(0, fixture->getFailureCount());
|
||||
fixture->assertPrintContains("Warning: Expected 1 leak(s), but leak detection was disabled");
|
||||
|
||||
cpputest_free_location_with_leak_detection(leak1, __FILE__, __LINE__);
|
||||
leak1 = NULLPTR;
|
||||
|
||||
MemoryLeakWarningPlugin::restoreNewDeleteOverloads();
|
||||
}
|
||||
|
||||
static void _testIgnore2()
|
||||
{
|
||||
memPlugin->expectLeaksInTest(2);
|
||||
leak1 = detector->allocMemory(allocator, 10);
|
||||
leak2 = (long*) (void*) detector->allocMemory(allocator, 4);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningTest, Ignore2)
|
||||
{
|
||||
fixture->setTestFunction(_testIgnore2);
|
||||
fixture->runAllTests();
|
||||
LONGS_EQUAL(0, fixture->getFailureCount());
|
||||
}
|
||||
|
||||
static void _failAndLeakMemory()
|
||||
{
|
||||
leak1 = detector->allocMemory(allocator, 10);
|
||||
FAIL("");
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningTest, FailingTestDoesNotReportMemoryLeaks)
|
||||
{
|
||||
fixture->setTestFunction(_failAndLeakMemory);
|
||||
fixture->runAllTests();
|
||||
LONGS_EQUAL(1, fixture->getFailureCount());
|
||||
}
|
||||
|
||||
static bool cpputestHasCrashed;
|
||||
|
||||
TEST_GROUP(MemoryLeakWarningGlobalDetectorTest)
|
||||
{
|
||||
MemoryLeakDetector* detector;
|
||||
MemoryLeakFailure* failureReporter;
|
||||
|
||||
DummyMemoryLeakDetector * dummyDetector;
|
||||
MemoryLeakFailure* dummyReporter;
|
||||
|
||||
GlobalMemoryAllocatorStash memoryAllocatorStash;
|
||||
|
||||
static void crashMethod()
|
||||
{
|
||||
cpputestHasCrashed = true;
|
||||
}
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
memoryAllocatorStash.save();
|
||||
detector = MemoryLeakWarningPlugin::getGlobalDetector();
|
||||
failureReporter = MemoryLeakWarningPlugin::getGlobalFailureReporter();
|
||||
|
||||
MemoryLeakWarningPlugin::saveAndDisableNewDeleteOverloads();
|
||||
|
||||
dummyReporter = new DummyMemoryLeakFailure;
|
||||
dummyDetector = new DummyMemoryLeakDetector(dummyReporter);
|
||||
|
||||
UtestShell::setCrashMethod(crashMethod);
|
||||
cpputestHasCrashed = false;
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
MemoryLeakWarningPlugin::restoreNewDeleteOverloads();
|
||||
|
||||
MemoryLeakWarningPlugin::saveAndDisableNewDeleteOverloads();
|
||||
|
||||
if (!DummyMemoryLeakDetector::wasDeleted()) delete dummyDetector;
|
||||
if (!DummyMemoryLeakFailure::wasDeleted()) delete dummyReporter;
|
||||
MemoryLeakWarningPlugin::setGlobalDetector(detector, failureReporter);
|
||||
|
||||
MemoryLeakWarningPlugin::restoreNewDeleteOverloads();
|
||||
|
||||
UtestShell::resetCrashMethod();
|
||||
|
||||
memoryAllocatorStash.restore();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(MemoryLeakWarningGlobalDetectorTest, turnOffNewOverloadsCausesNoAdditionalLeaks)
|
||||
{
|
||||
size_t storedAmountOfLeaks = detector->totalMemoryLeaks(mem_leak_period_all);
|
||||
|
||||
char* arrayMemory = new char[100];
|
||||
char* nonArrayMemory = new char;
|
||||
char* mallocMemory = (char*) cpputest_malloc_location_with_leak_detection(10, "file", 10);
|
||||
char* reallocMemory = (char*) cpputest_realloc_location_with_leak_detection(NULLPTR, 10, "file", 10);
|
||||
|
||||
LONGS_EQUAL(storedAmountOfLeaks, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
|
||||
cpputest_free_location_with_leak_detection(mallocMemory, "file", 10);
|
||||
cpputest_free_location_with_leak_detection(reallocMemory, "file", 10);
|
||||
delete [] arrayMemory;
|
||||
delete nonArrayMemory;
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningGlobalDetectorTest, destroyGlobalDetector)
|
||||
{
|
||||
MemoryLeakWarningPlugin::setGlobalDetector(dummyDetector, dummyReporter);
|
||||
|
||||
MemoryLeakWarningPlugin::destroyGlobalDetector();
|
||||
|
||||
CHECK(DummyMemoryLeakDetector::wasDeleted());
|
||||
CHECK(DummyMemoryLeakFailure::wasDeleted());
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningGlobalDetectorTest, MemoryWarningPluginCanBeSetToDestroyTheGlobalDetector)
|
||||
{
|
||||
MemoryLeakWarningPlugin* plugin = new MemoryLeakWarningPlugin("dummy");
|
||||
plugin->destroyGlobalDetectorAndTurnOffMemoryLeakDetectionInDestructor(true);
|
||||
MemoryLeakWarningPlugin::setGlobalDetector(dummyDetector, dummyReporter);
|
||||
|
||||
delete plugin;
|
||||
|
||||
CHECK(DummyMemoryLeakDetector::wasDeleted());
|
||||
}
|
||||
|
||||
#if CPPUTEST_USE_MEM_LEAK_DETECTION
|
||||
|
||||
TEST(MemoryLeakWarningGlobalDetectorTest, crashOnLeakWithOperatorNew)
|
||||
{
|
||||
MemoryLeakWarningPlugin::setGlobalDetector(dummyDetector, dummyReporter);
|
||||
|
||||
MemoryLeakWarningPlugin::restoreNewDeleteOverloads();
|
||||
|
||||
crash_on_allocation_number(1);
|
||||
char* memory = new char[100];
|
||||
CHECK(cpputestHasCrashed);
|
||||
delete [] memory;
|
||||
MemoryLeakWarningPlugin::saveAndDisableNewDeleteOverloads();
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningGlobalDetectorTest, crashOnLeakWithOperatorNewArray)
|
||||
{
|
||||
MemoryLeakWarningPlugin::setGlobalDetector(dummyDetector, dummyReporter);
|
||||
|
||||
MemoryLeakWarningPlugin::restoreNewDeleteOverloads();
|
||||
|
||||
crash_on_allocation_number(1);
|
||||
char* memory = new char;
|
||||
CHECK(cpputestHasCrashed);
|
||||
delete memory;
|
||||
|
||||
MemoryLeakWarningPlugin::saveAndDisableNewDeleteOverloads();
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningGlobalDetectorTest, crashOnLeakWithOperatorMalloc)
|
||||
{
|
||||
MemoryLeakWarningPlugin::setGlobalDetector(dummyDetector, dummyReporter);
|
||||
|
||||
MemoryLeakWarningPlugin::restoreNewDeleteOverloads();
|
||||
|
||||
crash_on_allocation_number(1);
|
||||
char* memory = (char*) cpputest_malloc(10);
|
||||
CHECK(cpputestHasCrashed);
|
||||
cpputest_free(memory);
|
||||
|
||||
MemoryLeakWarningPlugin::saveAndDisableNewDeleteOverloads();
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningGlobalDetectorTest, gettingTheGlobalDetectorDoesNotRestoreTheMemoryLeakOverloadsWhenTheyWereAlreadyOff)
|
||||
{
|
||||
MemoryLeakWarningPlugin::setGlobalDetector(NULLPTR, NULLPTR);
|
||||
MemoryLeakDetector* temporaryDetector = MemoryLeakWarningPlugin::getGlobalDetector();
|
||||
MemoryLeakFailure* temporaryReporter = MemoryLeakWarningPlugin::getGlobalFailureReporter();
|
||||
|
||||
MemoryLeakWarningPlugin::saveAndDisableNewDeleteOverloads();
|
||||
|
||||
bool areNewDeleteOverloaded = MemoryLeakWarningPlugin::areNewDeleteOverloaded();
|
||||
MemoryLeakWarningPlugin::restoreNewDeleteOverloads();
|
||||
|
||||
CHECK(!areNewDeleteOverloaded);
|
||||
|
||||
delete temporaryReporter;
|
||||
delete temporaryDetector;
|
||||
MemoryLeakWarningPlugin::setGlobalDetector(NULLPTR, NULLPTR);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningGlobalDetectorTest, checkIfTheMemoryLeakOverloadsAreOn)
|
||||
{
|
||||
MemoryLeakWarningPlugin::turnOnDefaultNotThreadSafeNewDeleteOverloads();
|
||||
CHECK(MemoryLeakWarningPlugin::areNewDeleteOverloaded());
|
||||
|
||||
MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningGlobalDetectorTest, checkIfTheMemoryLeakOverloadsAreOff)
|
||||
{
|
||||
MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
|
||||
bool areNewDeleteOverloaded = MemoryLeakWarningPlugin::areNewDeleteOverloaded();
|
||||
|
||||
MemoryLeakWarningPlugin::turnOnDefaultNotThreadSafeNewDeleteOverloads();
|
||||
CHECK(!areNewDeleteOverloaded);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningGlobalDetectorTest, checkIfTheMemoryLeakOverloadsAreOnWithRestore)
|
||||
{
|
||||
MemoryLeakWarningPlugin::restoreNewDeleteOverloads();
|
||||
CHECK(MemoryLeakWarningPlugin::areNewDeleteOverloaded());
|
||||
MemoryLeakWarningPlugin::saveAndDisableNewDeleteOverloads();
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningGlobalDetectorTest, checkIfTheMemoryLeakOverloadsAreOffWithSaveDisable)
|
||||
{
|
||||
MemoryLeakWarningPlugin::saveAndDisableNewDeleteOverloads();
|
||||
CHECK(!MemoryLeakWarningPlugin::areNewDeleteOverloaded());
|
||||
MemoryLeakWarningPlugin::restoreNewDeleteOverloads();
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningGlobalDetectorTest, threadSafeMemoryLeakDetectorOverloadsAreAlsoOverloaded)
|
||||
{
|
||||
MemoryLeakWarningPlugin::restoreNewDeleteOverloads();
|
||||
MemoryLeakWarningPlugin::turnOnThreadSafeNewDeleteOverloads();
|
||||
CHECK(MemoryLeakWarningPlugin::areNewDeleteOverloaded());
|
||||
MemoryLeakWarningPlugin::turnOnDefaultNotThreadSafeNewDeleteOverloads();
|
||||
MemoryLeakWarningPlugin::saveAndDisableNewDeleteOverloads();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if CPPUTEST_USE_STD_CPP_LIB
|
||||
|
||||
TEST(MemoryLeakWarningGlobalDetectorTest, turnOffNewOverloadsNoThrowCausesNoAdditionalLeaks)
|
||||
{
|
||||
#undef new
|
||||
size_t storedAmountOfLeaks = detector->totalMemoryLeaks(mem_leak_period_all);
|
||||
|
||||
char* nonMemoryNoThrow = new (std::nothrow) char;
|
||||
char* nonArrayMemoryNoThrow = new (std::nothrow) char[10];
|
||||
char* nonArrayMemoryThrow = new char[10];
|
||||
|
||||
LONGS_EQUAL(storedAmountOfLeaks, detector->totalMemoryLeaks(mem_leak_period_all));
|
||||
|
||||
::operator delete(nonMemoryNoThrow, std::nothrow);
|
||||
::operator delete[](nonArrayMemoryNoThrow, std::nothrow);
|
||||
::operator delete[](nonArrayMemoryThrow, std::nothrow);
|
||||
#ifdef CPPUTEST_USE_NEW_MACROS
|
||||
#include "CppUTest/MemoryLeakDetectorNewMacros.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CPPUTEST_USE_MEM_LEAK_DETECTION
|
||||
|
||||
static int mutexLockCount = 0;
|
||||
static int mutexUnlockCount = 0;
|
||||
|
||||
static void StubMutexLock(PlatformSpecificMutex)
|
||||
{
|
||||
mutexLockCount++;
|
||||
}
|
||||
|
||||
static void StubMutexUnlock(PlatformSpecificMutex)
|
||||
{
|
||||
mutexUnlockCount++;
|
||||
}
|
||||
|
||||
TEST_GROUP(MemoryLeakWarningThreadSafe)
|
||||
{
|
||||
void setup() _override
|
||||
{
|
||||
UT_PTR_SET(PlatformSpecificMutexLock, StubMutexLock);
|
||||
UT_PTR_SET(PlatformSpecificMutexUnlock, StubMutexUnlock);
|
||||
|
||||
mutexLockCount = 0;
|
||||
mutexUnlockCount = 0;
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
TEST(MemoryLeakWarningThreadSafe, turnOnThreadSafeMallocFreeReallocOverloadsDebug)
|
||||
{
|
||||
size_t storedAmountOfLeaks = MemoryLeakWarningPlugin::getGlobalDetector()->totalMemoryLeaks(mem_leak_period_all);
|
||||
|
||||
MemoryLeakWarningPlugin::turnOnThreadSafeNewDeleteOverloads();
|
||||
|
||||
int *n = (int*) cpputest_malloc(sizeof(int));
|
||||
|
||||
LONGS_EQUAL(storedAmountOfLeaks + 1, MemoryLeakWarningPlugin::getGlobalDetector()->totalMemoryLeaks(mem_leak_period_all));
|
||||
CHECK_EQUAL(1, mutexLockCount);
|
||||
CHECK_EQUAL(1, mutexUnlockCount);
|
||||
|
||||
n = (int*) cpputest_realloc(n, sizeof(int)*3);
|
||||
|
||||
LONGS_EQUAL(storedAmountOfLeaks + 1, MemoryLeakWarningPlugin::getGlobalDetector()->totalMemoryLeaks(mem_leak_period_all));
|
||||
CHECK_EQUAL(2, mutexLockCount);
|
||||
CHECK_EQUAL(2, mutexUnlockCount);
|
||||
|
||||
cpputest_free(n);
|
||||
|
||||
LONGS_EQUAL(storedAmountOfLeaks, MemoryLeakWarningPlugin::getGlobalDetector()->totalMemoryLeaks(mem_leak_period_all));
|
||||
CHECK_EQUAL(3, mutexLockCount);
|
||||
CHECK_EQUAL(3, mutexUnlockCount);
|
||||
|
||||
MemoryLeakWarningPlugin::turnOnDefaultNotThreadSafeNewDeleteOverloads();
|
||||
}
|
||||
|
||||
TEST(MemoryLeakWarningThreadSafe, turnOnThreadSafeNewDeleteOverloadsDebug)
|
||||
{
|
||||
size_t storedAmountOfLeaks = MemoryLeakWarningPlugin::getGlobalDetector()->totalMemoryLeaks(mem_leak_period_all);
|
||||
|
||||
MemoryLeakWarningPlugin::turnOnThreadSafeNewDeleteOverloads();
|
||||
|
||||
int *n = new int;
|
||||
char *str = new char[20];
|
||||
|
||||
LONGS_EQUAL(storedAmountOfLeaks + 2, MemoryLeakWarningPlugin::getGlobalDetector()->totalMemoryLeaks(mem_leak_period_all));
|
||||
CHECK_EQUAL(2, mutexLockCount);
|
||||
CHECK_EQUAL(2, mutexUnlockCount);
|
||||
|
||||
delete [] str;
|
||||
delete n;
|
||||
|
||||
LONGS_EQUAL(storedAmountOfLeaks, MemoryLeakWarningPlugin::getGlobalDetector()->totalMemoryLeaks(mem_leak_period_all));
|
||||
CHECK_EQUAL(4, mutexLockCount);
|
||||
CHECK_EQUAL(4, mutexUnlockCount);
|
||||
|
||||
MemoryLeakWarningPlugin::turnOnDefaultNotThreadSafeNewDeleteOverloads();
|
||||
}
|
||||
|
||||
#ifdef __clang__
|
||||
|
||||
IGNORE_TEST(MemoryLeakWarningThreadSafe, turnOnThreadSafeNewDeleteOverloads)
|
||||
{
|
||||
/* Clang misbehaves with -O2 - it will not overload operator new or
|
||||
* operator new[] no matter what. Therefore, this test is must be ignored.
|
||||
*/
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
TEST(MemoryLeakWarningThreadSafe, turnOnThreadSafeNewDeleteOverloads)
|
||||
{
|
||||
#undef new
|
||||
|
||||
size_t storedAmountOfLeaks = MemoryLeakWarningPlugin::getGlobalDetector()->totalMemoryLeaks(mem_leak_period_all);
|
||||
MemoryLeakWarningPlugin::turnOnThreadSafeNewDeleteOverloads();
|
||||
|
||||
int *n = new int;
|
||||
int *n_nothrow = new (std::nothrow) int;
|
||||
char *str = new char[20];
|
||||
char *str_nothrow = new (std::nothrow) char[20];
|
||||
|
||||
LONGS_EQUAL(storedAmountOfLeaks + 4, MemoryLeakWarningPlugin::getGlobalDetector()->totalMemoryLeaks(mem_leak_period_all));
|
||||
CHECK_EQUAL(4, mutexLockCount);
|
||||
CHECK_EQUAL(4, mutexUnlockCount);
|
||||
|
||||
delete [] str_nothrow;
|
||||
delete [] str;
|
||||
delete n;
|
||||
delete n_nothrow;
|
||||
|
||||
LONGS_EQUAL(storedAmountOfLeaks, MemoryLeakWarningPlugin::getGlobalDetector()->totalMemoryLeaks(mem_leak_period_all));
|
||||
CHECK_EQUAL(8, mutexLockCount);
|
||||
CHECK_EQUAL(8, mutexUnlockCount);
|
||||
|
||||
MemoryLeakWarningPlugin::turnOnDefaultNotThreadSafeNewDeleteOverloads();
|
||||
#ifdef CPPUTEST_USE_NEW_MACROS
|
||||
#include "CppUTest/MemoryLeakDetectorNewMacros.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,506 @@
|
|||
#include "CppUTest/TestHarness.h"
|
||||
#include "CppUTest/TestMemoryAllocator.h"
|
||||
#include "CppUTest/MemoryLeakDetector.h"
|
||||
#include "CppUTest/TestOutput.h"
|
||||
#include "CppUTest/TestRegistry.h"
|
||||
#include "CppUTest/PlatformSpecificFunctions.h"
|
||||
#include "CppUTest/TestTestingFixture.h"
|
||||
#include "AllocationInCppFile.h"
|
||||
|
||||
#include "CppUTest/TestHarness_c.h"
|
||||
#include "AllocationInCFile.h"
|
||||
|
||||
TEST_GROUP(BasicBehavior)
|
||||
{
|
||||
};
|
||||
|
||||
TEST(BasicBehavior, CanDeleteNullPointers)
|
||||
{
|
||||
delete (char*) NULLPTR;
|
||||
delete [] (char*) NULLPTR;
|
||||
}
|
||||
|
||||
#if CPPUTEST_USE_MEM_LEAK_DETECTION
|
||||
|
||||
CPPUTEST_DO_NOT_SANITIZE_ADDRESS
|
||||
static void deleteArrayInvalidatesMemory()
|
||||
{
|
||||
unsigned char* memory = new unsigned char[10];
|
||||
PlatformSpecificMemset(memory, 0xAB, 10);
|
||||
delete [] memory;
|
||||
CHECK(memory[5] != 0xCB);
|
||||
}
|
||||
|
||||
TEST(BasicBehavior, deleteArrayInvalidatesMemory)
|
||||
{
|
||||
deleteArrayInvalidatesMemory();
|
||||
}
|
||||
|
||||
CPPUTEST_DO_NOT_SANITIZE_ADDRESS
|
||||
static void deleteInvalidatesMemory()
|
||||
{
|
||||
unsigned char* memory = new unsigned char;
|
||||
*memory = 0xAD;
|
||||
delete memory;
|
||||
CHECK(*memory != 0xAD);
|
||||
}
|
||||
|
||||
TEST(BasicBehavior, deleteInvalidatesMemory)
|
||||
{
|
||||
deleteInvalidatesMemory();
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
TEST(BasicBehavior, DeleteWithSizeParameterWorks)
|
||||
{
|
||||
char* charMemory = new char;
|
||||
char* charArrayMemory = new char[10];
|
||||
::operator delete(charMemory, sizeof(char));
|
||||
::operator delete[](charArrayMemory, sizeof(char)* 10);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void deleteUnallocatedMemory()
|
||||
{
|
||||
delete (char*) 0x1234678;
|
||||
FAIL("Should never come here"); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(BasicBehavior, deleteWillNotThrowAnExceptionWhenDeletingUnallocatedMemoryButCanStillCauseTestFailures)
|
||||
{
|
||||
/*
|
||||
* Test failure might cause an exception. But according to C++ standard, you aren't allowed
|
||||
* to throw exceptions in the delete function. If you do that, it will call std::terminate.
|
||||
* Therefore, the delete will need to fail without exceptions.
|
||||
*/
|
||||
MemoryLeakFailure* defaultReporter = MemoryLeakWarningPlugin::getGlobalFailureReporter();
|
||||
TestTestingFixture fixture;
|
||||
fixture.setTestFunction(deleteUnallocatedMemory);
|
||||
fixture.runAllTests();
|
||||
LONGS_EQUAL(1, fixture.getFailureCount());
|
||||
POINTERS_EQUAL(defaultReporter, MemoryLeakWarningPlugin::getGlobalFailureReporter());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CPPUTEST_USE_MALLOC_MACROS
|
||||
|
||||
/* This include is added because *sometimes* the cstdlib does an #undef. This should have been prevented */
|
||||
#if CPPUTEST_USE_STD_CPP_LIB
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
TEST(BasicBehavior, bothMallocAndFreeAreOverloaded)
|
||||
{
|
||||
void* memory = cpputest_malloc_location(sizeof(char), "file", 10);
|
||||
free(memory);
|
||||
|
||||
memory = malloc(sizeof(unsigned char));
|
||||
cpputest_free_location(memory, "file", 10);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if CPPUTEST_USE_MEM_LEAK_DETECTION
|
||||
|
||||
CPPUTEST_DO_NOT_SANITIZE_ADDRESS
|
||||
static void freeInvalidatesMemory()
|
||||
{
|
||||
unsigned char* memory = (unsigned char*) cpputest_malloc(sizeof(unsigned char));
|
||||
*memory = 0xAD;
|
||||
cpputest_free(memory);
|
||||
CHECK(*memory != 0xAD);
|
||||
}
|
||||
|
||||
TEST(BasicBehavior, freeInvalidatesMemory)
|
||||
{
|
||||
freeInvalidatesMemory();
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_GROUP(MemoryLeakOverridesToBeUsedInProductionCode)
|
||||
{
|
||||
MemoryLeakDetector* memLeakDetector;
|
||||
void setup() _override
|
||||
{
|
||||
memLeakDetector = MemoryLeakWarningPlugin::getGlobalDetector();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#if ! defined CPPUTEST_MEM_LEAK_DETECTION_DISABLED || ! CPPUTEST_MEM_LEAK_DETECTION_DISABLED
|
||||
|
||||
#ifdef CPPUTEST_USE_NEW_MACROS
|
||||
#undef new
|
||||
#endif
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, newDeleteOverloadsWithIntLineWorks)
|
||||
{
|
||||
const int line = 42;
|
||||
char* leak = new("TestFile.cpp", line) char;
|
||||
|
||||
size_t memLeaks = memLeakDetector->totalMemoryLeaks(mem_leak_period_checking);
|
||||
STRCMP_NOCASE_CONTAINS("Allocated at: TestFile.cpp and line: 42.", memLeakDetector->report(mem_leak_period_checking));
|
||||
|
||||
::operator delete (leak, "TestFile.cpp", line);
|
||||
|
||||
LONGS_EQUAL(memLeaks-1, memLeakDetector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
}
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, newDeleteOverloadsWithSizeTLineWorks)
|
||||
{
|
||||
const size_t line = 42;
|
||||
char* leak = new("TestFile.cpp", line) char;
|
||||
|
||||
size_t memLeaks = memLeakDetector->totalMemoryLeaks(mem_leak_period_checking);
|
||||
STRCMP_NOCASE_CONTAINS("Allocated at: TestFile.cpp and line: 42.", memLeakDetector->report(mem_leak_period_checking));
|
||||
|
||||
::operator delete (leak, "TestFile.cpp", line);
|
||||
|
||||
LONGS_EQUAL(memLeaks-1, memLeakDetector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
}
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, newDeleteArrayOverloadsWithIntLineWorks)
|
||||
{
|
||||
const int line = 42;
|
||||
char* leak = new("TestFile.cpp", line) char[10];
|
||||
|
||||
size_t memLeaks = memLeakDetector->totalMemoryLeaks(mem_leak_period_checking);
|
||||
STRCMP_NOCASE_CONTAINS("Allocated at: TestFile.cpp and line: 42.", memLeakDetector->report(mem_leak_period_checking));
|
||||
|
||||
::operator delete [] (leak, "TestFile.cpp", line);
|
||||
|
||||
LONGS_EQUAL(memLeaks-1, memLeakDetector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
}
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, newDeleteArrayOverloadsWithSizeTLineWorks)
|
||||
{
|
||||
const size_t line = 42;
|
||||
char* leak = new("TestFile.cpp", line) char[10];
|
||||
|
||||
size_t memLeaks = memLeakDetector->totalMemoryLeaks(mem_leak_period_checking);
|
||||
STRCMP_NOCASE_CONTAINS("Allocated at: TestFile.cpp and line: 42.", memLeakDetector->report(mem_leak_period_checking));
|
||||
|
||||
::operator delete [] (leak, "TestFile.cpp", line);
|
||||
|
||||
LONGS_EQUAL(memLeaks-1, memLeakDetector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
}
|
||||
#ifdef CPPUTEST_USE_NEW_MACROS
|
||||
#include "CppUTest/MemoryLeakDetectorNewMacros.h" // redefine the 'new' macro
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CPPUTEST_USE_MALLOC_MACROS
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, MallocOverrideIsUsed)
|
||||
{
|
||||
size_t memLeaks = memLeakDetector->totalMemoryLeaks(mem_leak_period_checking);
|
||||
void* memory = malloc(10);
|
||||
LONGS_EQUAL(memLeaks+1, memLeakDetector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
free (memory);
|
||||
}
|
||||
|
||||
#ifdef CPPUTEST_USE_STRDUP_MACROS
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, StrdupOverrideIsUsed)
|
||||
{
|
||||
size_t memLeaks = memLeakDetector->totalMemoryLeaks(mem_leak_period_checking);
|
||||
char* memory = strdup("0123456789");
|
||||
LONGS_EQUAL(memLeaks+1, memLeakDetector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
free (memory);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, StrndupOverrideIsUsed)
|
||||
{
|
||||
size_t memLeaks = memLeakDetector->totalMemoryLeaks(mem_leak_period_checking);
|
||||
char* memory = strndup("0123456789", 10);
|
||||
LONGS_EQUAL(memLeaks+1, memLeakDetector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
free (memory);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, UseNativeMallocByTemporarlySwitchingOffMalloc)
|
||||
{
|
||||
size_t memLeaks = memLeakDetector->totalMemoryLeaks(mem_leak_period_checking);
|
||||
#ifdef CPPUTEST_USE_MALLOC_MACROS
|
||||
#undef malloc
|
||||
#undef free
|
||||
#endif
|
||||
|
||||
#if CPPUTEST_USE_STD_C_LIB
|
||||
void* memory = malloc(10);
|
||||
LONGS_EQUAL(memLeaks, memLeakDetector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
free (memory);
|
||||
#else
|
||||
void* memory = PlatformSpecificMalloc(10);
|
||||
LONGS_EQUAL(memLeaks, memLeakDetector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
PlatformSpecificFree (memory);
|
||||
#endif
|
||||
|
||||
#ifdef CPPUTEST_USE_MALLOC_MACROS
|
||||
#include "CppUTest/MemoryLeakDetectorMallocMacros.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
/* TEST... allowing for a new overload in a class */
|
||||
class NewDummyClass
|
||||
{
|
||||
public:
|
||||
static bool overloaded_new_called;
|
||||
|
||||
#ifdef CPPUTEST_USE_NEW_MACROS
|
||||
#undef new
|
||||
#endif
|
||||
void* operator new (size_t size)
|
||||
#ifdef CPPUTEST_USE_NEW_MACROS
|
||||
#include "CppUTest/MemoryLeakDetectorNewMacros.h"
|
||||
#endif
|
||||
{
|
||||
overloaded_new_called = true;
|
||||
return malloc(size);
|
||||
}
|
||||
void dummyFunction()
|
||||
{
|
||||
char* memory = new char;
|
||||
delete memory;
|
||||
}
|
||||
};
|
||||
bool NewDummyClass::overloaded_new_called = false;
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, NoSideEffectsFromTurningOffNewMacros)
|
||||
{
|
||||
/*
|
||||
* Interesting effect of wrapping the operator new around the macro is
|
||||
* that the actual new that is called is a different one than expected.
|
||||
*
|
||||
* The overloaded operator new doesn't actually ever get called.
|
||||
*
|
||||
* This might come as a surprise, so it is important to realize!
|
||||
*/
|
||||
NewDummyClass dummy;
|
||||
dummy.dummyFunction();
|
||||
// CHECK(dummy.overloaded_new_called);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, UseNativeNewByTemporarlySwitchingOffNew)
|
||||
{
|
||||
#ifdef CPPUTEST_USE_NEW_MACROS
|
||||
#undef new
|
||||
#undef delete
|
||||
#endif
|
||||
char* memory = new char[10];
|
||||
delete [] memory;
|
||||
#ifdef CPPUTEST_USE_NEW_MACROS
|
||||
#include "CppUTest/MemoryLeakDetectorNewMacros.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if CPPUTEST_USE_MEM_LEAK_DETECTION
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, OperatorNewMacroOverloadViaIncludeFileWorks)
|
||||
{
|
||||
char* leak = newAllocation();
|
||||
STRCMP_NOCASE_CONTAINS("AllocationInCppFile.cpp", memLeakDetector->report(mem_leak_period_checking));
|
||||
delete leak;
|
||||
}
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, OperatorNewArrayMacroOverloadViaIncludeFileWorks)
|
||||
{
|
||||
char* leak = newArrayAllocation();
|
||||
STRCMP_NOCASE_CONTAINS("AllocationInCppFile.cpp", memLeakDetector->report(mem_leak_period_checking));
|
||||
delete[] leak;
|
||||
}
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, MallocOverrideWorks)
|
||||
{
|
||||
char* leak = mallocAllocation();
|
||||
STRCMP_NOCASE_CONTAINS("AllocationInCFile.c", memLeakDetector->report(mem_leak_period_checking));
|
||||
freeAllocation(leak);
|
||||
}
|
||||
|
||||
#ifdef CPPUTEST_USE_STRDUP_MACROS
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, StrdupOverrideWorks)
|
||||
{
|
||||
char* leak = strdupAllocation();
|
||||
STRCMP_NOCASE_CONTAINS("AllocationInCFile.c", memLeakDetector->report(mem_leak_period_checking));
|
||||
freeAllocation(leak);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, StrndupOverrideWorks)
|
||||
{
|
||||
char* leak = strndupAllocation();
|
||||
STRCMP_NOCASE_CONTAINS("AllocationInCFile.c", memLeakDetector->report(mem_leak_period_checking));
|
||||
freeAllocation(leak);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, MallocWithButFreeWithoutLeakDetectionDoesntCrash)
|
||||
{
|
||||
char* leak = mallocAllocation();
|
||||
freeAllocationWithoutMacro(leak);
|
||||
LONGS_EQUAL(2, memLeakDetector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
memLeakDetector->removeMemoryLeakInformationWithoutCheckingOrDeallocatingTheMemoryButDeallocatingTheAccountInformation(getCurrentMallocAllocator(), leak, true);
|
||||
}
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, OperatorNewOverloadingWithoutMacroWorks)
|
||||
{
|
||||
char* leak = newAllocationWithoutMacro();
|
||||
STRCMP_CONTAINS("unknown", memLeakDetector->report(mem_leak_period_checking));
|
||||
delete leak;
|
||||
}
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, OperatorNewArrayOverloadingWithoutMacroWorks)
|
||||
{
|
||||
char* leak = newArrayAllocationWithoutMacro();
|
||||
STRCMP_CONTAINS("unknown", memLeakDetector->report(mem_leak_period_checking));
|
||||
delete[] leak;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
TEST(MemoryLeakOverridesToBeUsedInProductionCode, MemoryOverridesAreDisabled)
|
||||
{
|
||||
char* leak = newAllocation();
|
||||
STRCMP_EQUAL("No memory leaks were detected.", memLeakDetector->report(mem_leak_period_checking));
|
||||
delete leak;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST_GROUP(OutOfMemoryTestsForOperatorNew)
|
||||
{
|
||||
TestMemoryAllocator* no_memory_allocator;
|
||||
GlobalMemoryAllocatorStash memoryAllocatorStash;
|
||||
void setup() _override
|
||||
{
|
||||
memoryAllocatorStash.save();
|
||||
no_memory_allocator = new NullUnknownAllocator;
|
||||
setCurrentNewAllocator(no_memory_allocator);
|
||||
setCurrentNewArrayAllocator(no_memory_allocator);
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
memoryAllocatorStash.restore();
|
||||
delete no_memory_allocator;
|
||||
}
|
||||
};
|
||||
|
||||
#if CPPUTEST_USE_MEM_LEAK_DETECTION
|
||||
|
||||
#if CPPUTEST_USE_STD_CPP_LIB
|
||||
|
||||
TEST(OutOfMemoryTestsForOperatorNew, FailingNewOperatorThrowsAnExceptionWhenUsingStdCppNew)
|
||||
{
|
||||
CHECK_THROWS(std::bad_alloc, new char);
|
||||
}
|
||||
|
||||
TEST(OutOfMemoryTestsForOperatorNew, FailingNewArrayOperatorThrowsAnExceptionWhenUsingStdCppNew)
|
||||
{
|
||||
CHECK_THROWS(std::bad_alloc, new char[10]);
|
||||
}
|
||||
|
||||
TEST_GROUP(TestForExceptionsInConstructor)
|
||||
{
|
||||
};
|
||||
|
||||
TEST(TestForExceptionsInConstructor,ConstructorThrowsAnException)
|
||||
{
|
||||
CHECK_THROWS(int, new ClassThatThrowsAnExceptionInTheConstructor);
|
||||
}
|
||||
|
||||
TEST(TestForExceptionsInConstructor,ConstructorThrowsAnExceptionAllocatedAsArray)
|
||||
{
|
||||
CHECK_THROWS(int, new ClassThatThrowsAnExceptionInTheConstructor[10]);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
TEST(OutOfMemoryTestsForOperatorNew, FailingNewOperatorReturnsNull)
|
||||
{
|
||||
POINTERS_EQUAL(NULLPTR, new char);
|
||||
}
|
||||
|
||||
TEST(OutOfMemoryTestsForOperatorNew, FailingNewArrayOperatorReturnsNull)
|
||||
{
|
||||
POINTERS_EQUAL(NULLPTR, new char[10]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#undef new
|
||||
|
||||
#if CPPUTEST_USE_STD_CPP_LIB
|
||||
|
||||
|
||||
/*
|
||||
* CLang 4.2 and memory allocation.
|
||||
*
|
||||
* Clang 4.2 has done some optimizations to their memory management that actually causes slightly different behavior than what the C++ Standard defines.
|
||||
* Usually this is not a problem... but in this case, it is a problem.
|
||||
*
|
||||
* More information about the optimization can be found at: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3433.html
|
||||
* We've done a bug-report to clang to fix some of this non-standard behavior, which is open at: http://llvm.org/bugs/show_bug.cgi?id=15541
|
||||
*
|
||||
* I very much hope that nobody would actually ever hit this bug/optimization as it is hard to figure out what is going on.
|
||||
*
|
||||
* The original test simply did "new char". Because the memory wasn't assigned to anything and is local in context, the optimization *doesn't* call
|
||||
* the operator new overload. Because it doesn't call the operator new (optimizing away a call to operator new), therefore the method wouldn't throw an exception
|
||||
* and therefore this test failed.
|
||||
*
|
||||
* The first attempt to fix this is to create a local variable and assigned the memory to that. Also this doesn't work as it still detects the allocation is
|
||||
* local and optimizes away the memory call.
|
||||
*
|
||||
* Now, we assign the memory on some static global which fools the optimizer to believe that it isn't local and it stops optimizing the operator new call.
|
||||
*
|
||||
* We (Bas Vodde and Terry Yin) suspect that in a real product, you wouldn't be able to detect the optimization and it's breaking of Standard C++. Therefore,
|
||||
* for now, we keep this hack in the test to fool the optimizer and hope nobody will ever notice this 'optimizer behavior' in a real product.
|
||||
*
|
||||
* Update 2020: The gcc compiler implemented the same optimization, but it seems to be slightly smarter and discovered that we assign to a static variable.
|
||||
* Thus it still optimized away the call to operator new. Did another bug report, but it is unlikely to get fixed. You can find it at:
|
||||
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94671
|
||||
*
|
||||
* Changed the variable to be external so it would definitively be a mistake to optimize the call.
|
||||
*
|
||||
*/
|
||||
|
||||
extern char* some_memory;
|
||||
char* some_memory;
|
||||
|
||||
TEST(OutOfMemoryTestsForOperatorNew, FailingNewOperatorThrowsAnExceptionWhenUsingStdCppNewWithoutOverride)
|
||||
{
|
||||
CHECK_THROWS(std::bad_alloc, some_memory = new char);
|
||||
}
|
||||
|
||||
TEST(OutOfMemoryTestsForOperatorNew, FailingNewArrayOperatorThrowsAnExceptionWhenUsingStdCppNewWithoutOverride)
|
||||
{
|
||||
CHECK_THROWS(std::bad_alloc, some_memory = new char[10]);
|
||||
}
|
||||
|
||||
TEST(OutOfMemoryTestsForOperatorNew, FailingNewOperatorReturnsNullWithoutOverride)
|
||||
{
|
||||
POINTERS_EQUAL(NULLPTR, new (std::nothrow) char);
|
||||
}
|
||||
|
||||
TEST(OutOfMemoryTestsForOperatorNew, FailingNewArrayOperatorReturnsNullWithoutOverride)
|
||||
{
|
||||
POINTERS_EQUAL(NULLPTR, new (std::nothrow) char[10]);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
TEST(OutOfMemoryTestsForOperatorNew, FailingNewOperatorReturnsNullWithoutOverride)
|
||||
{
|
||||
POINTERS_EQUAL(NULLPTR, new char);
|
||||
}
|
||||
|
||||
TEST(OutOfMemoryTestsForOperatorNew, FailingNewArrayOperatorReturnsNullWithoutOverride)
|
||||
{
|
||||
POINTERS_EQUAL(NULLPTR, new char[10]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/TestRegistry.h"
|
||||
#include "CppUTest/TestOutput.h"
|
||||
#include "CppUTest/TestTestingFixture.h"
|
||||
|
||||
#define GENERIC_PLUGIN "GenericPlugin"
|
||||
#define GENERIC_PLUGIN2 "GenericPlugin2"
|
||||
#define GENERIC_PLUGIN3 "GenericPlugin3"
|
||||
|
||||
static int sequenceNumber;
|
||||
|
||||
class DummyPlugin: public TestPlugin
|
||||
{
|
||||
public:
|
||||
DummyPlugin(const SimpleString& name) :
|
||||
TestPlugin(name), preAction(0), preActionSequence(0), postAction(0), postActionSequence(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void preTestAction(UtestShell&, TestResult&) _override
|
||||
{
|
||||
preAction++;
|
||||
preActionSequence = sequenceNumber++;
|
||||
}
|
||||
|
||||
virtual void postTestAction(UtestShell&, TestResult&) _override
|
||||
{
|
||||
postAction++;
|
||||
postActionSequence = sequenceNumber++;
|
||||
}
|
||||
|
||||
int preAction;
|
||||
int preActionSequence;
|
||||
int postAction;
|
||||
int postActionSequence;
|
||||
};
|
||||
|
||||
class DummyPluginWhichAcceptsParameters: public DummyPlugin
|
||||
{
|
||||
public:
|
||||
DummyPluginWhichAcceptsParameters(const SimpleString& name) :
|
||||
DummyPlugin(name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool parseArguments(int ac, const char *const *av, int index) _override
|
||||
{
|
||||
SimpleString argument (av[index]);
|
||||
if (argument == "-paccept")
|
||||
return true;
|
||||
return TestPlugin::parseArguments(ac, av, index);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TEST_GROUP(PluginTest)
|
||||
{
|
||||
DummyPlugin* firstPlugin;
|
||||
DummyPluginWhichAcceptsParameters* secondPlugin;
|
||||
DummyPlugin* thirdPlugin;
|
||||
TestTestingFixture *genFixture;
|
||||
TestRegistry* registry;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
firstPlugin = new DummyPlugin(GENERIC_PLUGIN);
|
||||
secondPlugin = new DummyPluginWhichAcceptsParameters(GENERIC_PLUGIN2);
|
||||
thirdPlugin = new DummyPlugin(GENERIC_PLUGIN3);
|
||||
genFixture = new TestTestingFixture;
|
||||
registry = genFixture->getRegistry();
|
||||
registry->installPlugin(firstPlugin);
|
||||
sequenceNumber = 1;
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
delete firstPlugin;
|
||||
delete secondPlugin;
|
||||
delete thirdPlugin;
|
||||
delete genFixture;
|
||||
}
|
||||
};
|
||||
|
||||
#define GENERIC_PLUGIN "GenericPlugin"
|
||||
|
||||
TEST(PluginTest, PluginHasName)
|
||||
{
|
||||
STRCMP_EQUAL(GENERIC_PLUGIN, firstPlugin->getName().asCharString());
|
||||
}
|
||||
|
||||
TEST(PluginTest, InstallPlugin)
|
||||
{
|
||||
CHECK_EQUAL(firstPlugin, registry->getFirstPlugin());
|
||||
CHECK_EQUAL(firstPlugin, registry->getPluginByName(GENERIC_PLUGIN));
|
||||
LONGS_EQUAL(1, registry->countPlugins());
|
||||
}
|
||||
|
||||
TEST(PluginTest, InstallMultiplePlugins)
|
||||
{
|
||||
registry->installPlugin(thirdPlugin);
|
||||
CHECK_EQUAL(firstPlugin, registry->getPluginByName(GENERIC_PLUGIN));
|
||||
CHECK_EQUAL(thirdPlugin, registry->getPluginByName(GENERIC_PLUGIN3));
|
||||
POINTERS_EQUAL(NULLPTR, registry->getPluginByName("I do not exist"));
|
||||
}
|
||||
|
||||
TEST(PluginTest, ActionsAllRun)
|
||||
{
|
||||
genFixture->runAllTests();
|
||||
genFixture->runAllTests();
|
||||
CHECK_EQUAL(2, firstPlugin->preAction);
|
||||
CHECK_EQUAL(2, firstPlugin->postAction);
|
||||
}
|
||||
|
||||
TEST(PluginTest, Sequence)
|
||||
{
|
||||
registry->installPlugin(thirdPlugin);
|
||||
genFixture->runAllTests();
|
||||
CHECK_EQUAL(1, thirdPlugin->preActionSequence);
|
||||
CHECK_EQUAL(2, firstPlugin->preActionSequence);
|
||||
CHECK_EQUAL(3, firstPlugin->postActionSequence);
|
||||
CHECK_EQUAL(4, thirdPlugin->postActionSequence);
|
||||
LONGS_EQUAL(2, registry->countPlugins());
|
||||
}
|
||||
|
||||
TEST(PluginTest, RemovePluginByName)
|
||||
{
|
||||
registry->installPlugin(secondPlugin);
|
||||
registry->installPlugin(thirdPlugin);
|
||||
LONGS_EQUAL(3, registry->countPlugins());
|
||||
registry->removePluginByName(GENERIC_PLUGIN2);
|
||||
LONGS_EQUAL(2, registry->countPlugins());
|
||||
}
|
||||
|
||||
struct DefaultPlugin : public TestPlugin
|
||||
{
|
||||
DefaultPlugin() : TestPlugin("default") {}
|
||||
};
|
||||
|
||||
TEST(PluginTest, DefaultPostTestActionDoesntDoAnything)
|
||||
{
|
||||
DefaultPlugin defaultPlugin;
|
||||
registry->installPlugin(&defaultPlugin);
|
||||
genFixture->runAllTests();
|
||||
}
|
||||
|
||||
TEST(PluginTest, DisablesPluginsDontRun)
|
||||
{
|
||||
registry->installPlugin(thirdPlugin);
|
||||
thirdPlugin->disable();
|
||||
genFixture->runAllTests();
|
||||
CHECK(!thirdPlugin->isEnabled());
|
||||
thirdPlugin->enable();
|
||||
genFixture->runAllTests();
|
||||
CHECK_EQUAL(2, firstPlugin->preAction);
|
||||
CHECK_EQUAL(1, thirdPlugin->preAction);
|
||||
CHECK(thirdPlugin->isEnabled());
|
||||
}
|
||||
|
||||
TEST(PluginTest, ParseArgumentsForUnknownArgumentsFails)
|
||||
{
|
||||
registry->installPlugin(secondPlugin);
|
||||
const char *cmd_line[] = {"nonsense", "andmorenonsense"};
|
||||
CHECK(registry->getFirstPlugin()->parseAllArguments(2, const_cast<char**>(cmd_line), 0) == false); /* cover non-const wrapper, too */
|
||||
}
|
||||
|
||||
TEST(PluginTest, ParseArgumentsContinuesAndSucceedsWhenAPluginCanParse)
|
||||
{
|
||||
registry->installPlugin(secondPlugin);
|
||||
const char *cmd_line[] = {"-paccept", "andmorenonsense"};
|
||||
CHECK(registry->getFirstPlugin()->parseAllArguments(2, const_cast<char**>(cmd_line), 0)); /* cover non-const wrapper, too */
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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"
|
||||
|
||||
TEST_GROUP(PreprocessorTest)
|
||||
{
|
||||
};
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
#include "CppUTest/TestHarness.h"
|
||||
#include "CppUTest/TestRegistry.h"
|
||||
#include "CppUTest/TestOutput.h"
|
||||
#include "CppUTest/TestPlugin.h"
|
||||
|
||||
static void orig_func1()
|
||||
{
|
||||
}
|
||||
|
||||
static void stub_func1()
|
||||
{
|
||||
}
|
||||
|
||||
static void orig_func2()
|
||||
{
|
||||
}
|
||||
|
||||
static void stub_func2()
|
||||
{
|
||||
}
|
||||
|
||||
static void (*fp1)();
|
||||
static void (*fp2)();
|
||||
|
||||
TEST_GROUP(SetPointerPluginTest)
|
||||
{
|
||||
SetPointerPlugin* plugin_;
|
||||
TestRegistry* myRegistry_;
|
||||
StringBufferTestOutput* output_;
|
||||
TestResult* result_;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
myRegistry_ = new TestRegistry();
|
||||
plugin_ = new SetPointerPlugin("TestSetPlugin");
|
||||
myRegistry_->setCurrentRegistry(myRegistry_);
|
||||
myRegistry_->installPlugin(plugin_);
|
||||
output_ = new StringBufferTestOutput();
|
||||
result_ = new TestResult(*output_);
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
myRegistry_->setCurrentRegistry(NULLPTR);
|
||||
delete myRegistry_;
|
||||
delete plugin_;
|
||||
delete output_;
|
||||
delete result_;
|
||||
}
|
||||
};
|
||||
|
||||
class FunctionPointerUtest : public Utest
|
||||
{
|
||||
public:
|
||||
void setup() _override
|
||||
{
|
||||
UT_PTR_SET(fp1, stub_func1);
|
||||
UT_PTR_SET(fp2, stub_func2);
|
||||
UT_PTR_SET(fp2, stub_func2);
|
||||
}
|
||||
void testBody() _override
|
||||
{
|
||||
CHECK(fp1 == stub_func1);
|
||||
CHECK(fp2 == stub_func2);
|
||||
}
|
||||
};
|
||||
|
||||
class FunctionPointerUtestShell: public UtestShell
|
||||
{
|
||||
public:
|
||||
virtual Utest* createTest() _override
|
||||
{
|
||||
return new FunctionPointerUtest();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(SetPointerPluginTest, installTwoFunctionPointer)
|
||||
{
|
||||
FunctionPointerUtestShell *tst = new FunctionPointerUtestShell();
|
||||
|
||||
fp1 = orig_func1;
|
||||
fp2 = orig_func2;
|
||||
myRegistry_->addTest(tst);
|
||||
myRegistry_->runAllTests(*result_);
|
||||
CHECK(fp1 == orig_func1);
|
||||
CHECK(fp2 == orig_func2);
|
||||
LONGS_EQUAL(0, result_->getFailureCount());
|
||||
LONGS_EQUAL(2, result_->getCheckCount());
|
||||
delete tst;
|
||||
}
|
||||
|
||||
class MaxFunctionPointerUtest : public Utest
|
||||
{
|
||||
public:
|
||||
int numOfFpSets;
|
||||
MaxFunctionPointerUtest(int num) :
|
||||
numOfFpSets(num)
|
||||
{
|
||||
}
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
for (int i = 0; i < numOfFpSets; ++i)
|
||||
{
|
||||
UT_PTR_SET(fp1, stub_func1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MaxFunctionPointerUtestShell: public UtestShell
|
||||
{
|
||||
public:
|
||||
int numOfFpSets;
|
||||
MaxFunctionPointerUtestShell(int num) :
|
||||
numOfFpSets(num)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Utest* createTest() _override
|
||||
{
|
||||
return new MaxFunctionPointerUtest(numOfFpSets);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(SetPointerPluginTest, installTooMuchFunctionPointer)
|
||||
{
|
||||
MaxFunctionPointerUtestShell *tst = new MaxFunctionPointerUtestShell(SetPointerPlugin::MAX_SET + 1);
|
||||
myRegistry_->addTest(tst);
|
||||
|
||||
myRegistry_->runAllTests(*result_);
|
||||
|
||||
LONGS_EQUAL(1, result_->getFailureCount());
|
||||
delete tst;
|
||||
}
|
||||
|
||||
static double orig_double = 3.0;
|
||||
static double* orig_double_ptr = &orig_double;
|
||||
static double stub_double = 4.0;
|
||||
|
||||
class SetDoublePointerUtest : public Utest
|
||||
{
|
||||
public:
|
||||
void setup() _override
|
||||
{
|
||||
UT_PTR_SET(orig_double_ptr, &stub_double);
|
||||
}
|
||||
void testBody() _override
|
||||
{
|
||||
CHECK(orig_double_ptr == &stub_double);
|
||||
}
|
||||
};
|
||||
|
||||
class SetDoublePointerUtestShell: public UtestShell
|
||||
{
|
||||
public:
|
||||
Utest * createTest() _override
|
||||
{
|
||||
return new SetDoublePointerUtest();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(SetPointerPluginTest, doublePointer)
|
||||
{
|
||||
SetDoublePointerUtestShell *doubletst = new SetDoublePointerUtestShell();
|
||||
myRegistry_->addTest(doubletst);
|
||||
myRegistry_->runAllTests(*result_);
|
||||
|
||||
CHECK(orig_double_ptr == &orig_double);
|
||||
LONGS_EQUAL(1, result_->getCheckCount());
|
||||
delete doubletst;
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Michael Feathers, James Grenning, Bas Vodde and Chen YewMing
|
||||
* 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 <organization> 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 <copyright holder> 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/SimpleMutex.h"
|
||||
#include "CppUTest/PlatformSpecificFunctions.h"
|
||||
|
||||
static int mutexCreateCount = 0;
|
||||
static int mutexLockCount = 0;
|
||||
static int mutexUnlockCount = 0;
|
||||
static int mutexDestroyCount = 0;
|
||||
|
||||
static PlatformSpecificMutex StubMutexCreate(void)
|
||||
{
|
||||
mutexCreateCount++;
|
||||
return NULLPTR;
|
||||
}
|
||||
|
||||
static void StubMutexLock(PlatformSpecificMutex)
|
||||
{
|
||||
mutexLockCount++;
|
||||
}
|
||||
|
||||
static void StubMutexUnlock(PlatformSpecificMutex)
|
||||
{
|
||||
mutexUnlockCount++;
|
||||
}
|
||||
|
||||
static void StubMutexDestroy(PlatformSpecificMutex)
|
||||
{
|
||||
mutexDestroyCount++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_GROUP(SimpleMutexTest)
|
||||
{
|
||||
void setup() _override
|
||||
{
|
||||
UT_PTR_SET(PlatformSpecificMutexCreate, StubMutexCreate);
|
||||
UT_PTR_SET(PlatformSpecificMutexLock, StubMutexLock);
|
||||
UT_PTR_SET(PlatformSpecificMutexUnlock, StubMutexUnlock);
|
||||
UT_PTR_SET(PlatformSpecificMutexDestroy, StubMutexDestroy);
|
||||
|
||||
mutexCreateCount = 0;
|
||||
mutexDestroyCount = 0;
|
||||
mutexLockCount = 0;
|
||||
mutexUnlockCount = 0;
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
TEST(SimpleMutexTest, CreateAndDestroy)
|
||||
{
|
||||
{
|
||||
SimpleMutex mtx;
|
||||
}
|
||||
|
||||
CHECK_EQUAL(1, mutexCreateCount);
|
||||
CHECK_EQUAL(1, mutexDestroyCount);
|
||||
CHECK_EQUAL(0, mutexLockCount);
|
||||
CHECK_EQUAL(0, mutexUnlockCount);
|
||||
}
|
||||
|
||||
TEST(SimpleMutexTest, LockUnlockTest)
|
||||
{
|
||||
{
|
||||
SimpleMutex mtx;
|
||||
mtx.Lock();
|
||||
mtx.Unlock();
|
||||
}
|
||||
|
||||
CHECK_EQUAL(1, mutexCreateCount);
|
||||
CHECK_EQUAL(1, mutexLockCount);
|
||||
CHECK_EQUAL(1, mutexUnlockCount);
|
||||
CHECK_EQUAL(1, mutexDestroyCount);
|
||||
}
|
|
@ -0,0 +1,389 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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"
|
||||
#include "CppUTest/TestTestingFixture.h"
|
||||
|
||||
class TestFunctionWithCache : public ExecFunction
|
||||
{
|
||||
public:
|
||||
void (*testFunction)(SimpleStringInternalCache*, size_t);
|
||||
SimpleStringInternalCache* parameter;
|
||||
size_t allocationSize;
|
||||
|
||||
void exec() _override
|
||||
{
|
||||
testFunction(parameter, allocationSize);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_GROUP(SimpleStringInternalCache)
|
||||
{
|
||||
SimpleStringInternalCache cache;
|
||||
MemoryAccountant accountant;
|
||||
MemoryLeakAllocator* defaultAllocator;
|
||||
AccountingTestMemoryAllocator* allocator;
|
||||
|
||||
TestFunctionWithCache testFunction;
|
||||
TestTestingFixture fixture;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
fixture.setTestFunction(&testFunction);
|
||||
testFunction.parameter = &cache;
|
||||
|
||||
defaultAllocator = new MemoryLeakAllocator(defaultMallocAllocator());
|
||||
allocator = new AccountingTestMemoryAllocator(accountant, defaultAllocator);
|
||||
cache.setAllocator(defaultAllocator);
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
cache.clearAllIncludingCurrentlyUsedMemory();
|
||||
accountant.clear();
|
||||
delete allocator;
|
||||
delete defaultAllocator;
|
||||
}
|
||||
|
||||
void createCacheForSize(size_t size, size_t amount)
|
||||
{
|
||||
for (size_t i = 0; i < amount; i++) {
|
||||
char* memory = cache.alloc(size);
|
||||
cache.dealloc(memory, size);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST(SimpleStringInternalCache, cacheHitWithOneEntry)
|
||||
{
|
||||
createCacheForSize(10, 1);
|
||||
cache.setAllocator(allocator);
|
||||
|
||||
char* mem = cache.alloc(10);
|
||||
mem[0] = 'B';
|
||||
mem[3] = 'A';
|
||||
mem[9] = 'S';
|
||||
|
||||
cache.setAllocator(allocator->originalAllocator());
|
||||
|
||||
LONGS_EQUAL(0, accountant.totalAllocationsOfSize(10));
|
||||
CHECK(!cache.hasFreeBlocksOfSize(10));
|
||||
|
||||
cache.setAllocator(allocator);
|
||||
}
|
||||
|
||||
TEST(SimpleStringInternalCache, cacheHitWithTwoEntries)
|
||||
{
|
||||
createCacheForSize(10, 2);
|
||||
cache.setAllocator(allocator);
|
||||
|
||||
cache.alloc(10);
|
||||
cache.alloc(10);
|
||||
|
||||
cache.setAllocator(allocator->originalAllocator());
|
||||
|
||||
LONGS_EQUAL(0, accountant.totalAllocationsOfSize(10));
|
||||
CHECK(!cache.hasFreeBlocksOfSize(10));
|
||||
|
||||
cache.setAllocator(allocator);
|
||||
}
|
||||
|
||||
TEST(SimpleStringInternalCache, allocatingMoreThanCacheAvailable)
|
||||
{
|
||||
createCacheForSize(10, 1);
|
||||
cache.setAllocator(allocator);
|
||||
|
||||
cache.alloc(10);
|
||||
cache.alloc(10);
|
||||
|
||||
cache.setAllocator(allocator->originalAllocator());
|
||||
|
||||
LONGS_EQUAL(1, accountant.totalAllocationsOfSize(32));
|
||||
CHECK(!cache.hasFreeBlocksOfSize(10));
|
||||
|
||||
cache.setAllocator(allocator);
|
||||
}
|
||||
|
||||
|
||||
TEST(SimpleStringInternalCache, allocationWillReuseTheAllocatedBlocks)
|
||||
{
|
||||
cache.setAllocator(allocator);
|
||||
|
||||
char* mem = cache.alloc(10);
|
||||
cache.dealloc(mem, 10);
|
||||
mem = cache.alloc(10);
|
||||
cache.dealloc(mem, 10);
|
||||
|
||||
LONGS_EQUAL(1, accountant.totalAllocationsOfSize(32));
|
||||
}
|
||||
|
||||
|
||||
TEST(SimpleStringInternalCache, multipleDifferentSizeAllocationsAndDeallocations)
|
||||
{
|
||||
cache.setAllocator(allocator);
|
||||
|
||||
char* mem10 = cache.alloc(10);
|
||||
char* mem11 = cache.alloc(11);
|
||||
|
||||
char* mem100 = cache.alloc(100);
|
||||
cache.dealloc(mem100, 100);
|
||||
|
||||
char* mem101 = cache.alloc(101);
|
||||
char* mem102 = cache.alloc(102);
|
||||
char* mem103 = cache.alloc(103);
|
||||
cache.dealloc(mem101, 102);
|
||||
cache.dealloc(mem102, 103);
|
||||
cache.dealloc(mem103, 104);
|
||||
|
||||
cache.alloc(105);
|
||||
cache.alloc(106);
|
||||
cache.alloc(107);
|
||||
|
||||
cache.dealloc(mem10, 10);
|
||||
cache.dealloc(mem11, 11);
|
||||
|
||||
LONGS_EQUAL(2, accountant.totalAllocationsOfSize(32));
|
||||
LONGS_EQUAL(3, accountant.totalAllocationsOfSize(128));
|
||||
}
|
||||
|
||||
TEST(SimpleStringInternalCache, deallocOfCachedMemoryWillNotDealloc)
|
||||
{
|
||||
cache.setAllocator(allocator);
|
||||
|
||||
char* mem = cache.alloc(10);
|
||||
cache.dealloc(mem, 10);
|
||||
|
||||
LONGS_EQUAL(0, accountant.totalDeallocationsOfSize(32));
|
||||
}
|
||||
|
||||
TEST(SimpleStringInternalCache, clearCacheWillRemoveAllCachedMemoryButNotAllUsedMemory)
|
||||
{
|
||||
cache.setAllocator(allocator);
|
||||
|
||||
char* mem = cache.alloc(10);
|
||||
cache.dealloc(mem, 10);
|
||||
|
||||
mem = cache.alloc(60);
|
||||
|
||||
cache.clearCache();
|
||||
|
||||
LONGS_EQUAL(1, accountant.totalDeallocationsOfSize(32));
|
||||
LONGS_EQUAL(0, accountant.totalDeallocationsOfSize(64));
|
||||
}
|
||||
|
||||
TEST(SimpleStringInternalCache, clearAllIncludingCurrentlyUsedMemory)
|
||||
{
|
||||
cache.setAllocator(allocator);
|
||||
|
||||
cache.alloc(60);
|
||||
|
||||
cache.clearAllIncludingCurrentlyUsedMemory();
|
||||
|
||||
LONGS_EQUAL(1, accountant.totalDeallocationsOfSize(64));
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(SimpleStringInternalCache, allocatingLargerStringThanCached)
|
||||
{
|
||||
cache.setAllocator(allocator);
|
||||
|
||||
char* mem = cache.alloc(1234);
|
||||
cache.dealloc(mem, 1234);
|
||||
|
||||
LONGS_EQUAL(1, accountant.totalAllocationsOfSize(1234));
|
||||
LONGS_EQUAL(1, accountant.totalDeallocationsOfSize(1234));
|
||||
}
|
||||
|
||||
TEST(SimpleStringInternalCache, allocatingMultipleLargerStringThanCached)
|
||||
{
|
||||
cache.setAllocator(allocator);
|
||||
|
||||
char* mem = cache.alloc(1234);
|
||||
char* mem2 = cache.alloc(1234);
|
||||
char* mem3 = cache.alloc(1234);
|
||||
|
||||
cache.dealloc(mem2, 1234);
|
||||
cache.dealloc(mem, 1234);
|
||||
cache.dealloc(mem3, 1234);
|
||||
|
||||
LONGS_EQUAL(3, accountant.totalAllocationsOfSize(1234));
|
||||
LONGS_EQUAL(3, accountant.totalDeallocationsOfSize(1234));
|
||||
}
|
||||
|
||||
|
||||
TEST(SimpleStringInternalCache, clearAllIncludingCurrentlyUsedMemoryAlsoReleasesLargeNonCachesMemory)
|
||||
{
|
||||
cache.setAllocator(allocator);
|
||||
|
||||
cache.alloc(1234);
|
||||
cache.alloc(1234);
|
||||
cache.alloc(1234);
|
||||
|
||||
cache.clearAllIncludingCurrentlyUsedMemory();
|
||||
|
||||
LONGS_EQUAL(3, accountant.totalAllocationsOfSize(1234));
|
||||
LONGS_EQUAL(3, accountant.totalDeallocationsOfSize(1234));
|
||||
}
|
||||
|
||||
static void _deallocatingStringMemoryThatWasntAllocatedWithCache(SimpleStringInternalCache* cache, size_t allocationSize)
|
||||
{
|
||||
char* mem = defaultMallocAllocator()->alloc_memory(allocationSize, __FILE__, __LINE__);
|
||||
mem[0] = 'B';
|
||||
mem[1] = 'a';
|
||||
mem[2] = 's';
|
||||
mem[3] = '\0';
|
||||
cache->dealloc(mem, allocationSize);
|
||||
defaultMallocAllocator()->free_memory(mem, allocationSize, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
TEST(SimpleStringInternalCache, deallocatingMemoryThatWasntAllocatedWhileCacheWasInPlaceProducesWarning)
|
||||
{
|
||||
testFunction.testFunction = _deallocatingStringMemoryThatWasntAllocatedWithCache;
|
||||
testFunction.allocationSize = 123;
|
||||
|
||||
cache.setAllocator(allocator);
|
||||
fixture.runAllTests();
|
||||
|
||||
fixture.assertPrintContains("\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: \"Bas\"\n");
|
||||
|
||||
}
|
||||
|
||||
static void _deallocatingStringMemoryTwiceThatWasntAllocatedWithCache(SimpleStringInternalCache* cache, size_t allocationSize)
|
||||
{
|
||||
char* mem = defaultMallocAllocator()->alloc_memory(allocationSize, __FILE__, __LINE__);
|
||||
mem[0] = '\0';
|
||||
cache->dealloc(mem, allocationSize);
|
||||
cache->dealloc(mem, allocationSize);
|
||||
defaultMallocAllocator()->free_memory(mem, allocationSize, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
TEST(SimpleStringInternalCache, deallocatingMemoryThatWasntAllocatedWhileCacheWasInPlaceProducesWarningButOnlyOnce)
|
||||
{
|
||||
testFunction.testFunction = _deallocatingStringMemoryTwiceThatWasntAllocatedWithCache;
|
||||
testFunction.allocationSize = 123;
|
||||
|
||||
cache.setAllocator(allocator);
|
||||
fixture.runAllTests();
|
||||
|
||||
LONGS_EQUAL(1, fixture.getOutput().count("WARNING"));
|
||||
}
|
||||
|
||||
TEST(SimpleStringInternalCache, deallocatingLargeMemoryThatWasntAllocatedWhileCacheWasInPlaceProducesWarning)
|
||||
{
|
||||
testFunction.testFunction = _deallocatingStringMemoryThatWasntAllocatedWithCache;
|
||||
testFunction.allocationSize = 12345;
|
||||
|
||||
cache.setAllocator(allocator);
|
||||
fixture.runAllTests();
|
||||
|
||||
fixture.assertPrintContains("\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: \"Bas\"\n");
|
||||
|
||||
}
|
||||
|
||||
TEST(SimpleStringInternalCache, deallocatingLargeMemoryThatWasntAllocatedWhileCacheWasInPlaceProducesWarningButOnlyOnce)
|
||||
{
|
||||
testFunction.testFunction = _deallocatingStringMemoryTwiceThatWasntAllocatedWithCache;
|
||||
testFunction.allocationSize = 12345;
|
||||
|
||||
cache.setAllocator(allocator);
|
||||
fixture.runAllTests();
|
||||
|
||||
LONGS_EQUAL(1, fixture.getOutput().count("WARNING"));
|
||||
}
|
||||
|
||||
TEST_GROUP(SimpleStringCacheAllocator)
|
||||
{
|
||||
SimpleStringCacheAllocator* allocator;
|
||||
SimpleStringInternalCache cache;
|
||||
MemoryAccountant accountant;
|
||||
AccountingTestMemoryAllocator* accountingAllocator;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
accountingAllocator = new AccountingTestMemoryAllocator(accountant, defaultMallocAllocator());
|
||||
allocator = new SimpleStringCacheAllocator(cache, accountingAllocator);
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
cache.clearCache();
|
||||
delete allocator;
|
||||
delete accountingAllocator;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(SimpleStringCacheAllocator, allocationIsCached)
|
||||
{
|
||||
char* mem = allocator->alloc_memory(10, __FILE__, __LINE__);
|
||||
allocator->free_memory(mem, 10, __FILE__, __LINE__);
|
||||
|
||||
size_t totalAllocations = accountant.totalAllocations();
|
||||
size_t totalDeallocations = accountant.totalDeallocations();
|
||||
|
||||
mem = allocator->alloc_memory(10, __FILE__, __LINE__);
|
||||
allocator->free_memory(mem, 10, __FILE__, __LINE__);
|
||||
|
||||
LONGS_EQUAL(totalAllocations, accountant.totalAllocations());
|
||||
LONGS_EQUAL(totalDeallocations, accountant.totalDeallocations());
|
||||
}
|
||||
|
||||
TEST(SimpleStringCacheAllocator, originalAllocator)
|
||||
{
|
||||
POINTERS_EQUAL(defaultMallocAllocator(), allocator->actualAllocator());
|
||||
STRCMP_EQUAL(defaultMallocAllocator()->alloc_name(), allocator->alloc_name());
|
||||
STRCMP_EQUAL(defaultMallocAllocator()->free_name(), allocator->free_name());
|
||||
}
|
||||
|
||||
TEST(SimpleStringCacheAllocator, name)
|
||||
{
|
||||
STRCMP_EQUAL("SimpleStringCacheAllocator", allocator->name());
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_GROUP(GlobalSimpleStringCache)
|
||||
{
|
||||
};
|
||||
|
||||
TEST(GlobalSimpleStringCache, installsAndRemovedCache)
|
||||
{
|
||||
TestMemoryAllocator* originalStringAllocator = SimpleString::getStringAllocator();
|
||||
{
|
||||
GlobalSimpleStringCache cache;
|
||||
STRCMP_EQUAL("SimpleStringCacheAllocator", SimpleString::getStringAllocator()->name());
|
||||
POINTERS_EQUAL(cache.getAllocator(), SimpleString::getStringAllocator());
|
||||
}
|
||||
POINTERS_EQUAL(originalStringAllocator, SimpleString::getStringAllocator());
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,226 @@
|
|||
#include "CppUTest/TestHarness.h"
|
||||
#include "CppUTest/TeamCityTestOutput.h"
|
||||
#include "CppUTest/PlatformSpecificFunctions.h"
|
||||
|
||||
class TeamCityOutputToBuffer : public TeamCityTestOutput
|
||||
{
|
||||
public:
|
||||
explicit TeamCityOutputToBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~TeamCityOutputToBuffer() _destructor_override
|
||||
{
|
||||
}
|
||||
|
||||
void printBuffer(const char* s) _override
|
||||
{
|
||||
output += s;
|
||||
}
|
||||
|
||||
void flush() _override
|
||||
{
|
||||
output = "";
|
||||
}
|
||||
|
||||
const SimpleString& getOutput()
|
||||
{
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
SimpleString output;
|
||||
};
|
||||
|
||||
static long millisTime;
|
||||
|
||||
extern "C" {
|
||||
|
||||
static long MockGetPlatformSpecificTimeInMillis()
|
||||
{
|
||||
return millisTime;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_GROUP(TeamCityOutputTest)
|
||||
{
|
||||
TeamCityTestOutput* tcout;
|
||||
TeamCityOutputToBuffer* mock;
|
||||
UtestShell* tst;
|
||||
TestFailure *f, *f2, *f3;
|
||||
TestResult* result;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
mock = new TeamCityOutputToBuffer();
|
||||
tcout = mock;
|
||||
tst = new UtestShell("group", "test", "file", 10);
|
||||
f = new TestFailure(tst, "failfile", 20, "failure message");
|
||||
f2 = new TestFailure(tst, "file", 20, "message");
|
||||
f3 = new TestFailure(tst, "file", 30, "apos' pipe| [brackets]\r\nCRLF");
|
||||
result = new TestResult(*mock);
|
||||
result->setTotalExecutionTime(10);
|
||||
millisTime = 0;
|
||||
UT_PTR_SET(GetPlatformSpecificTimeInMillis, MockGetPlatformSpecificTimeInMillis);
|
||||
}
|
||||
void teardown() _override
|
||||
{
|
||||
delete tcout;
|
||||
delete tst;
|
||||
delete f;
|
||||
delete f2;
|
||||
delete f3;
|
||||
delete result;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TeamCityOutputTest, PrintGroupStarted)
|
||||
{
|
||||
result->currentGroupStarted(tst);
|
||||
STRCMP_EQUAL("##teamcity[testSuiteStarted name='group']\n", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, PrintGroupStartedAndEnded)
|
||||
{
|
||||
const char* expected = "##teamcity[testSuiteStarted name='group']\n"
|
||||
"##teamcity[testSuiteFinished name='group']\n";
|
||||
result->currentGroupStarted(tst);
|
||||
result->currentGroupEnded(tst);
|
||||
STRCMP_EQUAL(expected, mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, PrintGroupEndedButNotStarted)
|
||||
{
|
||||
result->currentGroupEnded(tst);
|
||||
STRCMP_EQUAL("", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, PrintTestStarted)
|
||||
{
|
||||
tcout->printCurrentTestStarted(*tst);
|
||||
STRCMP_EQUAL("##teamcity[testStarted name='test']\n", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, PrintTestStartedAndEnded)
|
||||
{
|
||||
result->currentTestStarted(tst);
|
||||
millisTime = 42;
|
||||
result->currentTestEnded(tst);
|
||||
STRCMP_EQUAL("##teamcity[testStarted name='test']\n##teamcity[testFinished name='test' duration='42']\n",
|
||||
mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, PrintTestEndedButNotStarted)
|
||||
{
|
||||
result->currentTestEnded(tst);
|
||||
STRCMP_EQUAL("", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, PrintTestIgnored)
|
||||
{
|
||||
const char* expected =
|
||||
"##teamcity[testStarted name='test']\n"
|
||||
"##teamcity[testIgnored name='test']\n"
|
||||
"##teamcity[testFinished name='test' duration='41']\n";
|
||||
|
||||
IgnoredUtestShell* itst = new IgnoredUtestShell("group", "test", "file", 10);
|
||||
result->currentTestStarted(itst);
|
||||
millisTime = 41;
|
||||
result->currentTestEnded(itst);
|
||||
STRCMP_EQUAL(expected, mock->getOutput().asCharString());
|
||||
delete itst;
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, PrintWithFailureInSameFile)
|
||||
{
|
||||
tcout->printFailure(*f2);
|
||||
const char* expected =
|
||||
"##teamcity[testFailed name='test' message='file:20' "
|
||||
"details='message']\n";
|
||||
STRCMP_EQUAL(expected, mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, PrintWithEscapedCharacters)
|
||||
{
|
||||
tcout->printFailure(*f3);
|
||||
const char* expected =
|
||||
"##teamcity[testFailed name='test' message='file:30' "
|
||||
"details='apos|' pipe|| |[brackets|]"
|
||||
"|r|nCRLF']\n";
|
||||
STRCMP_EQUAL(expected, mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, PrintFailureWithFailInDifferentFile)
|
||||
{
|
||||
tcout->printFailure(*f);
|
||||
const char* expected =
|
||||
"##teamcity[testFailed name='test' message='TEST failed (file:10): failfile:20' "
|
||||
"details='failure message']\n";
|
||||
STRCMP_EQUAL(expected, mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, TestGroupEscaped_Start)
|
||||
{
|
||||
tst->setGroupName("'[]\n\r");
|
||||
result->currentGroupStarted(tst);
|
||||
const char* expected =
|
||||
"##teamcity[testSuiteStarted name='|'|[|]|n|r']\n";
|
||||
STRCMP_EQUAL(expected, mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, TestGroupEscaped_End)
|
||||
{
|
||||
tst->setGroupName("'[]\n\r");
|
||||
result->currentGroupStarted(tst);
|
||||
result->currentGroupEnded(tst);
|
||||
const char* expected =
|
||||
"##teamcity[testSuiteStarted name='|'|[|]|n|r']\n"
|
||||
"##teamcity[testSuiteFinished name='|'|[|]|n|r']\n";
|
||||
STRCMP_EQUAL(expected, mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, TestNameEscaped_Start)
|
||||
{
|
||||
tst->setTestName("'[]\n\r");
|
||||
result->currentTestStarted(tst);
|
||||
const char* expected =
|
||||
"##teamcity[testStarted name='|'|[|]|n|r']\n";
|
||||
STRCMP_EQUAL(expected, mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, TestNameEscaped_End)
|
||||
{
|
||||
tst->setTestName("'[]\n\r");
|
||||
result->currentTestStarted(tst);
|
||||
result->currentTestEnded(tst);
|
||||
const char* expected =
|
||||
"##teamcity[testStarted name='|'|[|]|n|r']\n"
|
||||
"##teamcity[testFinished name='|'|[|]|n|r' duration='0']\n";
|
||||
STRCMP_EQUAL(expected, mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, TestNameEscaped_Ignore)
|
||||
{
|
||||
IgnoredUtestShell itst("group", "'[]\n\r", "file", 10);
|
||||
result->currentTestStarted(&itst);
|
||||
const char* expected =
|
||||
"##teamcity[testStarted name='|'|[|]|n|r']\n"
|
||||
"##teamcity[testIgnored name='|'|[|]|n|r']\n";
|
||||
STRCMP_EQUAL(expected, mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TeamCityOutputTest, TestNameEscaped_Fail)
|
||||
{
|
||||
tst->setTestName("'[]\n\r");
|
||||
TestFailure fail(tst, "failfile", 20, "failure message");
|
||||
tcout->printFailure(fail);
|
||||
const char* expected =
|
||||
"##teamcity[testFailed name='|'|[|]|n|r' message='TEST failed (file:10): failfile:20' "
|
||||
"details='failure message']\n";
|
||||
STRCMP_EQUAL(expected, mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
/* Todo:
|
||||
* -Detect when running in TeamCity and switch output to -o teamcity automatically
|
||||
*/
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/TestOutput.h"
|
||||
#include "CppUTest/PlatformSpecificFunctions.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
const int failLineNumber = 2;
|
||||
const char* failFileName = "fail.cpp";
|
||||
}
|
||||
|
||||
static double zero = 0.0;
|
||||
static double one = 1.0;
|
||||
static double not_a_number = zero / zero;
|
||||
static double infinity = one / zero;
|
||||
|
||||
extern "C" {
|
||||
static int IsNanForSystemsWithoutNan(double d) { return ((long)not_a_number == (long)d); }
|
||||
static int IsInfForSystemsWithoutInf(double d) { return ((long)infinity == (long)d); }
|
||||
}
|
||||
|
||||
TEST_GROUP(TestFailureNanAndInf)
|
||||
{
|
||||
UtestShell* test;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
test = new UtestShell("groupname", "testname", failFileName, failLineNumber-1);
|
||||
if(PlatformSpecificIsNan(not_a_number) == false)
|
||||
{
|
||||
not_a_number = -1.0;
|
||||
UT_PTR_SET(PlatformSpecificIsNan, IsNanForSystemsWithoutNan);
|
||||
}
|
||||
if(PlatformSpecificIsInf(infinity) == false)
|
||||
{
|
||||
infinity = -2.0;
|
||||
UT_PTR_SET(PlatformSpecificIsInf, IsInfForSystemsWithoutInf);
|
||||
}
|
||||
}
|
||||
void teardown() _override
|
||||
{
|
||||
delete test;
|
||||
}
|
||||
};
|
||||
#define FAILURE_EQUAL(a, b) STRCMP_EQUAL_LOCATION(a, b.getMessage().asCharString(), "", __FILE__, __LINE__)
|
||||
|
||||
TEST(TestFailureNanAndInf, DoublesEqualExpectedIsNaN)
|
||||
{
|
||||
DoublesEqualFailure f(test, failFileName, failLineNumber, not_a_number, 2.0, 3.0, "");
|
||||
FAILURE_EQUAL("expected <Nan - Not a number>\n"
|
||||
"\tbut was <2> threshold used was <3>\n"
|
||||
"\tCannot make comparisons with Nan", f);
|
||||
}
|
||||
|
||||
TEST(TestFailureNanAndInf, DoublesEqualActualIsNaN)
|
||||
{
|
||||
DoublesEqualFailure f(test, failFileName, failLineNumber, 1.0, not_a_number, 3.0, "");
|
||||
FAILURE_EQUAL("expected <1>\n"
|
||||
"\tbut was <Nan - Not a number> threshold used was <3>\n"
|
||||
"\tCannot make comparisons with Nan", f);
|
||||
}
|
||||
|
||||
TEST(TestFailureNanAndInf, DoublesEqualThresholdIsNaN)
|
||||
{
|
||||
DoublesEqualFailure f(test, failFileName, failLineNumber, 1.0, 2.0, not_a_number, "");
|
||||
FAILURE_EQUAL("expected <1>\n"
|
||||
"\tbut was <2> threshold used was <Nan - Not a number>\n"
|
||||
"\tCannot make comparisons with Nan", f);
|
||||
}
|
||||
|
||||
TEST(TestFailureNanAndInf, DoublesEqualExpectedIsInf)
|
||||
{
|
||||
DoublesEqualFailure f(test, failFileName, failLineNumber, infinity, 2.0, 3.0, "");
|
||||
FAILURE_EQUAL("expected <Inf - Infinity>\n"
|
||||
"\tbut was <2> threshold used was <3>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailureNanAndInf, DoublesEqualActualIsInf)
|
||||
{
|
||||
DoublesEqualFailure f(test, failFileName, failLineNumber, 1.0, infinity, 3.0, "");
|
||||
FAILURE_EQUAL("expected <1>\n"
|
||||
"\tbut was <Inf - Infinity> threshold used was <3>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailureNanAndInf, DoublesEqualThresholdIsInf)
|
||||
{
|
||||
DoublesEqualFailure f(test, failFileName, failLineNumber, 1.0, not_a_number, infinity, "");
|
||||
FAILURE_EQUAL("expected <1>\n"
|
||||
"\tbut was <Nan - Not a number> threshold used was <Inf - Infinity>\n"
|
||||
"\tCannot make comparisons with Nan", f);
|
||||
}
|
|
@ -0,0 +1,428 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/TestOutput.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
const int failLineNumber = 2;
|
||||
const char* failFileName = "fail.cpp";
|
||||
}
|
||||
|
||||
TEST_GROUP(TestFailure)
|
||||
{
|
||||
UtestShell* test;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
test = new UtestShell("groupname", "testname", failFileName, failLineNumber-1);
|
||||
}
|
||||
void teardown() _override
|
||||
{
|
||||
delete test;
|
||||
}
|
||||
};
|
||||
#define FAILURE_EQUAL(a, b) STRCMP_EQUAL_LOCATION(a, b.getMessage().asCharString(), "", __FILE__, __LINE__)
|
||||
|
||||
TEST(TestFailure, CreateFailure)
|
||||
{
|
||||
TestFailure f1(test, failFileName, failLineNumber, "the failure message");
|
||||
TestFailure f2(test, "the failure message");
|
||||
TestFailure f3(test, failFileName, failLineNumber);
|
||||
}
|
||||
|
||||
TEST(TestFailure, GetTestFileAndLineFromFailure)
|
||||
{
|
||||
TestFailure f1(test, failFileName, failLineNumber, "the failure message");
|
||||
STRCMP_EQUAL(failFileName, f1.getTestFileName().asCharString());
|
||||
LONGS_EQUAL(1, f1.getTestLineNumber());
|
||||
}
|
||||
|
||||
TEST(TestFailure, EqualsFailureWithText)
|
||||
{
|
||||
EqualsFailure f(test, failFileName, failLineNumber, "expected", "actual", "text");
|
||||
FAILURE_EQUAL("Message: text\n"
|
||||
"\texpected <expected>\n\tbut was <actual>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, EqualsFailure)
|
||||
{
|
||||
EqualsFailure f(test, failFileName, failLineNumber, "expected", "actual", "");
|
||||
FAILURE_EQUAL("expected <expected>\n\tbut was <actual>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, EqualsFailureWithNullAsActual)
|
||||
{
|
||||
EqualsFailure f(test, failFileName, failLineNumber, "expected", NULLPTR, "");
|
||||
FAILURE_EQUAL("expected <expected>\n\tbut was <(null)>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, EqualsFailureWithNullAsExpected)
|
||||
{
|
||||
EqualsFailure f(test, failFileName, failLineNumber, NULLPTR, "actual", "");
|
||||
FAILURE_EQUAL("expected <(null)>\n\tbut was <actual>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, CheckEqualFailureWithText)
|
||||
{
|
||||
CheckEqualFailure f(test, failFileName, failLineNumber, "expected", "actual", "text");
|
||||
FAILURE_EQUAL("Message: text\n"
|
||||
"\texpected <expected>\n"
|
||||
"\tbut was <actual>\n"
|
||||
"\tdifference starts at position 0 at: < actual >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, CheckEqualFailure)
|
||||
{
|
||||
CheckEqualFailure f(test, failFileName, failLineNumber, "expected", "actual", "");
|
||||
FAILURE_EQUAL("expected <expected>\n"
|
||||
"\tbut was <actual>\n"
|
||||
"\tdifference starts at position 0 at: < actual >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, CheckFailure)
|
||||
{
|
||||
CheckFailure f(test, failFileName, failLineNumber, "CHECK", "chk");
|
||||
FAILURE_EQUAL("CHECK(chk) failed", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, CheckFailureWithText)
|
||||
{
|
||||
CheckFailure f(test, failFileName, failLineNumber, "CHECK", "chk", "text");
|
||||
FAILURE_EQUAL("Message: text\n"
|
||||
"\tCHECK(chk) failed", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, FailFailure)
|
||||
{
|
||||
FailFailure f(test, failFileName, failLineNumber, "chk");
|
||||
FAILURE_EQUAL("chk", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, LongsEqualFailureWithText)
|
||||
{
|
||||
LongsEqualFailure f(test, failFileName, failLineNumber, 1, 2, "text");
|
||||
FAILURE_EQUAL("Message: text\n"
|
||||
"\texpected <1 (0x1)>\n\tbut was <2 (0x2)>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, LongsEqualFailure)
|
||||
{
|
||||
LongsEqualFailure f(test, failFileName, failLineNumber, 1, 2, "");
|
||||
FAILURE_EQUAL("expected <1 (0x1)>\n\tbut was <2 (0x2)>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, LongLongsEqualFailure)
|
||||
{
|
||||
#ifdef CPPUTEST_USE_LONG_LONG
|
||||
LongLongsEqualFailure f(test, failFileName, failLineNumber, 1, 2, "");
|
||||
FAILURE_EQUAL("expected <1 (0x1)>\n\tbut was <2 (0x2)>", f);
|
||||
#else
|
||||
cpputest_longlong dummy_longlong;
|
||||
LongLongsEqualFailure f(test, failFileName, failLineNumber, dummy_longlong, dummy_longlong, "");
|
||||
FAILURE_EQUAL("expected <<longlong_unsupported> >\n\tbut was <<longlong_unsupported> >", f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(TestFailure, UnsignedLongLongsEqualFailure)
|
||||
{
|
||||
#ifdef CPPUTEST_USE_LONG_LONG
|
||||
UnsignedLongLongsEqualFailure f(test, failFileName, failLineNumber, 1, 2, "");
|
||||
FAILURE_EQUAL("expected <1 (0x1)>\n\tbut was <2 (0x2)>", f);
|
||||
#else
|
||||
cpputest_ulonglong dummy_ulonglong;
|
||||
UnsignedLongLongsEqualFailure f(test, failFileName, failLineNumber, dummy_ulonglong, dummy_ulonglong, "");
|
||||
FAILURE_EQUAL("expected <<ulonglong_unsupported> >\n\tbut was <<ulonglong_unsupported> >", f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(TestFailure, SignedBytesEqualFailure)
|
||||
{
|
||||
SignedBytesEqualFailure f(test, failFileName, failLineNumber, (signed char)-1, (signed char)2, "");
|
||||
FAILURE_EQUAL("expected <-1 (0xff)>\n\tbut was < 2 (0x2)>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, StringsEqualFailureWithText)
|
||||
{
|
||||
StringEqualFailure f(test, failFileName, failLineNumber, "abc", "abd", "text");
|
||||
FAILURE_EQUAL("Message: text\n"
|
||||
"\texpected <abc>\n"
|
||||
"\tbut was <abd>\n"
|
||||
"\tdifference starts at position 2 at: < abd >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, StringsEqualFailure)
|
||||
{
|
||||
StringEqualFailure f(test, failFileName, failLineNumber, "abc", "abd", "");
|
||||
FAILURE_EQUAL("expected <abc>\n"
|
||||
"\tbut was <abd>\n"
|
||||
"\tdifference starts at position 2 at: < abd >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, StringsEqualFailureAtTheEnd)
|
||||
{
|
||||
StringEqualFailure f(test, failFileName, failLineNumber, "abc", "ab", "");
|
||||
FAILURE_EQUAL("expected <abc>\n"
|
||||
"\tbut was <ab>\n"
|
||||
"\tdifference starts at position 2 at: < ab >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, StringsEqualFailureNewVariantAtTheEnd)
|
||||
{
|
||||
StringEqualFailure f(test, failFileName, failLineNumber, "EndOfALongerString", "EndOfALongerStrinG", "");
|
||||
FAILURE_EQUAL("expected <EndOfALongerString>\n"
|
||||
"\tbut was <EndOfALongerStrinG>\n"
|
||||
"\tdifference starts at position 17 at: <ongerStrinG >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, StringsEqualFailureWithNewLinesAndTabs)
|
||||
{
|
||||
StringEqualFailure f(test, failFileName, failLineNumber,
|
||||
"StringWith\t\nDifferentString",
|
||||
"StringWith\t\ndifferentString", "");
|
||||
|
||||
FAILURE_EQUAL("expected <StringWith\\t\\nDifferentString>\n"
|
||||
"\tbut was <StringWith\\t\\ndifferentString>\n"
|
||||
"\tdifference starts at position 12 at: <ngWith\\t\\ndifferentS>\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, StringsEqualFailureInTheMiddle)
|
||||
{
|
||||
StringEqualFailure f(test, failFileName, failLineNumber, "aa", "ab", "");
|
||||
FAILURE_EQUAL("expected <aa>\n"
|
||||
"\tbut was <ab>\n"
|
||||
"\tdifference starts at position 1 at: < ab >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, StringsEqualFailureAtTheBeginning)
|
||||
{
|
||||
StringEqualFailure f(test, failFileName, failLineNumber, "aaa", "bbb", "");
|
||||
FAILURE_EQUAL("expected <aaa>\n"
|
||||
"\tbut was <bbb>\n"
|
||||
"\tdifference starts at position 0 at: < bbb >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, StringsEqualFailureWithNullAsActual)
|
||||
{
|
||||
StringEqualFailure f(test, failFileName, failLineNumber, "abc", NULLPTR, "");
|
||||
FAILURE_EQUAL("expected <abc>\n"
|
||||
"\tbut was <(null)>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, StringsEqualFailureWithNullAsExpected)
|
||||
{
|
||||
StringEqualFailure f(test, failFileName, failLineNumber, NULLPTR, "abd", "");
|
||||
FAILURE_EQUAL("expected <(null)>\n"
|
||||
"\tbut was <abd>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, StringsEqualNoCaseFailureWithText)
|
||||
{
|
||||
StringEqualNoCaseFailure f(test, failFileName, failLineNumber, "ABC", "abd", "text");
|
||||
FAILURE_EQUAL("Message: text\n"
|
||||
"\texpected <ABC>\n"
|
||||
"\tbut was <abd>\n"
|
||||
"\tdifference starts at position 2 at: < abd >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, StringsEqualNoCaseFailure)
|
||||
{
|
||||
StringEqualNoCaseFailure f(test, failFileName, failLineNumber, "ABC", "abd", "");
|
||||
FAILURE_EQUAL("expected <ABC>\n"
|
||||
"\tbut was <abd>\n"
|
||||
"\tdifference starts at position 2 at: < abd >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, StringsEqualNoCaseFailureWithActualAsNull)
|
||||
{
|
||||
StringEqualNoCaseFailure f(test, failFileName, failLineNumber, "ABC", NULLPTR, "");
|
||||
FAILURE_EQUAL("expected <ABC>\n"
|
||||
"\tbut was <(null)>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, StringsEqualNoCaseFailureWithExpectedAsNull)
|
||||
{
|
||||
StringEqualNoCaseFailure f(test, failFileName, failLineNumber, NULLPTR, "abd", "");
|
||||
FAILURE_EQUAL("expected <(null)>\n"
|
||||
"\tbut was <abd>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, StringsEqualNoCaseFailure2)
|
||||
{
|
||||
StringEqualNoCaseFailure f(test, failFileName, failLineNumber, "ac", "AB", "");
|
||||
FAILURE_EQUAL("expected <ac>\n"
|
||||
"\tbut was <AB>\n"
|
||||
"\tdifference starts at position 1 at: < AB >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, DoublesEqualNormalWithText)
|
||||
{
|
||||
DoublesEqualFailure f(test, failFileName, failLineNumber, 1.0, 2.0, 3.0, "text");
|
||||
FAILURE_EQUAL("Message: text\n"
|
||||
"\texpected <1>\n"
|
||||
"\tbut was <2> threshold used was <3>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, DoublesEqualNormal)
|
||||
{
|
||||
DoublesEqualFailure f(test, failFileName, failLineNumber, 1.0, 2.0, 3.0, "");
|
||||
FAILURE_EQUAL("expected <1>\n"
|
||||
"\tbut was <2> threshold used was <3>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, BinaryEqualWithText)
|
||||
{
|
||||
const unsigned char expectedData[] = { 0x00 };
|
||||
const unsigned char actualData[] = { 0x01 };
|
||||
BinaryEqualFailure f(test, failFileName, failLineNumber, expectedData, actualData, sizeof(expectedData), "text");
|
||||
FAILURE_EQUAL("Message: text\n"
|
||||
"\texpected <00>\n"
|
||||
"\tbut was <01>\n"
|
||||
"\tdifference starts at position 0 at: < 01 >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, BinaryEqualOneByte)
|
||||
{
|
||||
const unsigned char expectedData[] = { 0x00 };
|
||||
const unsigned char actualData[] = { 0x01 };
|
||||
BinaryEqualFailure f(test, failFileName, failLineNumber, expectedData, actualData, sizeof(expectedData), "");
|
||||
FAILURE_EQUAL("expected <00>\n"
|
||||
"\tbut was <01>\n"
|
||||
"\tdifference starts at position 0 at: < 01 >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, BinaryEqualTwoBytes)
|
||||
{
|
||||
const unsigned char expectedData[] = {0x00, 0x01};
|
||||
const unsigned char actualData[] = {0x00, 0x02};
|
||||
BinaryEqualFailure f(test, failFileName, failLineNumber, expectedData, actualData, sizeof(expectedData), "");
|
||||
FAILURE_EQUAL("expected <00 01>\n"
|
||||
"\tbut was <00 02>\n"
|
||||
"\tdifference starts at position 1 at: < 00 02 >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, BinaryEqualThreeBytes)
|
||||
{
|
||||
const unsigned char expectedData[] = {0x00, 0x01, 0x00};
|
||||
const unsigned char actualData[] = {0x00, 0x02, 0x00};
|
||||
BinaryEqualFailure f(test, failFileName, failLineNumber, expectedData, actualData, sizeof(expectedData), "");
|
||||
FAILURE_EQUAL("expected <00 01 00>\n"
|
||||
"\tbut was <00 02 00>\n"
|
||||
"\tdifference starts at position 1 at: < 00 02 00 >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, BinaryEqualFullWidth)
|
||||
{
|
||||
const unsigned char expectedData[] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};
|
||||
const unsigned char actualData[] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00};
|
||||
BinaryEqualFailure f(test, failFileName, failLineNumber, expectedData, actualData, sizeof(expectedData), "");
|
||||
FAILURE_EQUAL("expected <00 00 00 01 00 00 00>\n"
|
||||
"\tbut was <00 00 00 02 00 00 00>\n"
|
||||
"\tdifference starts at position 3 at: <00 00 00 02 00 00 00>\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, BinaryEqualLast)
|
||||
{
|
||||
const unsigned char expectedData[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const unsigned char actualData[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
|
||||
BinaryEqualFailure f(test, failFileName, failLineNumber, expectedData, actualData, sizeof(expectedData), "");
|
||||
FAILURE_EQUAL("expected <00 00 00 00 00 00 00>\n"
|
||||
"\tbut was <00 00 00 00 00 00 01>\n"
|
||||
"\tdifference starts at position 6 at: <00 00 00 01 >\n"
|
||||
"\t ^", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, BinaryEqualActualNull)
|
||||
{
|
||||
const unsigned char expectedData[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
BinaryEqualFailure f(test, failFileName, failLineNumber, expectedData, NULLPTR, sizeof(expectedData), "");
|
||||
FAILURE_EQUAL("expected <00 00 00 00 00 00 00>\n\tbut was <(null)>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, BinaryEqualExpectedNull)
|
||||
{
|
||||
const unsigned char actualData[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
|
||||
BinaryEqualFailure f(test, failFileName, failLineNumber, NULLPTR, actualData, sizeof(actualData), "");
|
||||
FAILURE_EQUAL("expected <(null)>\n\tbut was <00 00 00 00 00 00 01>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, BitsEqualWithText)
|
||||
{
|
||||
BitsEqualFailure f(test, failFileName, failLineNumber, 0x0001, 0x0003, 0x00FF, 2*8/CPPUTEST_CHAR_BIT, "text");
|
||||
FAILURE_EQUAL("Message: text\n"
|
||||
"\texpected <xxxxxxxx 00000001>\n\tbut was <xxxxxxxx 00000011>", f);
|
||||
}
|
||||
|
||||
#if (CPPUTEST_CHAR_BIT == 16)
|
||||
TEST(TestFailure, BitsEqualChar)
|
||||
{
|
||||
BitsEqualFailure f(test, failFileName, failLineNumber, 0x01, 0x03, 0xFF, sizeof(char), "");
|
||||
FAILURE_EQUAL("expected <xxxxxxxx 00000001>\n\tbut was <xxxxxxxx 00000011>", f);
|
||||
}
|
||||
#else
|
||||
TEST(TestFailure, BitsEqualChar)
|
||||
{
|
||||
BitsEqualFailure f(test, failFileName, failLineNumber, 0x01, 0x03, 0xFF, sizeof(char), "");
|
||||
FAILURE_EQUAL("expected <00000001>\n\tbut was <00000011>", f);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(TestFailure, BitsEqual16Bit)
|
||||
{
|
||||
BitsEqualFailure f(test, failFileName, failLineNumber, 0x0001, 0x0003, 0xFFFF, 2*8/CPPUTEST_CHAR_BIT, "");
|
||||
FAILURE_EQUAL("expected <00000000 00000001>\n\tbut was <00000000 00000011>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, BitsEqual32Bit)
|
||||
{
|
||||
BitsEqualFailure f(test, failFileName, failLineNumber, 0x00000001, 0x00000003, 0xFFFFFFFF, 4*8/CPPUTEST_CHAR_BIT, "");
|
||||
FAILURE_EQUAL("expected <00000000 00000000 00000000 00000001>\n\tbut was <00000000 00000000 00000000 00000011>", f);
|
||||
}
|
||||
|
||||
TEST(TestFailure, FeatureUnsupported)
|
||||
{
|
||||
FeatureUnsupportedFailure f(test, failFileName, failLineNumber, "SOME_FEATURE", "");
|
||||
FAILURE_EQUAL("The feature \"SOME_FEATURE\" is not supported in this environment or with the feature set selected when building the library.", f);
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/TestFilter.h"
|
||||
|
||||
TEST_GROUP(TestFilter)
|
||||
{
|
||||
};
|
||||
|
||||
TEST(TestFilter, emptyFilterMatchesEverything)
|
||||
{
|
||||
TestFilter filter;
|
||||
CHECK(filter.match("random_name"));
|
||||
CHECK(filter.match(""));
|
||||
CHECK(filter.match("*&%#^&%$(*&^@#(&*@#^(&*$^@#"));
|
||||
}
|
||||
|
||||
TEST(TestFilter, defaultAbsoluteMismatches)
|
||||
{
|
||||
TestFilter filter("filtername");
|
||||
CHECK(!filter.match("notevenclose"));
|
||||
CHECK(!filter.match("filterrname"));
|
||||
CHECK(!filter.match(""));
|
||||
}
|
||||
|
||||
TEST(TestFilter, strictMatching)
|
||||
{
|
||||
TestFilter filter("filter");
|
||||
filter.strictMatching();
|
||||
CHECK(filter.match("filter"));
|
||||
CHECK(!filter.match("filterr"));
|
||||
CHECK(!filter.match(" filter"));
|
||||
}
|
||||
|
||||
TEST(TestFilter, invertMatching)
|
||||
{
|
||||
TestFilter filter("filter");
|
||||
filter.invertMatching();
|
||||
CHECK(!filter.match("filter"));
|
||||
CHECK(!filter.match("filterr"));
|
||||
CHECK(filter.match("notevenclose"));
|
||||
CHECK(filter.match(""));
|
||||
}
|
||||
|
||||
TEST(TestFilter, invertStrictMatching)
|
||||
{
|
||||
TestFilter filter("filter");
|
||||
filter.invertMatching();
|
||||
filter.strictMatching();
|
||||
CHECK(!filter.match("filter"));
|
||||
CHECK(filter.match("filterr"));
|
||||
CHECK(filter.match(" filter"));
|
||||
}
|
||||
|
||||
TEST(TestFilter, equality)
|
||||
{
|
||||
TestFilter filter1("filter");
|
||||
TestFilter filter2("filter");
|
||||
TestFilter filter3("filter3");
|
||||
CHECK(filter1 == filter2);
|
||||
CHECK(! (filter1 == filter3));
|
||||
}
|
||||
|
||||
TEST(TestFilter, equalityWithStrictness)
|
||||
{
|
||||
TestFilter filter1("filter");
|
||||
TestFilter filter2("filter");
|
||||
filter2.strictMatching();
|
||||
CHECK(! (filter1 == filter2));
|
||||
}
|
||||
|
||||
TEST(TestFilter, equalityWithInvertion)
|
||||
{
|
||||
TestFilter filter1("filter");
|
||||
TestFilter filter2("filter");
|
||||
filter2.invertMatching();
|
||||
CHECK(! (filter1 == filter2));
|
||||
}
|
||||
|
||||
TEST(TestFilter, notEqual)
|
||||
{
|
||||
TestFilter filter1("filter");
|
||||
TestFilter filter2("filter");
|
||||
TestFilter filter3("filter3");
|
||||
CHECK(filter1 != filter3);
|
||||
CHECK(! (filter1 != filter2));
|
||||
}
|
||||
|
||||
TEST(TestFilter, stringFrom)
|
||||
{
|
||||
TestFilter filter("filter");
|
||||
STRCMP_EQUAL("TestFilter: \"filter\"", StringFrom(filter).asCharString());
|
||||
}
|
||||
|
||||
TEST(TestFilter, stringFromWithStrictMatching)
|
||||
{
|
||||
TestFilter filter("filter");
|
||||
filter.strictMatching();
|
||||
STRCMP_EQUAL("TestFilter: \"filter\" with strict matching", StringFrom(filter).asCharString());
|
||||
}
|
||||
|
||||
TEST(TestFilter, stringFromWithInvertMatching)
|
||||
{
|
||||
TestFilter filter("filter");
|
||||
filter.invertMatching();
|
||||
STRCMP_EQUAL("TestFilter: \"filter\" with invert matching", StringFrom(filter).asCharString());
|
||||
}
|
||||
|
||||
TEST(TestFilter, stringFromWithStrictInvertMatching)
|
||||
{
|
||||
TestFilter filter("filter");
|
||||
filter.strictMatching();
|
||||
filter.invertMatching();
|
||||
STRCMP_EQUAL("TestFilter: \"filter\" with strict, invert matching", StringFrom(filter).asCharString());
|
||||
}
|
||||
|
||||
TEST(TestFilter, listOfFilters)
|
||||
{
|
||||
TestFilter *listOfFilters = NULLPTR;
|
||||
TestFilter first("foo");
|
||||
TestFilter secnd("bar");
|
||||
listOfFilters = first.add(listOfFilters);
|
||||
listOfFilters = secnd.add(listOfFilters);
|
||||
TestFilter *current = listOfFilters;
|
||||
STRCMP_EQUAL("TestFilter: \"bar\"", StringFrom(*current).asCharString());
|
||||
current = current->getNext();
|
||||
STRCMP_EQUAL("TestFilter: \"foo\"", StringFrom(*current).asCharString());
|
||||
POINTERS_EQUAL(NULLPTR, current->getNext());
|
||||
}
|
||||
|
||||
TEST(TestFilter, constructors)
|
||||
{
|
||||
TestFilter filter1;
|
||||
TestFilter filter2(SimpleString("a"));
|
||||
TestFilter filter3("a");
|
||||
CHECK(filter1.getNext() == NULLPTR);
|
||||
CHECK(filter2.getNext() == NULLPTR);
|
||||
CHECK(filter3.getNext() == NULLPTR);
|
||||
CHECK(filter2.match("ab"));
|
||||
CHECK(filter3.match("ab"));
|
||||
}
|
|
@ -0,0 +1,807 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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_c.h"
|
||||
|
||||
#include "CppUTest/TestHarness.h"
|
||||
#include "CppUTest/TestRegistry.h"
|
||||
#include "CppUTest/TestOutput.h"
|
||||
#include "CppUTest/TestTestingFixture.h"
|
||||
#include "CppUTest/PlatformSpecificFunctions.h"
|
||||
|
||||
|
||||
extern "C" int setup_teardown_was_called_in_test_group_in_C;
|
||||
extern "C" int test_was_called_in_test_group_in_C;
|
||||
int setup_teardown_was_called_in_test_group_in_C = 0;
|
||||
int test_was_called_in_test_group_in_C = 0;
|
||||
|
||||
TEST_GROUP_C_WRAPPER(TestGroupInC)
|
||||
{
|
||||
TEST_GROUP_C_SETUP_WRAPPER(TestGroupInC)
|
||||
TEST_GROUP_C_TEARDOWN_WRAPPER(TestGroupInC)
|
||||
};
|
||||
|
||||
TEST_C_WRAPPER(TestGroupInC, checkThatTheTestHasRun)
|
||||
IGNORE_TEST_C_WRAPPER(TestGroupInC, ignoreMacroForCFile)
|
||||
|
||||
/*
|
||||
* This test is a bit strange. They use the fact that you can do -r2 for repeating the same run.
|
||||
* When you do so, the same statics will be shared and therefore we can test whether the setup/teardown is run
|
||||
* correctly.
|
||||
*/
|
||||
|
||||
TEST(TestGroupInC, setupHasBeenCalled)
|
||||
{
|
||||
test_was_called_in_test_group_in_C++;
|
||||
/* Increased in setup, decreased in teardown. So at this point it must be 1 also on a multiple run */
|
||||
LONGS_EQUAL(1, setup_teardown_was_called_in_test_group_in_C);
|
||||
}
|
||||
|
||||
static bool hasDestructorOfTheDestructorCheckedBeenCalled;
|
||||
|
||||
class HasTheDestructorBeenCalledChecker
|
||||
{
|
||||
public:
|
||||
HasTheDestructorBeenCalledChecker(){}
|
||||
~HasTheDestructorBeenCalledChecker() { hasDestructorOfTheDestructorCheckedBeenCalled = true; }
|
||||
};
|
||||
|
||||
TEST_GROUP(TestHarness_c)
|
||||
{
|
||||
TestTestingFixture* fixture;
|
||||
TEST_SETUP()
|
||||
{
|
||||
hasDestructorOfTheDestructorCheckedBeenCalled = false;
|
||||
fixture = new TestTestingFixture();
|
||||
}
|
||||
TEST_TEARDOWN()
|
||||
{
|
||||
delete fixture;
|
||||
}
|
||||
};
|
||||
|
||||
static void _failBoolMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_BOOL(1, 0);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkBool)
|
||||
{
|
||||
CHECK_EQUAL_C_BOOL(1, 1);
|
||||
CHECK_EQUAL_C_BOOL(1, 2);
|
||||
fixture->setTestFunction(_failBoolMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <true>\n but was <false>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failBoolTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_BOOL_TEXT(1, 0, "BoolTestText");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkBoolText)
|
||||
{
|
||||
CHECK_EQUAL_C_BOOL_TEXT(1, 1, "Text");
|
||||
CHECK_EQUAL_C_BOOL_TEXT(1, 2, "Text");
|
||||
fixture->setTestFunction(_failBoolTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <true>\n but was <false>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
fixture->assertPrintContains("Message: BoolTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failIntMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_INT(1, 2);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkInt)
|
||||
{
|
||||
CHECK_EQUAL_C_INT(2, 2);
|
||||
fixture->setTestFunction(_failIntMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <1 (0x1)>\n but was <2 (0x2)>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failIntTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_INT_TEXT(1, 2, "IntTestText");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkIntText)
|
||||
{
|
||||
CHECK_EQUAL_C_INT_TEXT(2, 2, "Text");
|
||||
fixture->setTestFunction(_failIntTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <1 (0x1)>\n but was <2 (0x2)>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
fixture->assertPrintContains("Message: IntTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failUnsignedIntMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_UINT(1, 2);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkUnsignedInt)
|
||||
{
|
||||
CHECK_EQUAL_C_UINT(2, 2);
|
||||
fixture->setTestFunction(_failUnsignedIntMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <1 (0x1)>\n but was <2 (0x2)>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failUnsignedIntTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_UINT_TEXT(1, 2, "UnsignedIntTestText");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkUnsignedIntText)
|
||||
{
|
||||
CHECK_EQUAL_C_UINT_TEXT(2, 2, "Text");
|
||||
fixture->setTestFunction(_failUnsignedIntTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <1 (0x1)>\n but was <2 (0x2)>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
fixture->assertPrintContains("Message: UnsignedIntTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failLongIntMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_LONG(1, 2);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkLongInt)
|
||||
{
|
||||
CHECK_EQUAL_C_LONG(2, 2);
|
||||
fixture->setTestFunction(_failLongIntMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <1 (0x1)>\n but was <2 (0x2)>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failLongIntTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_LONG_TEXT(1, 2, "LongIntTestText");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkLongIntText)
|
||||
{
|
||||
CHECK_EQUAL_C_LONG_TEXT(2, 2, "Text");
|
||||
fixture->setTestFunction(_failLongIntTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <1 (0x1)>\n but was <2 (0x2)>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
fixture->assertPrintContains("Message: LongIntTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failUnsignedLongIntMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_ULONG(1, 2);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkUnsignedLongInt)
|
||||
{
|
||||
CHECK_EQUAL_C_ULONG(2, 2);
|
||||
fixture->setTestFunction(_failUnsignedLongIntMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <1 (0x1)>\n but was <2 (0x2)>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failUnsignedLongIntTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_ULONG_TEXT(1, 2, "UnsignedLongIntTestText");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkUnsignedLongIntText)
|
||||
{
|
||||
CHECK_EQUAL_C_ULONG_TEXT(2, 2, "Text");
|
||||
fixture->setTestFunction(_failUnsignedLongIntTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <1 (0x1)>\n but was <2 (0x2)>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
fixture->assertPrintContains("Message: UnsignedLongIntTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
#ifdef CPPUTEST_USE_LONG_LONG
|
||||
|
||||
static void _failLongLongIntMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_LONGLONG(1, 2);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkLongLongInt)
|
||||
{
|
||||
CHECK_EQUAL_C_LONGLONG(2, 2);
|
||||
fixture->setTestFunction(_failLongLongIntMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <1 (0x1)>\n but was <2 (0x2)>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failLongLongIntTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_LONGLONG_TEXT(1, 2, "LongLongTestText");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkLongLongIntText)
|
||||
{
|
||||
CHECK_EQUAL_C_LONGLONG_TEXT(2, 2, "Text");
|
||||
fixture->setTestFunction(_failLongLongIntTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <1 (0x1)>\n but was <2 (0x2)>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
fixture->assertPrintContains("Message: LongLongTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failUnsignedLongLongIntMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_ULONGLONG(1, 2);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkUnsignedLongLongInt)
|
||||
{
|
||||
CHECK_EQUAL_C_ULONGLONG(2, 2);
|
||||
fixture->setTestFunction(_failUnsignedLongLongIntMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <1 (0x1)>\n but was <2 (0x2)>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failUnsignedLongLongIntTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_ULONGLONG_TEXT(1, 2, "UnsignedLongLongTestText");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkUnsignedLongLongIntText)
|
||||
{
|
||||
CHECK_EQUAL_C_ULONGLONG_TEXT(2, 2, "Text");
|
||||
fixture->setTestFunction(_failUnsignedLongLongIntTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <1 (0x1)>\n but was <2 (0x2)>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
fixture->assertPrintContains("Message: UnsignedLongLongTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void _failLongLongIntMethod()
|
||||
{
|
||||
cpputest_longlong dummy_longlong;
|
||||
CHECK_EQUAL_C_LONGLONG(dummy_longlong, dummy_longlong);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkLongLongInt)
|
||||
{
|
||||
fixture->setTestFunction(_failLongLongIntMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("is not supported");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
}
|
||||
|
||||
static void _failLongLongIntTextMethod()
|
||||
{
|
||||
cpputest_longlong dummy_longlong;
|
||||
CHECK_EQUAL_C_LONGLONG_TEXT(dummy_longlong, dummy_longlong, "Text");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkLongLongIntText)
|
||||
{
|
||||
fixture->setTestFunction(_failLongLongIntTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("is not supported");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
}
|
||||
|
||||
static void _failUnsignedLongLongIntMethod()
|
||||
{
|
||||
cpputest_ulonglong dummy_ulonglong;
|
||||
CHECK_EQUAL_C_ULONGLONG(dummy_ulonglong, dummy_ulonglong);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkUnsignedLongLongInt)
|
||||
{
|
||||
fixture->setTestFunction(_failUnsignedLongLongIntMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("is not supported");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
}
|
||||
|
||||
static void _failUnsignedLongLongIntTextMethod()
|
||||
{
|
||||
cpputest_ulonglong dummy_ulonglong;
|
||||
CHECK_EQUAL_C_ULONGLONG_TEXT(dummy_ulonglong, dummy_ulonglong, "Text");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkUnsignedLongLongIntText)
|
||||
{
|
||||
fixture->setTestFunction(_failUnsignedLongLongIntTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("is not supported");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void _failRealMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_REAL(1.0, 2.0, 0.5);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkReal)
|
||||
{
|
||||
CHECK_EQUAL_C_REAL(1.0, 1.1, 0.5);
|
||||
fixture->setTestFunction(_failRealMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <1>\n but was <2>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failRealTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_REAL_TEXT(1.0, 2.0, 0.5, "RealTestText");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkRealText)
|
||||
{
|
||||
CHECK_EQUAL_C_REAL_TEXT(1.0, 1.1, 0.5, "Text");
|
||||
fixture->setTestFunction(_failRealTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <1>\n but was <2>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
fixture->assertPrintContains("Message: RealTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failCharMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_CHAR('a', 'c');
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, checkChar)
|
||||
{
|
||||
CHECK_EQUAL_C_CHAR('a', 'a');
|
||||
fixture->setTestFunction(_failCharMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <a>\n but was <c>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failCharTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_CHAR_TEXT('a', 'c', "CharTestText");
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, checkCharText)
|
||||
{
|
||||
CHECK_EQUAL_C_CHAR_TEXT('a', 'a', "Text");
|
||||
fixture->setTestFunction(_failCharTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <a>\n but was <c>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
fixture->assertPrintContains("Message: CharTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failUnsignedByteMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_UBYTE(254, 253);
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, checkUnsignedByte)
|
||||
{
|
||||
CHECK_EQUAL_C_UBYTE(254, 254);
|
||||
fixture->setTestFunction(_failUnsignedByteMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <254>\n but was <253>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failUnsignedByteTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_UBYTE_TEXT(254, 253, "UnsignedByteTestText");
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, checkUnsignedByteText)
|
||||
{
|
||||
CHECK_EQUAL_C_UBYTE_TEXT(254, 254, "Text");
|
||||
fixture->setTestFunction(_failUnsignedByteTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <254>\n but was <253>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
fixture->assertPrintContains("Message: UnsignedByteTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failSignedByteMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_SBYTE(-3, -5);
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, checkSignedByte)
|
||||
{
|
||||
CHECK_EQUAL_C_SBYTE(-3, -3);
|
||||
fixture->setTestFunction(_failSignedByteMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <-3>\n but was <-5>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failSignedByteTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_SBYTE_TEXT(-3, -5, "SignedByteTestText");
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, checkSignedByteText)
|
||||
{
|
||||
CHECK_EQUAL_C_SBYTE_TEXT(-3, -3, "Text");
|
||||
fixture->setTestFunction(_failSignedByteTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <-3>\n but was <-5>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
fixture->assertPrintContains("Message: SignedByteTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failStringMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_STRING("Hello", "Hello World");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkString)
|
||||
{
|
||||
CHECK_EQUAL_C_STRING("Hello", "Hello");
|
||||
fixture->setTestFunction(_failStringMethod);
|
||||
fixture->runAllTests();
|
||||
|
||||
StringEqualFailure failure(UtestShell::getCurrent(), "file", 1, "Hello", "Hello World", "");
|
||||
fixture->assertPrintContains(failure.getMessage());
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failStringTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_STRING_TEXT("Hello", "Hello World", "StringTestText");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkStringText)
|
||||
{
|
||||
CHECK_EQUAL_C_STRING_TEXT("Hello", "Hello", "Text");
|
||||
fixture->setTestFunction(_failStringTextMethod);
|
||||
fixture->runAllTests();
|
||||
|
||||
StringEqualFailure failure(UtestShell::getCurrent(), "file", 1, "Hello", "Hello World", "");
|
||||
fixture->assertPrintContains(failure.getMessage());
|
||||
fixture->assertPrintContains("arness_c");
|
||||
fixture->assertPrintContains("Message: StringTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failPointerMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_POINTER(NULLPTR, (void *)0x1);
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, checkPointer)
|
||||
{
|
||||
CHECK_EQUAL_C_POINTER(NULLPTR, NULLPTR);
|
||||
fixture->setTestFunction(_failPointerMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <0x0>\n but was <0x1>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failPointerTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_POINTER_TEXT(NULLPTR, (void *)0x1, "PointerTestText");
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, checkPointerText)
|
||||
{
|
||||
CHECK_EQUAL_C_POINTER_TEXT(NULLPTR, NULLPTR, "Text");
|
||||
fixture->setTestFunction(_failPointerTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <0x0>\n but was <0x1>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
fixture->assertPrintContains("Message: PointerTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failBitsMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_BITS(0x0001, (unsigned short)0x0003, 0xFFFF);
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, checkBits)
|
||||
{
|
||||
CHECK_EQUAL_C_BITS(0xABCD, (unsigned short)0xABCD, 0xFFFF);
|
||||
fixture->setTestFunction(_failBitsMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <00000000 00000001>\n\tbut was <00000000 00000011>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failBitsTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_EQUAL_C_BITS_TEXT(0x0001, (unsigned short)0x0003, 0xFFFF, "BitsTestText");
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, checkBitsText)
|
||||
{
|
||||
CHECK_EQUAL_C_BITS_TEXT(0xABCD, (unsigned short)0xABCD, 0xFFFF, "Text");
|
||||
fixture->setTestFunction(_failBitsTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("expected <00000000 00000001>\n\tbut was <00000000 00000011>");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
fixture->assertPrintContains("Message: BitsTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
FAIL_TEXT_C("Booo");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkFailText)
|
||||
{
|
||||
fixture->setTestFunction(_failTextMethod);
|
||||
fixture->runAllTests();
|
||||
fixture->assertPrintContains("Booo");
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _failMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
FAIL_C();
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkFail)
|
||||
{
|
||||
fixture->setTestFunction(_failMethod);
|
||||
fixture->runAllTests();
|
||||
LONGS_EQUAL(1, fixture->getFailureCount());
|
||||
fixture->assertPrintContains("arness_c");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _CheckMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_C(false);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkCheck)
|
||||
{
|
||||
CHECK_C(true);
|
||||
fixture->setTestFunction(_CheckMethod);
|
||||
fixture->runAllTests();
|
||||
LONGS_EQUAL(1, fixture->getFailureCount());
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
static void _CheckTextMethod()
|
||||
{
|
||||
HasTheDestructorBeenCalledChecker checker;
|
||||
CHECK_C_TEXT(false, "CheckTestText");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestHarness_c, checkCheckText)
|
||||
{
|
||||
CHECK_C_TEXT(true, "Text");
|
||||
fixture->setTestFunction(_CheckTextMethod);
|
||||
fixture->runAllTests();
|
||||
LONGS_EQUAL(1, fixture->getFailureCount());
|
||||
fixture->assertPrintContains("Message: CheckTestText");
|
||||
CHECK(!hasDestructorOfTheDestructorCheckedBeenCalled);
|
||||
}
|
||||
|
||||
#if CPPUTEST_USE_MEM_LEAK_DETECTION
|
||||
|
||||
TEST(TestHarness_c, cpputest_malloc_out_of_memory)
|
||||
{
|
||||
cpputest_malloc_set_out_of_memory();
|
||||
CHECK(NULLPTR == cpputest_malloc(100));
|
||||
|
||||
cpputest_malloc_set_not_out_of_memory();
|
||||
void * mem = cpputest_malloc(100);
|
||||
CHECK(NULLPTR != mem);
|
||||
cpputest_free(mem);
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, cpputest_malloc_out_of_memory_after_n_mallocs)
|
||||
{
|
||||
cpputest_malloc_set_out_of_memory_countdown(3);
|
||||
void * m1 = cpputest_malloc(10);
|
||||
void * m2 = cpputest_malloc(11);
|
||||
void * m3 = cpputest_malloc(12);
|
||||
CHECK(m1 != NULLPTR);
|
||||
CHECK(m2 != NULLPTR);
|
||||
CHECK(m3 == NULLPTR);
|
||||
cpputest_malloc_set_not_out_of_memory();
|
||||
cpputest_free(m1);
|
||||
cpputest_free(m2);
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, cpputest_malloc_out_of_memory_after_0_mallocs)
|
||||
{
|
||||
cpputest_malloc_set_out_of_memory_countdown(0);
|
||||
void * m1 = cpputest_malloc(10);
|
||||
CHECK(m1 == NULLPTR);
|
||||
cpputest_malloc_set_not_out_of_memory();
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, count_mallocs)
|
||||
{
|
||||
cpputest_malloc_count_reset();
|
||||
void * m1 = cpputest_malloc(10);
|
||||
void * m2 = cpputest_malloc(11);
|
||||
void * m3 = cpputest_malloc(12);
|
||||
cpputest_free(m1);
|
||||
cpputest_free(m2);
|
||||
cpputest_free(m3);
|
||||
LONGS_EQUAL(3, cpputest_malloc_get_count());
|
||||
}
|
||||
|
||||
#ifdef CPPUTEST_USE_STRDUP_MACROS
|
||||
|
||||
TEST(TestHarness_c, cpputest_strdup)
|
||||
{
|
||||
char * mem = cpputest_strdup("0123456789");
|
||||
CHECK(NULLPTR != mem);
|
||||
STRCMP_EQUAL("0123456789", mem);
|
||||
cpputest_free(mem);
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, cpputest_strndup)
|
||||
{
|
||||
char * mem = cpputest_strndup("0123456789", 3);
|
||||
CHECK(NULLPTR != mem);
|
||||
STRCMP_EQUAL("012", mem);
|
||||
cpputest_free(mem);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST(TestHarness_c, cpputest_calloc)
|
||||
{
|
||||
void * mem = cpputest_calloc(10, 10);
|
||||
CHECK(NULLPTR != mem);
|
||||
cpputest_free(mem);
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, cpputest_realloc_larger)
|
||||
{
|
||||
const char* number_string = "123456789";
|
||||
|
||||
char* mem1 = (char*) cpputest_malloc(10);
|
||||
|
||||
SimpleString::StrNCpy(mem1, number_string, 10);
|
||||
|
||||
CHECK(mem1 != NULLPTR);
|
||||
|
||||
char* mem2 = (char*) cpputest_realloc(mem1, 1000);
|
||||
|
||||
CHECK(mem2 != NULLPTR);
|
||||
STRCMP_EQUAL(number_string, mem2);
|
||||
|
||||
cpputest_free(mem2);
|
||||
}
|
||||
|
||||
#include "CppUTest/MemoryLeakDetector.h"
|
||||
|
||||
TEST(TestHarness_c, macros)
|
||||
{
|
||||
#if CPPUTEST_USE_MALLOC_MACROS
|
||||
MemoryLeakDetector* memLeakDetector = MemoryLeakWarningPlugin::getGlobalDetector();
|
||||
size_t memLeaks = memLeakDetector->totalMemoryLeaks(mem_leak_period_checking);
|
||||
#endif
|
||||
void* mem1 = malloc(10);
|
||||
void* mem2 = calloc(10, 20);
|
||||
void* mem3 = realloc(mem2, 100);
|
||||
#if CPPUTEST_USE_MALLOC_MACROS
|
||||
LONGS_EQUAL(memLeaks + 2, memLeakDetector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
#endif
|
||||
free(mem1);
|
||||
free(mem3);
|
||||
#if CPPUTEST_USE_MALLOC_MACROS
|
||||
LONGS_EQUAL(memLeaks, memLeakDetector->totalMemoryLeaks(mem_leak_period_checking));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, callocInitializedToZero)
|
||||
{
|
||||
char* mem = (char*) calloc(20, sizeof(char));
|
||||
for (int i = 0; i < 20; i++)
|
||||
CHECK(mem[i] == 0);
|
||||
free(mem);
|
||||
}
|
||||
|
||||
TEST(TestHarness_c, callocShouldReturnNULLWhenOutOfMemory)
|
||||
{
|
||||
cpputest_malloc_set_out_of_memory_countdown(0);
|
||||
void * m = cpputest_calloc(1, 1);
|
||||
CHECK(m == NULLPTR);
|
||||
cpputest_malloc_set_not_out_of_memory();
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
#include "CppUTest/TestHarness_c.h"
|
||||
#include "CppUTest/PlatformSpecificFunctions_c.h"
|
||||
|
||||
extern void functionWithUnusedParameter(void* PUNUSED(unlessParamater));
|
||||
|
||||
void functionWithUnusedParameter(void* PUNUSED(unlessParamater))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* Declared in the cpp file */
|
||||
extern int setup_teardown_was_called_in_test_group_in_C;
|
||||
extern int test_was_called_in_test_group_in_C;
|
||||
|
||||
TEST_GROUP_C_SETUP(TestGroupInC)
|
||||
{
|
||||
setup_teardown_was_called_in_test_group_in_C++;
|
||||
}
|
||||
|
||||
TEST_GROUP_C_TEARDOWN(TestGroupInC)
|
||||
{
|
||||
setup_teardown_was_called_in_test_group_in_C--;
|
||||
CHECK_C(test_was_called_in_test_group_in_C == 1);
|
||||
test_was_called_in_test_group_in_C--;
|
||||
}
|
||||
|
||||
TEST_C(TestGroupInC, checkThatTheTestHasRun)
|
||||
{
|
||||
test_was_called_in_test_group_in_C++;
|
||||
}
|
||||
|
||||
IGNORE_TEST_C(TestGroupInC, ignoreMacroForCFile)
|
||||
{
|
||||
test_was_called_in_test_group_in_C++;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/TestRegistry.h"
|
||||
|
||||
class TestInstallerTestUtestShell : public UtestShell
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
// this is file scope because the test is installed
|
||||
// with all other tests, which also happen to be
|
||||
// created as static instances at file scope
|
||||
|
||||
TEST_GROUP(TestInstaller)
|
||||
{
|
||||
TestInstaller* testInstaller;
|
||||
TestRegistry* myRegistry;
|
||||
TestInstallerTestUtestShell shell;
|
||||
void setup() _override
|
||||
{
|
||||
myRegistry = new TestRegistry();
|
||||
myRegistry->setCurrentRegistry(myRegistry);
|
||||
testInstaller = new TestInstaller(shell, "TestInstaller", "test", __FILE__, __LINE__);
|
||||
}
|
||||
void teardown() _override
|
||||
{
|
||||
myRegistry->setCurrentRegistry(NULLPTR);
|
||||
testInstaller->unDo();
|
||||
delete testInstaller;
|
||||
delete myRegistry;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TestInstaller, Create)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,765 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/TestMemoryAllocator.h"
|
||||
#include "CppUTest/PlatformSpecificFunctions.h"
|
||||
#include "CppUTest/TestTestingFixture.h"
|
||||
#include "CppUTest/MemoryLeakDetector.h"
|
||||
|
||||
TEST_GROUP(TestMemoryAllocatorTest)
|
||||
{
|
||||
TestMemoryAllocator* allocator;
|
||||
GlobalMemoryAllocatorStash memoryAllocatorStash;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
allocator = NULLPTR;
|
||||
memoryAllocatorStash.save();
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
memoryAllocatorStash.restore();
|
||||
delete allocator;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TestMemoryAllocatorTest, SetCurrentNewAllocator)
|
||||
{
|
||||
allocator = new TestMemoryAllocator("new allocator for test");
|
||||
setCurrentNewAllocator(allocator);
|
||||
POINTERS_EQUAL(allocator, getCurrentNewAllocator());
|
||||
}
|
||||
|
||||
TEST(TestMemoryAllocatorTest, SetCurrentNewAllocatorToDefault)
|
||||
{
|
||||
TestMemoryAllocator* originalAllocator = getCurrentNewAllocator();
|
||||
|
||||
setCurrentNewAllocatorToDefault();
|
||||
POINTERS_EQUAL(defaultNewAllocator(), getCurrentNewAllocator());
|
||||
|
||||
setCurrentNewAllocator(originalAllocator);
|
||||
}
|
||||
|
||||
TEST(TestMemoryAllocatorTest, SetCurrentNewArrayAllocator)
|
||||
{
|
||||
allocator = new TestMemoryAllocator("new array allocator for test");
|
||||
setCurrentNewArrayAllocator(allocator);
|
||||
POINTERS_EQUAL(allocator, getCurrentNewArrayAllocator());
|
||||
setCurrentNewArrayAllocatorToDefault();
|
||||
POINTERS_EQUAL(defaultNewArrayAllocator(), getCurrentNewArrayAllocator());
|
||||
}
|
||||
|
||||
TEST(TestMemoryAllocatorTest, SetCurrentMallocAllocator)
|
||||
{
|
||||
allocator = new TestMemoryAllocator("malloc_allocator");
|
||||
setCurrentMallocAllocator(allocator);
|
||||
POINTERS_EQUAL(allocator, getCurrentMallocAllocator());
|
||||
setCurrentMallocAllocatorToDefault();
|
||||
POINTERS_EQUAL(defaultMallocAllocator(), getCurrentMallocAllocator());
|
||||
}
|
||||
|
||||
TEST(TestMemoryAllocatorTest, MemoryAllocation)
|
||||
{
|
||||
allocator = new TestMemoryAllocator();
|
||||
allocator->free_memory(allocator->alloc_memory(100, "file", 1), 100, "file", 1);
|
||||
}
|
||||
|
||||
TEST(TestMemoryAllocatorTest, MallocNames)
|
||||
{
|
||||
STRCMP_EQUAL("Standard Malloc Allocator", defaultMallocAllocator()->name());
|
||||
STRCMP_EQUAL("malloc", defaultMallocAllocator()->alloc_name());
|
||||
STRCMP_EQUAL("free", defaultMallocAllocator()->free_name());
|
||||
}
|
||||
|
||||
TEST(TestMemoryAllocatorTest, NewNames)
|
||||
{
|
||||
STRCMP_EQUAL("Standard New Allocator", defaultNewAllocator()->name());
|
||||
STRCMP_EQUAL("new", defaultNewAllocator()->alloc_name());
|
||||
STRCMP_EQUAL("delete", defaultNewAllocator()->free_name());
|
||||
}
|
||||
|
||||
TEST(TestMemoryAllocatorTest, NewArrayNames)
|
||||
{
|
||||
STRCMP_EQUAL("Standard New [] Allocator", defaultNewArrayAllocator()->name());
|
||||
STRCMP_EQUAL("new []", defaultNewArrayAllocator()->alloc_name());
|
||||
STRCMP_EQUAL("delete []", defaultNewArrayAllocator()->free_name());
|
||||
}
|
||||
|
||||
TEST(TestMemoryAllocatorTest, NullUnknownAllocation)
|
||||
{
|
||||
allocator = new NullUnknownAllocator;
|
||||
allocator->free_memory(allocator->alloc_memory(100, "file", 1), 100, "file", 1);
|
||||
}
|
||||
|
||||
TEST(TestMemoryAllocatorTest, NullUnknownNames)
|
||||
{
|
||||
allocator = new NullUnknownAllocator;
|
||||
STRCMP_EQUAL("Null Allocator", allocator->name());
|
||||
STRCMP_EQUAL("unknown", allocator->alloc_name());
|
||||
STRCMP_EQUAL("unknown", allocator->free_name());
|
||||
}
|
||||
|
||||
#if (! CPPUTEST_SANITIZE_ADDRESS)
|
||||
|
||||
#define MAX_SIZE_FOR_ALLOC ((size_t) -1 > (unsigned short)-1) ? (size_t) -97 : (size_t) -1
|
||||
|
||||
static void failTryingToAllocateTooMuchMemory(void)
|
||||
{
|
||||
TestMemoryAllocator allocator;
|
||||
allocator.alloc_memory(MAX_SIZE_FOR_ALLOC, "file", 1);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(TestMemoryAllocatorTest, TryingToAllocateTooMuchFailsTest)
|
||||
{
|
||||
TestTestingFixture fixture;
|
||||
fixture.setTestFunction(&failTryingToAllocateTooMuchMemory);
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("malloc returned null pointer");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST_GROUP(MemoryLeakAllocator)
|
||||
{
|
||||
MemoryLeakAllocator* allocator;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
allocator = new MemoryLeakAllocator(defaultMallocAllocator());
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
delete allocator;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(MemoryLeakAllocator, allocMemory)
|
||||
{
|
||||
char* memory = allocator->alloc_memory(10, __FILE__, __LINE__);
|
||||
memory[0] = 'B';
|
||||
MemoryLeakWarningPlugin::getGlobalDetector()->deallocMemory(allocator->actualAllocator(), memory);
|
||||
|
||||
/* No leaks or crashes */
|
||||
}
|
||||
|
||||
TEST(MemoryLeakAllocator, freeMemory)
|
||||
{
|
||||
char* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(allocator->actualAllocator(), 10);
|
||||
allocator->free_memory(memory, 10, __FILE__, __LINE__);
|
||||
|
||||
/* No leaks or crashes */
|
||||
}
|
||||
|
||||
TEST(MemoryLeakAllocator, originalAllocator)
|
||||
{
|
||||
POINTERS_EQUAL(defaultMallocAllocator(), allocator->actualAllocator());
|
||||
STRCMP_EQUAL(defaultMallocAllocator()->alloc_name(), allocator->alloc_name());
|
||||
STRCMP_EQUAL(defaultMallocAllocator()->free_name(), allocator->free_name());
|
||||
}
|
||||
|
||||
TEST(MemoryLeakAllocator, name)
|
||||
{
|
||||
STRCMP_EQUAL("MemoryLeakAllocator", allocator->name());
|
||||
}
|
||||
|
||||
#if CPPUTEST_USE_MEM_LEAK_DETECTION
|
||||
#if CPPUTEST_USE_MALLOC_MACROS
|
||||
|
||||
class FailableMemoryAllocatorExecFunction : public ExecFunction
|
||||
{
|
||||
public:
|
||||
FailableMemoryAllocator* allocator_;
|
||||
void (*testFunction_)(FailableMemoryAllocator*);
|
||||
|
||||
void exec() _override
|
||||
{
|
||||
testFunction_(allocator_);
|
||||
}
|
||||
|
||||
FailableMemoryAllocatorExecFunction() : allocator_(NULLPTR), testFunction_(NULLPTR) {}
|
||||
virtual ~FailableMemoryAllocatorExecFunction() _destructor_override {}
|
||||
};
|
||||
|
||||
TEST_GROUP(FailableMemoryAllocator)
|
||||
{
|
||||
FailableMemoryAllocator *failableMallocAllocator;
|
||||
FailableMemoryAllocatorExecFunction testFunction;
|
||||
TestTestingFixture fixture;
|
||||
GlobalMemoryAllocatorStash stash;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
stash.save();
|
||||
testFunction.allocator_ = failableMallocAllocator = new FailableMemoryAllocator("Failable Malloc Allocator", "malloc", "free");
|
||||
fixture.setTestFunction(&testFunction);
|
||||
setCurrentMallocAllocator(failableMallocAllocator);
|
||||
}
|
||||
void teardown() _override
|
||||
{
|
||||
failableMallocAllocator->checkAllFailedAllocsWereDone();
|
||||
failableMallocAllocator->clearFailedAllocs();
|
||||
delete failableMallocAllocator;
|
||||
stash.restore();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(FailableMemoryAllocator, MallocWorksNormallyIfNotAskedToFail)
|
||||
{
|
||||
int *memory = (int*)malloc(sizeof(int));
|
||||
CHECK(memory != NULLPTR);
|
||||
free(memory);
|
||||
}
|
||||
|
||||
TEST(FailableMemoryAllocator, FailFirstMalloc)
|
||||
{
|
||||
failableMallocAllocator->failAllocNumber(1);
|
||||
POINTERS_EQUAL(NULLPTR, (int*)malloc(sizeof(int)));
|
||||
}
|
||||
|
||||
TEST(FailableMemoryAllocator, FailSecondAndFourthMalloc)
|
||||
{
|
||||
failableMallocAllocator->failAllocNumber(2);
|
||||
failableMallocAllocator->failAllocNumber(4);
|
||||
int *memory1 = (int*)malloc(sizeof(int));
|
||||
int *memory2 = (int*)malloc(sizeof(int));
|
||||
int *memory3 = (int*)malloc(sizeof(int));
|
||||
int *memory4 = (int*)malloc(sizeof(int));
|
||||
|
||||
CHECK(NULLPTR != memory1);
|
||||
POINTERS_EQUAL(NULLPTR, memory2);
|
||||
CHECK(NULLPTR != memory3);
|
||||
POINTERS_EQUAL(NULLPTR, memory4);
|
||||
|
||||
free(memory1);
|
||||
free(memory3);
|
||||
}
|
||||
|
||||
static void _failingAllocIsNeverDone(FailableMemoryAllocator* failableMallocAllocator)
|
||||
{
|
||||
failableMallocAllocator->failAllocNumber(1);
|
||||
failableMallocAllocator->failAllocNumber(2);
|
||||
failableMallocAllocator->failAllocNumber(3);
|
||||
malloc(sizeof(int));
|
||||
malloc(sizeof(int));
|
||||
failableMallocAllocator->checkAllFailedAllocsWereDone();
|
||||
}
|
||||
|
||||
TEST(FailableMemoryAllocator, CheckAllFailingAllocsWereDone)
|
||||
{
|
||||
testFunction.testFunction_ = _failingAllocIsNeverDone;
|
||||
|
||||
fixture.runAllTests();
|
||||
|
||||
LONGS_EQUAL(1, fixture.getFailureCount());
|
||||
fixture.assertPrintContains("Expected allocation number 3 was never done");
|
||||
failableMallocAllocator->clearFailedAllocs();
|
||||
}
|
||||
|
||||
TEST(FailableMemoryAllocator, FailFirstAllocationAtGivenLine)
|
||||
{
|
||||
failableMallocAllocator->failNthAllocAt(1, __FILE__, __LINE__ + 2);
|
||||
|
||||
POINTERS_EQUAL(NULLPTR, malloc(sizeof(int)));
|
||||
}
|
||||
|
||||
TEST(FailableMemoryAllocator, FailThirdAllocationAtGivenLine)
|
||||
{
|
||||
int *memory[10] = { NULLPTR };
|
||||
int allocation;
|
||||
failableMallocAllocator->failNthAllocAt(3, __FILE__, __LINE__ + 4);
|
||||
|
||||
for (allocation = 1; allocation <= 10; allocation++)
|
||||
{
|
||||
memory[allocation - 1] = (int *)malloc(sizeof(int));
|
||||
if (memory[allocation - 1] == NULLPTR)
|
||||
break;
|
||||
free(memory[allocation -1]);
|
||||
}
|
||||
|
||||
LONGS_EQUAL(3, allocation);
|
||||
}
|
||||
|
||||
static void _failingLocationAllocIsNeverDone(FailableMemoryAllocator* failableMallocAllocator)
|
||||
{
|
||||
failableMallocAllocator->failNthAllocAt(1, "TestMemoryAllocatorTest.cpp", __LINE__);
|
||||
failableMallocAllocator->checkAllFailedAllocsWereDone();
|
||||
}
|
||||
|
||||
TEST(FailableMemoryAllocator, CheckAllFailingLocationAllocsWereDone)
|
||||
{
|
||||
testFunction.testFunction_ = _failingLocationAllocIsNeverDone;
|
||||
|
||||
fixture.runAllTests();
|
||||
|
||||
LONGS_EQUAL(1, fixture.getFailureCount());
|
||||
fixture.assertPrintContains("Expected failing alloc at TestMemoryAllocatorTest.cpp:");
|
||||
fixture.assertPrintContains("was never done");
|
||||
|
||||
failableMallocAllocator->clearFailedAllocs();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class MemoryAccountantExecFunction
|
||||
: public ExecFunction
|
||||
{
|
||||
public:
|
||||
virtual ~MemoryAccountantExecFunction() _destructor_override
|
||||
{
|
||||
}
|
||||
|
||||
void (*testFunction_)(MemoryAccountant*);
|
||||
MemoryAccountant* parameter_;
|
||||
|
||||
virtual void exec() _override
|
||||
{
|
||||
testFunction_(parameter_);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_GROUP(TestMemoryAccountant)
|
||||
{
|
||||
MemoryAccountant accountant;
|
||||
TestTestingFixture fixture;
|
||||
MemoryAccountantExecFunction testFunction;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
testFunction.parameter_ = &accountant;
|
||||
fixture.setTestFunction(&testFunction);
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
accountant.clear();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TestMemoryAccountant, totalAllocsIsZero)
|
||||
{
|
||||
LONGS_EQUAL(0, accountant.totalAllocations());
|
||||
LONGS_EQUAL(0, accountant.totalDeallocations());
|
||||
}
|
||||
|
||||
TEST(TestMemoryAccountant, countAllocationsPerSize)
|
||||
{
|
||||
accountant.alloc(4);
|
||||
LONGS_EQUAL(1, accountant.totalAllocationsOfSize(4));
|
||||
LONGS_EQUAL(0, accountant.totalAllocationsOfSize(10));
|
||||
LONGS_EQUAL(1, accountant.totalAllocations());
|
||||
LONGS_EQUAL(0, accountant.maximumAllocationAtATimeOfSize(10));
|
||||
}
|
||||
|
||||
TEST(TestMemoryAccountant, countAllocationsPerSizeMultipleAllocations)
|
||||
{
|
||||
accountant.alloc(4);
|
||||
accountant.alloc(4);
|
||||
accountant.alloc(8);
|
||||
LONGS_EQUAL(2, accountant.totalAllocationsOfSize(4));
|
||||
LONGS_EQUAL(1, accountant.totalAllocationsOfSize(8));
|
||||
LONGS_EQUAL(0, accountant.totalAllocationsOfSize(10));
|
||||
LONGS_EQUAL(3, accountant.totalAllocations());
|
||||
}
|
||||
|
||||
TEST(TestMemoryAccountant, countAllocationsPerSizeMultipleAllocationsOutOfOrder)
|
||||
{
|
||||
accountant.alloc(4);
|
||||
accountant.alloc(8);
|
||||
accountant.alloc(4);
|
||||
accountant.alloc(5);
|
||||
accountant.alloc(2);
|
||||
accountant.alloc(4);
|
||||
accountant.alloc(10);
|
||||
|
||||
LONGS_EQUAL(3, accountant.totalAllocationsOfSize(4));
|
||||
LONGS_EQUAL(1, accountant.totalAllocationsOfSize(8));
|
||||
LONGS_EQUAL(1, accountant.totalAllocationsOfSize(10));
|
||||
LONGS_EQUAL(7, accountant.totalAllocations());
|
||||
}
|
||||
|
||||
TEST(TestMemoryAccountant, countDeallocationsPerSizeMultipleAllocations)
|
||||
{
|
||||
accountant.dealloc(8);
|
||||
accountant.dealloc(4);
|
||||
accountant.dealloc(8);
|
||||
LONGS_EQUAL(1, accountant.totalDeallocationsOfSize(4));
|
||||
LONGS_EQUAL(2, accountant.totalDeallocationsOfSize(8));
|
||||
LONGS_EQUAL(0, accountant.totalDeallocationsOfSize(20));
|
||||
LONGS_EQUAL(3, accountant.totalDeallocations());
|
||||
}
|
||||
|
||||
TEST(TestMemoryAccountant, countMaximumAllocationsAtATime)
|
||||
{
|
||||
accountant.alloc(4);
|
||||
accountant.alloc(4);
|
||||
accountant.dealloc(4);
|
||||
accountant.dealloc(4);
|
||||
accountant.alloc(4);
|
||||
LONGS_EQUAL(2, accountant.maximumAllocationAtATimeOfSize(4));
|
||||
}
|
||||
|
||||
TEST(TestMemoryAccountant, reportNoAllocations)
|
||||
{
|
||||
STRCMP_EQUAL("CppUTest Memory Accountant has not noticed any allocations or deallocations. Sorry\n", accountant.report().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestMemoryAccountant, reportAllocations)
|
||||
{
|
||||
accountant.dealloc(8);
|
||||
accountant.dealloc(8);
|
||||
accountant.dealloc(8);
|
||||
|
||||
accountant.alloc(4);
|
||||
accountant.dealloc(4);
|
||||
accountant.alloc(4);
|
||||
STRCMP_EQUAL("CppUTest Memory Accountant report:\n"
|
||||
"Allocation size # allocations # deallocations max # allocations at one time\n"
|
||||
" 4 2 1 1\n"
|
||||
" 8 0 3 0\n"
|
||||
" Thank you for your business\n"
|
||||
, accountant.report().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestMemoryAccountant, reportAllocationsWithSizeZero)
|
||||
{
|
||||
accountant.dealloc(0);
|
||||
|
||||
accountant.dealloc(4);
|
||||
accountant.dealloc(4);
|
||||
accountant.alloc(4);
|
||||
|
||||
STRCMP_EQUAL("CppUTest Memory Accountant report:\n"
|
||||
"Allocation size # allocations # deallocations max # allocations at one time\n"
|
||||
"other 0 1 0\n"
|
||||
" 4 1 2 1\n"
|
||||
" Thank you for your business\n"
|
||||
, accountant.report().asCharString());
|
||||
}
|
||||
|
||||
|
||||
static void _failUseCacheSizesAfterAllocation(MemoryAccountant* accountant)
|
||||
{
|
||||
size_t cacheSizes[] = {0};
|
||||
|
||||
accountant->alloc(4);
|
||||
accountant->useCacheSizes(cacheSizes, 1);
|
||||
}
|
||||
|
||||
TEST(TestMemoryAccountant, withCacheSizesFailsWhenAlreadyAllocatedMemory)
|
||||
{
|
||||
testFunction.testFunction_ = _failUseCacheSizesAfterAllocation;
|
||||
|
||||
fixture.runAllTests();
|
||||
|
||||
fixture.assertPrintContains("MemoryAccountant: Cannot set cache sizes as allocations already occured!");
|
||||
}
|
||||
|
||||
TEST(TestMemoryAccountant, reportWithCacheSizesEmpty)
|
||||
{
|
||||
size_t cacheSizes[] = {0};
|
||||
|
||||
accountant.useCacheSizes(cacheSizes, 0);
|
||||
accountant.alloc(4);
|
||||
|
||||
STRCMP_EQUAL("CppUTest Memory Accountant report (with cache sizes):\n"
|
||||
"Cache size # allocations # deallocations max # allocations at one time\n"
|
||||
"other 1 0 1\n"
|
||||
" Thank you for your business\n"
|
||||
, accountant.report().asCharString());
|
||||
}
|
||||
|
||||
|
||||
TEST(TestMemoryAccountant, reportWithCacheSizes)
|
||||
{
|
||||
size_t cacheSizes[] = {4};
|
||||
|
||||
accountant.useCacheSizes(cacheSizes, 1);
|
||||
accountant.dealloc(8);
|
||||
accountant.dealloc(12);
|
||||
accountant.dealloc(20);
|
||||
|
||||
accountant.alloc(4);
|
||||
accountant.dealloc(4);
|
||||
accountant.alloc(4);
|
||||
STRCMP_EQUAL("CppUTest Memory Accountant report (with cache sizes):\n"
|
||||
"Cache size # allocations # deallocations max # allocations at one time\n"
|
||||
" 4 2 1 1\n"
|
||||
"other 0 3 0\n"
|
||||
" Thank you for your business\n"
|
||||
, accountant.report().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestMemoryAccountant, reportWithCacheSizesMultipleCaches)
|
||||
{
|
||||
size_t cacheSizes[] = {4, 10, 20};
|
||||
|
||||
accountant.useCacheSizes(cacheSizes, 3);
|
||||
accountant.alloc(8);
|
||||
accountant.alloc(12);
|
||||
accountant.alloc(20);
|
||||
|
||||
accountant.alloc(4);
|
||||
accountant.dealloc(4);
|
||||
accountant.alloc(4);
|
||||
STRCMP_EQUAL("CppUTest Memory Accountant report (with cache sizes):\n"
|
||||
"Cache size # allocations # deallocations max # allocations at one time\n"
|
||||
" 4 2 1 1\n"
|
||||
" 10 1 0 1\n"
|
||||
" 20 2 0 2\n"
|
||||
"other 0 0 0\n"
|
||||
" Thank you for your business\n"
|
||||
, accountant.report().asCharString());
|
||||
}
|
||||
|
||||
|
||||
TEST_GROUP(AccountingTestMemoryAllocator)
|
||||
{
|
||||
MemoryAccountant accountant;
|
||||
AccountingTestMemoryAllocator *allocator;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
allocator = new AccountingTestMemoryAllocator(accountant, getCurrentMallocAllocator());
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
accountant.clear();
|
||||
delete allocator;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(AccountingTestMemoryAllocator, canAllocateAndAccountMemory)
|
||||
{
|
||||
char* memory = allocator->alloc_memory(10, __FILE__, __LINE__);
|
||||
allocator->free_memory(memory, 10, __FILE__, __LINE__);
|
||||
|
||||
LONGS_EQUAL(1, accountant.totalAllocationsOfSize(10));
|
||||
LONGS_EQUAL(1, accountant.totalDeallocationsOfSize(10));
|
||||
}
|
||||
|
||||
TEST(AccountingTestMemoryAllocator, canAllocateAndAccountMemoryMultipleAllocations)
|
||||
{
|
||||
char* memory1 = allocator->alloc_memory(10, __FILE__, __LINE__);
|
||||
char* memory2 = allocator->alloc_memory(8, __FILE__, __LINE__);
|
||||
char* memory3 = allocator->alloc_memory(12, __FILE__, __LINE__);
|
||||
|
||||
allocator->free_memory(memory1, 10, __FILE__, __LINE__);
|
||||
allocator->free_memory(memory3, 12, __FILE__, __LINE__);
|
||||
|
||||
char* memory4 = allocator->alloc_memory(15, __FILE__, __LINE__);
|
||||
char* memory5 = allocator->alloc_memory(20, __FILE__, __LINE__);
|
||||
|
||||
allocator->free_memory(memory2, 8, __FILE__, __LINE__);
|
||||
allocator->free_memory(memory4, 15, __FILE__, __LINE__);
|
||||
allocator->free_memory(memory5, 20, __FILE__, __LINE__);
|
||||
|
||||
char* memory6 = allocator->alloc_memory(1, __FILE__, __LINE__);
|
||||
char* memory7 = allocator->alloc_memory(100, __FILE__, __LINE__);
|
||||
|
||||
allocator->free_memory(memory6, 1, __FILE__, __LINE__);
|
||||
allocator->free_memory(memory7, 100, __FILE__, __LINE__);
|
||||
|
||||
LONGS_EQUAL(7, accountant.totalAllocations());
|
||||
LONGS_EQUAL(7, accountant.totalDeallocations());
|
||||
}
|
||||
|
||||
TEST(AccountingTestMemoryAllocator, useOriginalAllocatorWhenDeallocatingMemoryNotAllocatedByAllocator)
|
||||
{
|
||||
char* memory = getCurrentMallocAllocator()->alloc_memory(10, __FILE__, __LINE__);
|
||||
allocator->free_memory(memory, 10, __FILE__, __LINE__);
|
||||
|
||||
LONGS_EQUAL(0, accountant.totalAllocations());
|
||||
LONGS_EQUAL(1, accountant.totalDeallocations());
|
||||
}
|
||||
|
||||
TEST(AccountingTestMemoryAllocator, allocatorForwardsAllocAndFreeName)
|
||||
{
|
||||
STRCMP_EQUAL("malloc", allocator->alloc_name());
|
||||
STRCMP_EQUAL("free", allocator->free_name());
|
||||
}
|
||||
|
||||
|
||||
class GlobalMemoryAccountantExecFunction
|
||||
: public ExecFunction
|
||||
{
|
||||
public:
|
||||
void (*testFunction_)(GlobalMemoryAccountant*);
|
||||
GlobalMemoryAccountant* parameter_;
|
||||
|
||||
virtual void exec() _override
|
||||
{
|
||||
testFunction_(parameter_);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_GROUP(GlobalMemoryAccountant)
|
||||
{
|
||||
GlobalMemoryAccountant accountant;
|
||||
TestTestingFixture fixture;
|
||||
GlobalMemoryAccountantExecFunction testFunction;
|
||||
GlobalMemoryAllocatorStash stash;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
testFunction.parameter_ = &accountant;
|
||||
fixture.setTestFunction(&testFunction);
|
||||
stash.save();
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
stash.restore();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(GlobalMemoryAccountant, start)
|
||||
{
|
||||
accountant.start();
|
||||
|
||||
POINTERS_EQUAL(accountant.getMallocAllocator(), getCurrentMallocAllocator());
|
||||
POINTERS_EQUAL(accountant.getNewAllocator(), getCurrentNewAllocator());
|
||||
POINTERS_EQUAL(accountant.getNewArrayAllocator(), getCurrentNewArrayAllocator());
|
||||
|
||||
accountant.stop();
|
||||
}
|
||||
|
||||
TEST(GlobalMemoryAccountant, stop)
|
||||
{
|
||||
TestMemoryAllocator* originalMallocAllocator = getCurrentMallocAllocator();
|
||||
TestMemoryAllocator* originalNewAllocator = getCurrentNewAllocator();
|
||||
TestMemoryAllocator* originalNewArrayAllocator = getCurrentNewArrayAllocator();
|
||||
|
||||
accountant.start();
|
||||
accountant.stop();
|
||||
|
||||
POINTERS_EQUAL(originalMallocAllocator, getCurrentMallocAllocator());
|
||||
POINTERS_EQUAL(originalNewAllocator, getCurrentNewAllocator());
|
||||
POINTERS_EQUAL(originalNewArrayAllocator, getCurrentNewArrayAllocator());
|
||||
}
|
||||
|
||||
#if CPPUTEST_USE_MEM_LEAK_DETECTION
|
||||
|
||||
TEST(GlobalMemoryAccountant, report)
|
||||
{
|
||||
accountant.start();
|
||||
char* memory = new char[185];
|
||||
delete [] memory;
|
||||
accountant.stop();
|
||||
|
||||
/* Allocation includes memory leak info */
|
||||
STRCMP_CONTAINS("1 1 1", accountant.report().asCharString());
|
||||
}
|
||||
|
||||
TEST(GlobalMemoryAccountant, reportWithCacheSizes)
|
||||
{
|
||||
size_t cacheSizes[] = {512};
|
||||
accountant.useCacheSizes(cacheSizes, 1);
|
||||
accountant.start();
|
||||
char* memory = new char[185];
|
||||
delete [] memory;
|
||||
accountant.stop();
|
||||
|
||||
/* Allocation includes memory leak info */
|
||||
STRCMP_CONTAINS("512 1 1 1", accountant.report().asCharString());
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
static void _failStopWithoutStartingWillFail(GlobalMemoryAccountant* accountant)
|
||||
{
|
||||
accountant->stop();
|
||||
}
|
||||
|
||||
TEST(GlobalMemoryAccountant, StopCantBeCalledWithoutStarting)
|
||||
{
|
||||
testFunction.testFunction_ = _failStopWithoutStartingWillFail;
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("GlobalMemoryAccount: Stop called without starting");
|
||||
}
|
||||
|
||||
static void _failStartingTwiceWillFail(GlobalMemoryAccountant* accountant)
|
||||
{
|
||||
accountant->start();
|
||||
accountant->start();
|
||||
}
|
||||
|
||||
TEST(GlobalMemoryAccountant, startTwiceWillFail)
|
||||
{
|
||||
testFunction.testFunction_ = _failStartingTwiceWillFail;
|
||||
fixture.runAllTests();
|
||||
accountant.stop();
|
||||
|
||||
fixture.assertPrintContains("Global allocator start called twice!");
|
||||
}
|
||||
|
||||
static void _failChangeMallocMemoryAllocator(GlobalMemoryAccountant* accountant)
|
||||
{
|
||||
accountant->start();
|
||||
setCurrentMallocAllocator(defaultMallocAllocator());
|
||||
accountant->stop();
|
||||
}
|
||||
|
||||
TEST(GlobalMemoryAccountant, checkWhetherMallocAllocatorIsNotChanged)
|
||||
{
|
||||
testFunction.testFunction_ = _failChangeMallocMemoryAllocator;
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("GlobalMemoryAccountant: Malloc memory allocator has been changed while accounting for memory");
|
||||
}
|
||||
|
||||
static void _failChangeNewMemoryAllocator(GlobalMemoryAccountant* accountant)
|
||||
{
|
||||
accountant->start();
|
||||
setCurrentNewAllocator(defaultNewAllocator());
|
||||
accountant->stop();
|
||||
}
|
||||
|
||||
TEST(GlobalMemoryAccountant, checkWhetherNewAllocatorIsNotChanged)
|
||||
{
|
||||
testFunction.testFunction_ = _failChangeNewMemoryAllocator;
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("GlobalMemoryAccountant: New memory allocator has been changed while accounting for memory");
|
||||
}
|
||||
|
||||
static void _failChangeNewArrayMemoryAllocator(GlobalMemoryAccountant* accountant)
|
||||
{
|
||||
accountant->start();
|
||||
setCurrentNewArrayAllocator(defaultNewArrayAllocator());
|
||||
accountant->stop();
|
||||
}
|
||||
|
||||
TEST(GlobalMemoryAccountant, checkWhetherNewArrayAllocatorIsNotChanged)
|
||||
{
|
||||
testFunction.testFunction_ = _failChangeNewArrayMemoryAllocator;
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("GlobalMemoryAccountant: New Array memory allocator has been changed while accounting for memory");
|
||||
}
|
|
@ -0,0 +1,472 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/TestOutput.h"
|
||||
#include "CppUTest/TestResult.h"
|
||||
#include "CppUTest/PlatformSpecificFunctions.h"
|
||||
|
||||
static long millisTime;
|
||||
|
||||
extern "C" {
|
||||
|
||||
static long MockGetPlatformSpecificTimeInMillis()
|
||||
{
|
||||
return millisTime;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_GROUP(TestOutput)
|
||||
{
|
||||
TestOutput* printer;
|
||||
StringBufferTestOutput* mock;
|
||||
UtestShell* tst;
|
||||
TestFailure *f;
|
||||
TestFailure *f2;
|
||||
TestFailure *f3;
|
||||
TestResult* result;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
mock = new StringBufferTestOutput();
|
||||
printer = mock;
|
||||
tst = new UtestShell("group", "test", "file", 10);
|
||||
f = new TestFailure(tst, "failfile", 20, "message");
|
||||
f2 = new TestFailure(tst, "file", 20, "message");
|
||||
f3 = new TestFailure(tst, "file", 2, "message");
|
||||
result = new TestResult(*mock);
|
||||
result->setTotalExecutionTime(10);
|
||||
millisTime = 0;
|
||||
UT_PTR_SET(GetPlatformSpecificTimeInMillis, MockGetPlatformSpecificTimeInMillis);
|
||||
TestOutput::setWorkingEnvironment(TestOutput::eclipse);
|
||||
|
||||
}
|
||||
void teardown() _override
|
||||
{
|
||||
TestOutput::setWorkingEnvironment(TestOutput::detectEnvironment);
|
||||
delete printer;
|
||||
delete tst;
|
||||
delete f;
|
||||
delete f2;
|
||||
delete f3;
|
||||
delete result;
|
||||
}
|
||||
|
||||
void runOneTest()
|
||||
{
|
||||
result->countTest();
|
||||
result->countRun();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TestOutput, PrintConstCharStar)
|
||||
{
|
||||
printer->print("hello");
|
||||
printer->print("hello\n");
|
||||
STRCMP_EQUAL("hellohello\n", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, PrintLong)
|
||||
{
|
||||
long number = 1234;
|
||||
printer->print(number);
|
||||
STRCMP_EQUAL("1234", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, PrintSize)
|
||||
{
|
||||
size_t ten = 10;
|
||||
printer->print(ten);
|
||||
STRCMP_EQUAL("10", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
|
||||
TEST(TestOutput, PrintDouble)
|
||||
{
|
||||
printer->printDouble(12.34);
|
||||
STRCMP_EQUAL("12.34", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, StreamOperators)
|
||||
{
|
||||
*printer << "n=" << 1234;
|
||||
STRCMP_EQUAL("n=1234", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, PrintTestEnded)
|
||||
{
|
||||
printer->printCurrentTestEnded(*result);
|
||||
STRCMP_EQUAL(".", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, PrintTestALot)
|
||||
{
|
||||
for (int i = 0; i < 60; ++i) {
|
||||
printer->printCurrentTestEnded(*result);
|
||||
}
|
||||
STRCMP_EQUAL("..................................................\n..........", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, PrintTestALotAndSimulateRepeatRun)
|
||||
{
|
||||
for (int i = 0; i < 60; ++i) {
|
||||
runOneTest();
|
||||
printer->printCurrentTestEnded(*result);
|
||||
}
|
||||
|
||||
printer->printTestsEnded(*result);
|
||||
|
||||
for (int i = 0; i < 60; ++i) {
|
||||
runOneTest();
|
||||
printer->printCurrentTestEnded(*result);
|
||||
}
|
||||
STRCMP_EQUAL("..................................................\n.........." \
|
||||
"\nOK (60 tests, 60 ran, 0 checks, 0 ignored, 0 filtered out, 10 ms)\n\n" \
|
||||
"..................................................\n..........", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, SetProgressIndicator)
|
||||
{
|
||||
printer->setProgressIndicator(".");
|
||||
printer->printCurrentTestEnded(*result);
|
||||
printer->setProgressIndicator("!");
|
||||
printer->printCurrentTestEnded(*result);
|
||||
printer->setProgressIndicator(".");
|
||||
printer->printCurrentTestEnded(*result);
|
||||
|
||||
STRCMP_EQUAL(".!.", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, PrintTestVerboseStarted)
|
||||
{
|
||||
mock->verbose(TestOutput::level_verbose);
|
||||
printer->printCurrentTestStarted(*tst);
|
||||
STRCMP_EQUAL("TEST(group, test)", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, PrintTestVerboseEnded)
|
||||
{
|
||||
mock->verbose(TestOutput::level_verbose);
|
||||
result->currentTestStarted(tst);
|
||||
millisTime = 5;
|
||||
result->currentTestEnded(tst);
|
||||
STRCMP_EQUAL("TEST(group, test) - 5 ms\n", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, printColorWithSuccess)
|
||||
{
|
||||
mock->color();
|
||||
runOneTest();
|
||||
printer->printTestsEnded(*result);
|
||||
STRCMP_EQUAL("\n\033[32;1mOK (1 tests, 1 ran, 0 checks, 0 ignored, 0 filtered out, 10 ms)\033[m\n\n",
|
||||
mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, printColorWithFailures)
|
||||
{
|
||||
mock->color();
|
||||
runOneTest();
|
||||
result->addFailure(*f);
|
||||
printer->flush();
|
||||
printer->printTestsEnded(*result);
|
||||
STRCMP_EQUAL("\n\033[31;1mErrors (1 failures, 1 tests, 1 ran, 0 checks, 0 ignored, 0 filtered out, 10 ms)"
|
||||
"\033[m\n\n", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, PrintTestRun)
|
||||
{
|
||||
printer->printTestRun(2, 3);
|
||||
STRCMP_EQUAL("Test run 2 of 3\n", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, PrintTestRunOnlyOne)
|
||||
{
|
||||
printer->printTestRun(1, 1);
|
||||
STRCMP_EQUAL("", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, PrintWithFailureInSameFile)
|
||||
{
|
||||
printer->printFailure(*f2);
|
||||
STRCMP_EQUAL("\nfile:20: error: Failure in TEST(group, test)\n\tmessage\n\n", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, PrintFailureWithFailInDifferentFile)
|
||||
{
|
||||
printer->printFailure(*f);
|
||||
const char* expected =
|
||||
"\nfile:10: error: Failure in TEST(group, test)"
|
||||
"\nfailfile:20: error:\n\tmessage\n\n";
|
||||
STRCMP_EQUAL(expected, mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, PrintFailureWithFailInHelper)
|
||||
{
|
||||
printer->printFailure(*f3);
|
||||
const char* expected =
|
||||
"\nfile:10: error: Failure in TEST(group, test)"
|
||||
"\nfile:2: error:\n\tmessage\n\n";
|
||||
STRCMP_EQUAL(expected, mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, PrintInVisualStudioFormat)
|
||||
{
|
||||
TestOutput::setWorkingEnvironment(TestOutput::visualStudio);
|
||||
printer->printFailure(*f3);
|
||||
const char* expected =
|
||||
"\nfile(10): error: Failure in TEST(group, test)"
|
||||
"\nfile(2): error:\n\tmessage\n\n";
|
||||
STRCMP_EQUAL(expected, mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, PrintTestStarts)
|
||||
{
|
||||
printer->printTestsStarted();
|
||||
STRCMP_EQUAL("", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, printTestsEnded)
|
||||
{
|
||||
result->countTest();
|
||||
result->countCheck();
|
||||
result->countIgnored();
|
||||
result->countIgnored();
|
||||
result->countRun();
|
||||
result->countRun();
|
||||
result->countRun();
|
||||
printer->printTestsEnded(*result);
|
||||
STRCMP_EQUAL("\nOK (1 tests, 3 ran, 1 checks, 2 ignored, 0 filtered out, 10 ms)\n\n", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, printTestsEndedWithFailures)
|
||||
{
|
||||
result->addFailure(*f);
|
||||
printer->flush();
|
||||
printer->printTestsEnded(*result);
|
||||
STRCMP_EQUAL("\nErrors (1 failures, 0 tests, 0 ran, 0 checks, 0 ignored, 0 filtered out, 10 ms)\n\n", mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(TestOutput, printTestsEndedWithNoTestsRunOrIgnored)
|
||||
{
|
||||
result->countTest();
|
||||
printer->flush();
|
||||
printer->printTestsEnded(*result);
|
||||
STRCMP_EQUAL("\nErrors (ran nothing, 1 tests, 0 ran, 0 checks, 0 ignored, 0 filtered out, 10 ms)\n"
|
||||
"Note: 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.\n\n",
|
||||
mock->getOutput().asCharString());
|
||||
}
|
||||
|
||||
class CompositeTestOutputTestStringBufferTestOutput : public StringBufferTestOutput
|
||||
{
|
||||
public:
|
||||
virtual void printTestsStarted() _override
|
||||
{
|
||||
output += "Test Start\n";
|
||||
}
|
||||
|
||||
virtual void printTestsEnded(const TestResult& result) _override
|
||||
{
|
||||
output += StringFromFormat("Test End %d\n", (int) result.getTestCount());
|
||||
}
|
||||
|
||||
void printCurrentGroupStarted(const UtestShell& test) _override
|
||||
{
|
||||
output += StringFromFormat("Group %s Start\n", test.getGroup().asCharString());
|
||||
}
|
||||
|
||||
void printCurrentGroupEnded(const TestResult& res) _override
|
||||
{
|
||||
output += StringFromFormat("Group End %d\n", (int) res.getTestCount());
|
||||
}
|
||||
|
||||
virtual void printCurrentTestStarted(const UtestShell&) _override
|
||||
{
|
||||
output += "s";
|
||||
}
|
||||
|
||||
void flush() _override
|
||||
{
|
||||
output += "flush";
|
||||
}
|
||||
|
||||
virtual bool isVerbose()
|
||||
{
|
||||
return verbose_ == level_verbose || verbose_ == level_veryVerbose;
|
||||
}
|
||||
|
||||
virtual bool isColor()
|
||||
{
|
||||
return color_;
|
||||
}
|
||||
|
||||
virtual const char* getProgressIndicator()
|
||||
{
|
||||
return progressIndication_;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_GROUP(CompositeTestOutput)
|
||||
{
|
||||
CompositeTestOutputTestStringBufferTestOutput* output1;
|
||||
CompositeTestOutputTestStringBufferTestOutput* output2;
|
||||
CompositeTestOutput compositeOutput;
|
||||
TestResult* result;
|
||||
UtestShell* test;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
output1 = new CompositeTestOutputTestStringBufferTestOutput;
|
||||
output2 = new CompositeTestOutputTestStringBufferTestOutput;
|
||||
compositeOutput.setOutputOne(output1);
|
||||
compositeOutput.setOutputTwo(output2);
|
||||
result = new TestResult(compositeOutput);
|
||||
test = new UtestShell("Group", "Name", "file", 10);
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
delete test;
|
||||
delete result;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(CompositeTestOutput, TestStartedAndEnded)
|
||||
{
|
||||
compositeOutput.printTestsStarted();
|
||||
compositeOutput.printTestsEnded(*result);
|
||||
STRCMP_EQUAL("Test Start\nTest End 0\n", output1->getOutput().asCharString());
|
||||
STRCMP_EQUAL("Test Start\nTest End 0\n", output2->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(CompositeTestOutput, CurrentTestStartedAndEnded)
|
||||
{
|
||||
compositeOutput.printCurrentTestStarted(*test);
|
||||
compositeOutput.printCurrentTestEnded(*result);
|
||||
STRCMP_EQUAL("s.", output1->getOutput().asCharString());
|
||||
STRCMP_EQUAL("s.", output2->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(CompositeTestOutput, CurrentGroupStartedAndEnded)
|
||||
{
|
||||
compositeOutput.printCurrentGroupStarted(*test);
|
||||
compositeOutput.printCurrentGroupEnded(*result);
|
||||
STRCMP_EQUAL("Group Group Start\nGroup End 0\n", output1->getOutput().asCharString());
|
||||
STRCMP_EQUAL("Group Group Start\nGroup End 0\n", output2->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(CompositeTestOutput, PrintBuffer)
|
||||
{
|
||||
compositeOutput.printBuffer("Boo");
|
||||
STRCMP_EQUAL("Boo", output1->getOutput().asCharString());
|
||||
STRCMP_EQUAL("Boo", output2->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(CompositeTestOutput, printChar)
|
||||
{
|
||||
compositeOutput.print("Boo");
|
||||
STRCMP_EQUAL("Boo", output1->getOutput().asCharString());
|
||||
STRCMP_EQUAL("Boo", output2->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(CompositeTestOutput, printLong)
|
||||
{
|
||||
long ten = 10;
|
||||
compositeOutput.print(ten);
|
||||
STRCMP_EQUAL("10", output1->getOutput().asCharString());
|
||||
STRCMP_EQUAL("10", output2->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(CompositeTestOutput, PrintSize)
|
||||
{
|
||||
size_t ten = 10;
|
||||
compositeOutput.print(ten);
|
||||
STRCMP_EQUAL("10", output1->getOutput().asCharString());
|
||||
STRCMP_EQUAL("10", output2->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(CompositeTestOutput, printDouble)
|
||||
{
|
||||
compositeOutput.printDouble(1.01);
|
||||
STRCMP_EQUAL("1.01", output1->getOutput().asCharString());
|
||||
STRCMP_EQUAL("1.01", output2->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(CompositeTestOutput, verbose)
|
||||
{
|
||||
compositeOutput.verbose(TestOutput::level_verbose);
|
||||
CHECK(output1->isVerbose());
|
||||
CHECK(output2->isVerbose());
|
||||
}
|
||||
|
||||
TEST(CompositeTestOutput, color)
|
||||
{
|
||||
compositeOutput.color();
|
||||
CHECK(output1->isColor());
|
||||
CHECK(output2->isColor());
|
||||
}
|
||||
|
||||
TEST(CompositeTestOutput, PrintTestFailure)
|
||||
{
|
||||
TestOutput::WorkingEnvironment previousEnvironment = TestOutput::getWorkingEnvironment();
|
||||
TestOutput::setWorkingEnvironment(TestOutput::eclipse);
|
||||
TestFailure failure(test, "file", 10, "failed");
|
||||
compositeOutput.printFailure(failure);
|
||||
STRCMP_EQUAL("\nfile:10: error: Failure in TEST(Group, Name)\n\tfailed\n\n", output1->getOutput().asCharString());
|
||||
STRCMP_EQUAL("\nfile:10: error: Failure in TEST(Group, Name)\n\tfailed\n\n", output2->getOutput().asCharString());
|
||||
TestOutput::setWorkingEnvironment(previousEnvironment);
|
||||
}
|
||||
|
||||
TEST(CompositeTestOutput, PrintTestRun)
|
||||
{
|
||||
compositeOutput.printTestRun(1, 2);
|
||||
STRCMP_EQUAL("Test run 1 of 2\n", output1->getOutput().asCharString());
|
||||
STRCMP_EQUAL("Test run 1 of 2\n", output2->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(CompositeTestOutput, setProgressIndicator)
|
||||
{
|
||||
compositeOutput.setProgressIndicator("?");
|
||||
STRCMP_EQUAL("?", output1->getProgressIndicator());
|
||||
STRCMP_EQUAL("?", output2->getProgressIndicator());
|
||||
}
|
||||
|
||||
TEST(CompositeTestOutput, flush)
|
||||
{
|
||||
compositeOutput.flush();
|
||||
STRCMP_EQUAL("flush", output1->getOutput().asCharString());
|
||||
STRCMP_EQUAL("flush", output2->getOutput().asCharString());
|
||||
}
|
||||
|
||||
TEST(CompositeTestOutput, deletePreviousInstanceWhenSettingNew)
|
||||
{
|
||||
compositeOutput.setOutputOne(new CompositeTestOutput);
|
||||
compositeOutput.setOutputTwo(new CompositeTestOutput);
|
||||
|
||||
// CHECK NO MEMORY LEAKS
|
||||
}
|
|
@ -0,0 +1,427 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/TestRegistry.h"
|
||||
#include "CppUTest/TestOutput.h"
|
||||
#include "CppUTest/PlatformSpecificFunctions.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
const int testLineNumber = 1;
|
||||
}
|
||||
|
||||
class MockTest: public UtestShell
|
||||
{
|
||||
public:
|
||||
MockTest(const char* group = "Group") :
|
||||
UtestShell(group, "Name", "File", testLineNumber), hasRun_(false)
|
||||
{
|
||||
}
|
||||
virtual void runOneTest(TestPlugin*, TestResult&) _override
|
||||
{
|
||||
hasRun_ = true;
|
||||
}
|
||||
|
||||
bool hasRun_;
|
||||
};
|
||||
|
||||
class MockTestResult: public TestResult
|
||||
{
|
||||
public:
|
||||
|
||||
int countTestsStarted;
|
||||
int countTestsEnded;
|
||||
int countCurrentTestStarted;
|
||||
int countCurrentTestEnded;
|
||||
int countCurrentGroupStarted;
|
||||
int countCurrentGroupEnded;
|
||||
|
||||
MockTestResult(TestOutput& p) :
|
||||
TestResult(p)
|
||||
{
|
||||
resetCount();
|
||||
}
|
||||
|
||||
virtual ~MockTestResult() _destructor_override
|
||||
{
|
||||
}
|
||||
|
||||
void resetCount()
|
||||
{
|
||||
countTestsStarted = 0;
|
||||
countTestsEnded = 0;
|
||||
countCurrentTestStarted = 0;
|
||||
countCurrentTestEnded = 0;
|
||||
countCurrentGroupStarted = 0;
|
||||
countCurrentGroupEnded = 0;
|
||||
}
|
||||
|
||||
virtual void testsStarted() _override
|
||||
{
|
||||
countTestsStarted++;
|
||||
}
|
||||
virtual void testsEnded() _override
|
||||
{
|
||||
countTestsEnded++;
|
||||
}
|
||||
virtual void currentTestStarted(UtestShell* /*test*/) _override
|
||||
{
|
||||
countCurrentTestStarted++;
|
||||
}
|
||||
virtual void currentTestEnded(UtestShell* /*test*/) _override
|
||||
{
|
||||
countCurrentTestEnded++;
|
||||
}
|
||||
virtual void currentGroupStarted(UtestShell* /*test*/) _override
|
||||
{
|
||||
countCurrentGroupStarted++;
|
||||
}
|
||||
virtual void currentGroupEnded(UtestShell* /*test*/) _override
|
||||
{
|
||||
countCurrentGroupEnded++;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TEST_GROUP(TestRegistry)
|
||||
{
|
||||
TestRegistry* myRegistry;
|
||||
StringBufferTestOutput* output;
|
||||
MockTest* test1;
|
||||
MockTest* test2;
|
||||
MockTest* test3;
|
||||
MockTest* test4;
|
||||
TestResult *result;
|
||||
MockTestResult *mockResult;
|
||||
void setup() _override
|
||||
{
|
||||
output = new StringBufferTestOutput();
|
||||
mockResult = new MockTestResult(*output);
|
||||
result = mockResult;
|
||||
test1 = new MockTest();
|
||||
test2 = new MockTest();
|
||||
test3 = new MockTest("group2");
|
||||
test4 = new MockTest();
|
||||
myRegistry = new TestRegistry();
|
||||
myRegistry->setCurrentRegistry(myRegistry);
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
myRegistry->setCurrentRegistry(NULLPTR);
|
||||
delete myRegistry;
|
||||
delete test1;
|
||||
delete test2;
|
||||
delete test3;
|
||||
delete test4;
|
||||
delete result;
|
||||
delete output;
|
||||
}
|
||||
|
||||
void addAndRunAllTests()
|
||||
{
|
||||
myRegistry->addTest(test1);
|
||||
myRegistry->addTest(test2);
|
||||
myRegistry->addTest(test3);
|
||||
myRegistry->runAllTests(*result);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TestRegistry, registryMyRegistryAndReset)
|
||||
{
|
||||
CHECK(myRegistry->getCurrentRegistry() == myRegistry);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, emptyRegistryIsEmpty)
|
||||
{
|
||||
CHECK(myRegistry->countTests() == 0);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, addOneTestIsNotEmpty)
|
||||
{
|
||||
myRegistry->addTest(test1);
|
||||
CHECK(myRegistry->countTests() == 1);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, addOneTwoTests)
|
||||
{
|
||||
myRegistry->addTest(test1);
|
||||
myRegistry->addTest(test2);
|
||||
CHECK(myRegistry->countTests() == 2);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, runTwoTests)
|
||||
{
|
||||
myRegistry->addTest(test1);
|
||||
myRegistry->addTest(test2);
|
||||
CHECK(!test1->hasRun_);
|
||||
CHECK(!test2->hasRun_);
|
||||
myRegistry->runAllTests(*result);
|
||||
CHECK(test1->hasRun_);
|
||||
CHECK(test2->hasRun_);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, runTwoTestsCheckResultFunctionsCalled)
|
||||
{
|
||||
myRegistry->addTest(test1);
|
||||
myRegistry->addTest(test2);
|
||||
myRegistry->runAllTests(*result);
|
||||
LONGS_EQUAL(1, mockResult->countTestsStarted);
|
||||
LONGS_EQUAL(1, mockResult->countTestsEnded);
|
||||
LONGS_EQUAL(1, mockResult->countCurrentGroupStarted);
|
||||
LONGS_EQUAL(1, mockResult->countCurrentGroupEnded);
|
||||
LONGS_EQUAL(2, mockResult->countCurrentTestStarted);
|
||||
LONGS_EQUAL(2, mockResult->countCurrentTestEnded);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, runThreeTestsandTwoGroupsCheckResultFunctionsCalled)
|
||||
{
|
||||
addAndRunAllTests();
|
||||
LONGS_EQUAL(2, mockResult->countCurrentGroupStarted);
|
||||
LONGS_EQUAL(2, mockResult->countCurrentGroupEnded);
|
||||
LONGS_EQUAL(3, mockResult->countCurrentTestStarted);
|
||||
LONGS_EQUAL(3, mockResult->countCurrentTestEnded);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, unDoTest)
|
||||
{
|
||||
myRegistry->addTest(test1);
|
||||
CHECK(myRegistry->countTests() == 1);
|
||||
myRegistry->unDoLastAddTest();
|
||||
CHECK(myRegistry->countTests() == 0);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, unDoButNoTest)
|
||||
{
|
||||
CHECK(myRegistry->countTests() == 0);
|
||||
myRegistry->unDoLastAddTest();
|
||||
CHECK(myRegistry->countTests() == 0);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, reallyUndoLastTest)
|
||||
{
|
||||
myRegistry->addTest(test1);
|
||||
myRegistry->addTest(test2);
|
||||
CHECK(myRegistry->countTests() == 2);
|
||||
myRegistry->unDoLastAddTest();
|
||||
CHECK(myRegistry->countTests() == 1);
|
||||
myRegistry->runAllTests(*result);
|
||||
CHECK(test1->hasRun_);
|
||||
CHECK(!test2->hasRun_);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, findTestWithNameDoesntExist)
|
||||
{
|
||||
CHECK(myRegistry->findTestWithName("ThisTestDoesntExists") == NULLPTR);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, findTestWithName)
|
||||
{
|
||||
test1->setTestName("NameOfATestThatDoesExist");
|
||||
test2->setTestName("SomeOtherTest");
|
||||
myRegistry->addTest(test1);
|
||||
myRegistry->addTest(test2);
|
||||
CHECK(myRegistry->findTestWithName("NameOfATestThatDoesExist") != NULLPTR);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, findTestWithGroupDoesntExist)
|
||||
{
|
||||
CHECK(myRegistry->findTestWithGroup("ThisTestGroupDoesntExists") == NULLPTR);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, findTestWithGroup)
|
||||
{
|
||||
test1->setGroupName("GroupOfATestThatDoesExist");
|
||||
test2->setGroupName("SomeOtherGroup");
|
||||
myRegistry->addTest(test1);
|
||||
myRegistry->addTest(test2);
|
||||
CHECK(myRegistry->findTestWithGroup("GroupOfATestThatDoesExist") != NULLPTR);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, nameFilterWorks)
|
||||
{
|
||||
test1->setTestName("testname");
|
||||
test2->setTestName("noname");
|
||||
TestFilter nameFilter("testname");
|
||||
myRegistry->setNameFilters(&nameFilter);
|
||||
addAndRunAllTests();
|
||||
CHECK(test1->hasRun_);
|
||||
CHECK(!test2->hasRun_);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, groupFilterWorks)
|
||||
{
|
||||
test1->setGroupName("groupname");
|
||||
test2->setGroupName("noname");
|
||||
TestFilter groupFilter("groupname");
|
||||
myRegistry->setGroupFilters(&groupFilter);
|
||||
addAndRunAllTests();
|
||||
CHECK(test1->hasRun_);
|
||||
CHECK(!test2->hasRun_);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, runTestInSeperateProcess)
|
||||
{
|
||||
myRegistry->setRunTestsInSeperateProcess();
|
||||
myRegistry->addTest(test1);
|
||||
myRegistry->runAllTests(*result);
|
||||
CHECK(test1->isRunInSeperateProcess());
|
||||
}
|
||||
|
||||
TEST(TestRegistry, CurrentRepetitionIsCorrectNone)
|
||||
{
|
||||
CHECK(0 == myRegistry->getCurrentRepetition());
|
||||
myRegistry->runAllTests(*result);
|
||||
LONGS_EQUAL(1, myRegistry->getCurrentRepetition());
|
||||
}
|
||||
|
||||
TEST(TestRegistry, CurrentRepetitionIsCorrectTwo)
|
||||
{
|
||||
CHECK(0 == myRegistry->getCurrentRepetition());
|
||||
myRegistry->runAllTests(*result);
|
||||
myRegistry->runAllTests(*result);
|
||||
LONGS_EQUAL(2, myRegistry->getCurrentRepetition());
|
||||
}
|
||||
|
||||
class MyTestPluginDummy: public TestPlugin
|
||||
{
|
||||
public:
|
||||
MyTestPluginDummy(const SimpleString& name) : TestPlugin(name) {}
|
||||
virtual ~MyTestPluginDummy() _destructor_override {}
|
||||
virtual void runAllPreTestAction(UtestShell&, TestResult&) _override {}
|
||||
virtual void runAllPostTestAction(UtestShell&, TestResult&) _override {}
|
||||
};
|
||||
|
||||
TEST(TestRegistry, ResetPluginsWorks)
|
||||
{
|
||||
MyTestPluginDummy plugin1("Plugin-1");
|
||||
MyTestPluginDummy plugin2("Plugin-2");
|
||||
myRegistry->installPlugin(&plugin1);
|
||||
myRegistry->installPlugin(&plugin2);
|
||||
LONGS_EQUAL(2, myRegistry->countPlugins());
|
||||
myRegistry->resetPlugins();
|
||||
LONGS_EQUAL(0, myRegistry->countPlugins());
|
||||
}
|
||||
|
||||
TEST(TestRegistry, listTestGroupNames_shouldListBackwardsGroup1AfterGroup11AndGroup2OnlyOnce)
|
||||
{
|
||||
test1->setGroupName("GROUP_1");
|
||||
myRegistry->addTest(test1);
|
||||
test2->setGroupName("GROUP_2");
|
||||
myRegistry->addTest(test2);
|
||||
test3->setGroupName("GROUP_11");
|
||||
myRegistry->addTest(test3);
|
||||
test4->setGroupName("GROUP_2");
|
||||
myRegistry->addTest(test4);
|
||||
|
||||
myRegistry->listTestGroupNames(*result);
|
||||
SimpleString s = output->getOutput();
|
||||
STRCMP_EQUAL("GROUP_2 GROUP_11 GROUP_1", s.asCharString());
|
||||
}
|
||||
|
||||
TEST(TestRegistry, listTestGroupAndCaseNames_shouldListBackwardsGroupATestaAfterGroupAtestaa)
|
||||
{
|
||||
test1->setGroupName("GROUP_A");
|
||||
test1->setTestName("test_a");
|
||||
myRegistry->addTest(test1);
|
||||
test2->setGroupName("GROUP_B");
|
||||
test2->setTestName("test_b");
|
||||
myRegistry->addTest(test2);
|
||||
test3->setGroupName("GROUP_A");
|
||||
test3->setTestName("test_aa");
|
||||
myRegistry->addTest(test3);
|
||||
|
||||
myRegistry->listTestGroupAndCaseNames(*result);
|
||||
SimpleString s = output->getOutput();
|
||||
STRCMP_EQUAL("GROUP_A.test_aa GROUP_B.test_b GROUP_A.test_a", s.asCharString());
|
||||
}
|
||||
|
||||
TEST(TestRegistry, shuffleEmptyListIsNoOp)
|
||||
{
|
||||
CHECK_TRUE(myRegistry->getFirstTest() == NULLPTR);
|
||||
myRegistry->shuffleTests(0);
|
||||
CHECK_TRUE(myRegistry->getFirstTest() == NULLPTR);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, shuffleSingleTestIsNoOp)
|
||||
{
|
||||
myRegistry->addTest(test1);
|
||||
myRegistry->shuffleTests(0);
|
||||
CHECK_TRUE(myRegistry->getFirstTest() == test1);
|
||||
}
|
||||
|
||||
static int getZero()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
IGNORE_TEST(TestRegistry, shuffleTestList)
|
||||
{
|
||||
UT_PTR_SET(PlatformSpecificRand, getZero);
|
||||
myRegistry->addTest(test3);
|
||||
myRegistry->addTest(test2);
|
||||
myRegistry->addTest(test1);
|
||||
|
||||
UtestShell* first_before = myRegistry->getFirstTest();
|
||||
UtestShell* second_before = first_before->getNext();
|
||||
UtestShell* third_before = second_before->getNext();
|
||||
|
||||
CHECK_TRUE(first_before == test1);
|
||||
CHECK_TRUE(second_before == test2);
|
||||
CHECK_TRUE(third_before == test3);
|
||||
CHECK_TRUE(third_before->getNext() == NULLPTR);
|
||||
|
||||
// shuffle always with element at index 0: [1] 2 [3] --> [3] [2] 1 --> 2 3 1
|
||||
myRegistry->shuffleTests(0);
|
||||
|
||||
UtestShell* first_after = myRegistry->getFirstTest();
|
||||
UtestShell* second_after = first_after->getNext();
|
||||
UtestShell* third_after = second_after->getNext();
|
||||
|
||||
CHECK_TRUE(first_after == test2);
|
||||
CHECK_TRUE(second_after == test3);
|
||||
CHECK_TRUE(third_after == test1);
|
||||
CHECK_TRUE(third_after->getNext() == NULLPTR);
|
||||
}
|
||||
|
||||
TEST(TestRegistry, reverseTests)
|
||||
{
|
||||
myRegistry->addTest(test1);
|
||||
myRegistry->addTest(test2);
|
||||
|
||||
myRegistry->reverseTests();
|
||||
|
||||
CHECK(test1 == myRegistry->getFirstTest());
|
||||
}
|
||||
|
||||
TEST(TestRegistry, reverseZeroTests)
|
||||
{
|
||||
myRegistry->reverseTests();
|
||||
|
||||
CHECK(NULLPTR == myRegistry->getFirstTest());
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/PlatformSpecificFunctions.h"
|
||||
#include "CppUTest/TestOutput.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
static long MockGetPlatformSpecificTimeInMillis()
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_GROUP(TestResult)
|
||||
{
|
||||
TestOutput* printer;
|
||||
StringBufferTestOutput* mock;
|
||||
|
||||
TestResult* res;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
mock = new StringBufferTestOutput();
|
||||
printer = mock;
|
||||
res = new TestResult(*printer);
|
||||
UT_PTR_SET(GetPlatformSpecificTimeInMillis, MockGetPlatformSpecificTimeInMillis);
|
||||
}
|
||||
void teardown() _override
|
||||
{
|
||||
delete printer;
|
||||
delete res;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TestResult, TestEndedWillPrintResultsAndExecutionTime)
|
||||
{
|
||||
res->testsEnded();
|
||||
CHECK(mock->getOutput().contains("10 ms"));
|
||||
}
|
||||
|
||||
TEST(TestResult, ResultIsOkIfTestIsRunWithNoFailures)
|
||||
{
|
||||
res->countTest();
|
||||
res->countRun();
|
||||
CHECK_FALSE(res->isFailure());
|
||||
}
|
||||
|
||||
TEST(TestResult, ResultIsOkIfTestIsIgnored)
|
||||
{
|
||||
res->countTest();
|
||||
res->countIgnored();
|
||||
CHECK_FALSE(res->isFailure());
|
||||
}
|
||||
|
||||
TEST(TestResult, ResultIsNotOkIfFailures)
|
||||
{
|
||||
res->countTest();
|
||||
res->countRun();
|
||||
res->addFailure(TestFailure(UtestShell::getCurrent(), StringFrom("dummy message")));
|
||||
CHECK_TRUE(res->isFailure());
|
||||
}
|
||||
|
||||
TEST(TestResult, ResultIsNotOkIfNoTestsAtAll)
|
||||
{
|
||||
CHECK_TRUE(res->isFailure());
|
||||
}
|
||||
|
||||
TEST(TestResult, ResultIsNotOkIfNoTestsRunOrIgnored)
|
||||
{
|
||||
res->countTest();
|
||||
CHECK_TRUE(res->isFailure());
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,468 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/TestOutput.h"
|
||||
#include "CppUTest/TestTestingFixture.h"
|
||||
|
||||
#define CHECK_TEST_FAILS_PROPER_WITH_TEXT(text) fixture.checkTestFailsWithProperTestLocation(text, __FILE__, __LINE__)
|
||||
|
||||
TEST_GROUP(UnitTestStringMacros)
|
||||
{
|
||||
TestTestingFixture fixture;
|
||||
};
|
||||
|
||||
static void _STRCMP_EQUALWithActualIsNULLTestMethod()
|
||||
{
|
||||
STRCMP_EQUAL("ok", NULLPTR);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_EQUALAndActualIsNULL)
|
||||
{
|
||||
fixture.runTestWithMethod(_STRCMP_EQUALWithActualIsNULLTestMethod);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("but was <(null)>");
|
||||
}
|
||||
|
||||
static void _STRCMP_EQUALWithExpectedIsNULLTestMethod()
|
||||
{
|
||||
STRCMP_EQUAL(NULLPTR, "ok");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_EQUALAndExpectedIsNULL)
|
||||
{
|
||||
fixture.runTestWithMethod(_STRCMP_EQUALWithExpectedIsNULLTestMethod);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("expected <(null)>");
|
||||
}
|
||||
|
||||
static void _STRCMP_CONTAINSWithActualIsNULLTestMethod()
|
||||
{
|
||||
STRCMP_CONTAINS("ok", NULLPTR);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_CONTAINSAndActualIsNULL)
|
||||
{
|
||||
fixture.runTestWithMethod(_STRCMP_CONTAINSWithActualIsNULLTestMethod);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("did not contain <ok>");
|
||||
}
|
||||
|
||||
static void _STRCMP_CONTAINSWithExpectedIsNULLTestMethod()
|
||||
{
|
||||
STRCMP_CONTAINS(NULLPTR, "ok");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_CONTAINSAndExpectedIsNULL)
|
||||
{
|
||||
fixture.runTestWithMethod(_STRCMP_CONTAINSWithExpectedIsNULLTestMethod);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("did not contain <>");
|
||||
}
|
||||
|
||||
static void _STRNCMP_EQUALWithActualIsNULLTestMethod()
|
||||
{
|
||||
STRNCMP_EQUAL("ok", NULLPTR, 2);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRNCMP_EQUALAndActualIsNULL)
|
||||
{
|
||||
fixture.runTestWithMethod(_STRNCMP_EQUALWithActualIsNULLTestMethod);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("but was <(null)>");
|
||||
}
|
||||
|
||||
static void _STRNCMP_EQUALWithExpectedIsNULLTestMethod()
|
||||
{
|
||||
STRNCMP_EQUAL(NULLPTR, "ok", 2);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRNCMP_EQUALAndExpectedIsNULL)
|
||||
{
|
||||
fixture.runTestWithMethod(_STRNCMP_EQUALWithExpectedIsNULLTestMethod);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("expected <(null)>");
|
||||
}
|
||||
|
||||
static void _STRCMP_NOCASE_EQUALWithActualIsNULLTestMethod()
|
||||
{
|
||||
STRCMP_NOCASE_EQUAL("ok", NULLPTR);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_NOCASE_EQUALAndActualIsNULL)
|
||||
{
|
||||
fixture.runTestWithMethod(_STRCMP_NOCASE_EQUALWithActualIsNULLTestMethod);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("but was <(null)>");
|
||||
}
|
||||
|
||||
static void _STRCMP_NOCASE_EQUALWithExpectedIsNULLTestMethod()
|
||||
{
|
||||
STRCMP_NOCASE_EQUAL(NULLPTR, "ok");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_NOCASE_EQUALAndExpectedIsNULL)
|
||||
{
|
||||
fixture.runTestWithMethod(_STRCMP_NOCASE_EQUALWithExpectedIsNULLTestMethod);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("expected <(null)>");
|
||||
}
|
||||
|
||||
static void _STRCMP_NOCASE_EQUALWithUnequalInputTestMethod()
|
||||
{
|
||||
STRCMP_NOCASE_EQUAL("no", "ok");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_NOCASE_EQUALAndUnequalInput)
|
||||
{
|
||||
fixture.runTestWithMethod(_STRCMP_NOCASE_EQUALWithUnequalInputTestMethod);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("but was <ok>");
|
||||
}
|
||||
|
||||
static void _STRCMP_NOCASE_CONTAINSWithActualIsNULLTestMethod()
|
||||
{
|
||||
STRCMP_NOCASE_CONTAINS("ok", NULLPTR);
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_NOCASE_CONTAINSAndActualIsNULL)
|
||||
{
|
||||
fixture.runTestWithMethod(_STRCMP_NOCASE_CONTAINSWithActualIsNULLTestMethod);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("did not contain <ok>");
|
||||
}
|
||||
|
||||
static void _STRCMP_NOCASE_CONTAINSWithExpectedIsNULLTestMethod()
|
||||
{
|
||||
STRCMP_NOCASE_CONTAINS(NULLPTR, "ok");
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_NOCASE_CONTAINSAndExpectedIsNULL)
|
||||
{
|
||||
fixture.runTestWithMethod(_STRCMP_NOCASE_CONTAINSWithExpectedIsNULLTestMethod);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("did not contain <>");
|
||||
}
|
||||
|
||||
static void _failingTestMethodWithSTRCMP_EQUAL()
|
||||
{
|
||||
STRCMP_EQUAL("hello", "hell");
|
||||
TestTestingFixture::lineExecutedAfterCheck(); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_EQUAL)
|
||||
{
|
||||
fixture.runTestWithMethod(_failingTestMethodWithSTRCMP_EQUAL);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("expected <hello>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("but was <hell>");
|
||||
}
|
||||
|
||||
TEST(UnitTestStringMacros, STRCMP_EQUALBehavesAsProperMacro)
|
||||
{
|
||||
if (false) STRCMP_EQUAL("1", "2");
|
||||
else STRCMP_EQUAL("1", "1");
|
||||
}
|
||||
|
||||
IGNORE_TEST(UnitTestStringMacros, STRCMP_EQUALWorksInAnIgnoredTest)
|
||||
{
|
||||
STRCMP_EQUAL("Hello", "World"); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
static void _failingTestMethodWithSTRCMP_EQUAL_TEXT()
|
||||
{
|
||||
STRCMP_EQUAL_TEXT("hello", "hell", "Failed because it failed");
|
||||
TestTestingFixture::lineExecutedAfterCheck(); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_EQUAL_TEXT)
|
||||
{
|
||||
fixture.runTestWithMethod(_failingTestMethodWithSTRCMP_EQUAL_TEXT);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("expected <hello>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("but was <hell>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("Failed because it failed");
|
||||
}
|
||||
|
||||
TEST(UnitTestStringMacros, STRCMP_EQUAL_TEXTBehavesAsProperMacro)
|
||||
{
|
||||
if (false) STRCMP_EQUAL_TEXT("1", "2", "Failed because it failed");
|
||||
else STRCMP_EQUAL_TEXT("1", "1", "Failed because it failed");
|
||||
}
|
||||
|
||||
IGNORE_TEST(UnitTestStringMacros, STRCMP_EQUAL_TEXTWorksInAnIgnoredTest)
|
||||
{
|
||||
STRCMP_EQUAL_TEXT("Hello", "World", "Failed because it failed"); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
static void _failingTestMethodWithSTRNCMP_EQUAL()
|
||||
{
|
||||
STRNCMP_EQUAL("hello", "hallo", 5);
|
||||
TestTestingFixture::lineExecutedAfterCheck(); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRNCMP_EQUAL)
|
||||
{
|
||||
fixture.runTestWithMethod(_failingTestMethodWithSTRNCMP_EQUAL);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("expected <hello>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("but was <hallo>");
|
||||
}
|
||||
|
||||
TEST(UnitTestStringMacros, STRNCMP_EQUALBehavesAsProperMacro)
|
||||
{
|
||||
if (false) STRNCMP_EQUAL("1", "2", 1);
|
||||
else STRNCMP_EQUAL("1", "1", 1);
|
||||
}
|
||||
|
||||
IGNORE_TEST(UnitTestStringMacros, STRNCMP_EQUALWorksInAnIgnoredTest)
|
||||
{
|
||||
STRNCMP_EQUAL("Hello", "World", 3); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
static void _failingTestMethodWithSTRNCMP_EQUAL_TEXT()
|
||||
{
|
||||
STRNCMP_EQUAL_TEXT("hello", "hallo", 5, "Failed because it failed");
|
||||
TestTestingFixture::lineExecutedAfterCheck(); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRNCMP_EQUAL_TEXT)
|
||||
{
|
||||
fixture.runTestWithMethod(_failingTestMethodWithSTRNCMP_EQUAL_TEXT);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("expected <hello>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("but was <hallo>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("Failed because it failed");
|
||||
}
|
||||
|
||||
TEST(UnitTestStringMacros, STRNCMP_EQUAL_TEXTBehavesAsProperMacro)
|
||||
{
|
||||
if (false) STRNCMP_EQUAL_TEXT("1", "2", 1, "Failed because it failed");
|
||||
else STRNCMP_EQUAL_TEXT("1", "1", 1, "Failed because it failed");
|
||||
}
|
||||
|
||||
IGNORE_TEST(UnitTestStringMacros, STRNCMP_EQUAL_TEXTWorksInAnIgnoredTest)
|
||||
{
|
||||
STRNCMP_EQUAL_TEXT("Hello", "World", 3, "Failed because it failed"); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
static void _failingTestMethodWithSTRCMP_NOCASE_EQUAL()
|
||||
{
|
||||
STRCMP_NOCASE_EQUAL("hello", "Hell");
|
||||
TestTestingFixture::lineExecutedAfterCheck(); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_NOCASE_EQUAL)
|
||||
{
|
||||
fixture.runTestWithMethod(_failingTestMethodWithSTRCMP_NOCASE_EQUAL);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("expected <hello>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("but was <Hell>");
|
||||
}
|
||||
|
||||
TEST(UnitTestStringMacros, STRCMP_NOCASE_EQUALBehavesAsProperMacro)
|
||||
{
|
||||
if (false) STRCMP_NOCASE_EQUAL("1", "2");
|
||||
else STRCMP_NOCASE_EQUAL("1", "1");
|
||||
}
|
||||
|
||||
IGNORE_TEST(UnitTestStringMacros, STRCMP_NOCASE_EQUALWorksInAnIgnoredTest)
|
||||
{
|
||||
STRCMP_NOCASE_EQUAL("Hello", "World"); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
static void _failingTestMethodWithSTRCMP_NOCASE_EQUAL_TEXT()
|
||||
{
|
||||
STRCMP_NOCASE_EQUAL_TEXT("hello", "hell", "Failed because it failed");
|
||||
TestTestingFixture::lineExecutedAfterCheck(); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_NOCASE_EQUAL_TEXT)
|
||||
{
|
||||
fixture.runTestWithMethod(_failingTestMethodWithSTRCMP_NOCASE_EQUAL_TEXT);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("expected <hello>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("but was <hell>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("Failed because it failed");
|
||||
}
|
||||
|
||||
TEST(UnitTestStringMacros, STRCMP_NOCASE_EQUAL_TEXTBehavesAsProperMacro)
|
||||
{
|
||||
if (false) STRCMP_NOCASE_EQUAL_TEXT("1", "2", "Failed because it failed");
|
||||
else STRCMP_NOCASE_EQUAL_TEXT("1", "1", "Failed because it failed");
|
||||
}
|
||||
|
||||
IGNORE_TEST(UnitTestStringMacros, STRCMP_NOCASE_EQUAL_TEXTWorksInAnIgnoredTest)
|
||||
{
|
||||
STRCMP_NOCASE_EQUAL_TEXT("Hello", "World", "Failed because it failed"); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
static void _failingTestMethodWithSTRCMP_CONTAINS()
|
||||
{
|
||||
STRCMP_CONTAINS("hello", "world");
|
||||
TestTestingFixture::lineExecutedAfterCheck(); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_CONTAINS)
|
||||
{
|
||||
fixture.runTestWithMethod(_failingTestMethodWithSTRCMP_CONTAINS);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("actual <world>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("did not contain <hello>");
|
||||
}
|
||||
|
||||
TEST(UnitTestStringMacros, STRCMP_CONTAINSBehavesAsProperMacro)
|
||||
{
|
||||
if (false) STRCMP_CONTAINS("1", "2");
|
||||
else STRCMP_CONTAINS("1", "1");
|
||||
}
|
||||
|
||||
IGNORE_TEST(UnitTestStringMacros, STRCMP_CONTAINSWorksInAnIgnoredTest)
|
||||
{
|
||||
STRCMP_CONTAINS("Hello", "World"); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
static void _failingTestMethodWithSTRCMP_CONTAINS_TEXT()
|
||||
{
|
||||
STRCMP_CONTAINS_TEXT("hello", "world", "Failed because it failed");
|
||||
TestTestingFixture::lineExecutedAfterCheck(); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_CONTAINS_TEXT)
|
||||
{
|
||||
fixture.runTestWithMethod(_failingTestMethodWithSTRCMP_CONTAINS_TEXT);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("actual <world>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("did not contain <hello>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("Failed because it failed");
|
||||
}
|
||||
|
||||
TEST(UnitTestStringMacros, STRCMP_CONTAINS_TEXTBehavesAsProperMacro)
|
||||
{
|
||||
if (false) STRCMP_CONTAINS_TEXT("1", "2", "Failed because it failed");
|
||||
else STRCMP_CONTAINS_TEXT("1", "1", "Failed because it failed");
|
||||
}
|
||||
|
||||
IGNORE_TEST(UnitTestStringMacros, STRCMP_CONTAINS_TEXTWorksInAnIgnoredTest)
|
||||
{
|
||||
STRCMP_CONTAINS_TEXT("Hello", "World", "Failed because it failed"); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
static void _failingTestMethodWithSTRCMP_NOCASE_CONTAINS()
|
||||
{
|
||||
STRCMP_NOCASE_CONTAINS("hello", "WORLD");
|
||||
TestTestingFixture::lineExecutedAfterCheck(); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_NOCASE_CONTAINS)
|
||||
{
|
||||
fixture.runTestWithMethod(_failingTestMethodWithSTRCMP_NOCASE_CONTAINS);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("actual <WORLD>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("did not contain <hello>");
|
||||
}
|
||||
|
||||
TEST(UnitTestStringMacros, STRCMP_NOCASE_CONTAINSBehavesAsProperMacro)
|
||||
{
|
||||
if (false) STRCMP_NOCASE_CONTAINS("never", "executed");
|
||||
else STRCMP_NOCASE_CONTAINS("hello", "HELLO WORLD");
|
||||
}
|
||||
|
||||
IGNORE_TEST(UnitTestStringMacros, STRCMP_NO_CASE_CONTAINSWorksInAnIgnoredTest)
|
||||
{
|
||||
STRCMP_NOCASE_CONTAINS("Hello", "World"); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
static void _failingTestMethodWithSTRCMP_NOCASE_CONTAINS_TEXT()
|
||||
{
|
||||
STRCMP_NOCASE_CONTAINS_TEXT("hello", "WORLD", "Failed because it failed");
|
||||
TestTestingFixture::lineExecutedAfterCheck(); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
TEST(UnitTestStringMacros, FailureWithSTRCMP_NOCASE_CONTAINS_TEXT)
|
||||
{
|
||||
fixture.runTestWithMethod(_failingTestMethodWithSTRCMP_NOCASE_CONTAINS_TEXT);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("actual <WORLD>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("did not contain <hello>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("Failed because it failed");
|
||||
}
|
||||
|
||||
TEST(UnitTestStringMacros, STRCMP_NOCASE_CONTAINS_TEXTBehavesAsProperMacro)
|
||||
{
|
||||
if (false) STRCMP_NOCASE_CONTAINS_TEXT("never", "executed", "Failed because it failed");
|
||||
else STRCMP_NOCASE_CONTAINS_TEXT("hello", "HELLO WORLD", "Failed because it failed");
|
||||
}
|
||||
|
||||
IGNORE_TEST(UnitTestStringMacros, STRCMP_NO_CASE_CONTAINS_TEXTWorksInAnIgnoredTest)
|
||||
{
|
||||
STRCMP_NOCASE_CONTAINS_TEXT("Hello", "World", "Failed because it failed"); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, NFirstCharsComparison)
|
||||
{
|
||||
STRNCMP_EQUAL("Hello World!", "Hello Peter!", 0);
|
||||
STRNCMP_EQUAL("Hello World!", "Hello Peter!", 1);
|
||||
STRNCMP_EQUAL("Hello World!", "Hello Peter!", 6);
|
||||
STRNCMP_EQUAL("Hello World!", "Hello", 5);
|
||||
}
|
||||
|
||||
static void _compareNFirstCharsWithUpperAndLowercase()
|
||||
{
|
||||
STRNCMP_EQUAL("hello world!", "HELLO WORLD!", 12);
|
||||
TestTestingFixture::lineExecutedAfterCheck(); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, CompareNFirstCharsWithUpperAndLowercase)
|
||||
{
|
||||
fixture.runTestWithMethod(_compareNFirstCharsWithUpperAndLowercase);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("expected <hello world!>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("but was <HELLO WORLD!>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("difference starts at position 0");
|
||||
}
|
||||
|
||||
static void _compareNFirstCharsWithDifferenceInTheMiddle()
|
||||
{
|
||||
STRNCMP_EQUAL("Hello World!", "Hello Peter!", 12);
|
||||
TestTestingFixture::lineExecutedAfterCheck(); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, CompareNFirstCharsWithDifferenceInTheMiddle)
|
||||
{
|
||||
fixture.runTestWithMethod(_compareNFirstCharsWithDifferenceInTheMiddle);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("expected <Hello World!>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("but was <Hello Peter!>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("difference starts at position 6");
|
||||
}
|
||||
|
||||
static void _compareNFirstCharsWithEmptyString()
|
||||
{
|
||||
STRNCMP_EQUAL("", "Not empty string", 5);
|
||||
TestTestingFixture::lineExecutedAfterCheck(); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, CompareNFirstCharsWithEmptyString)
|
||||
{
|
||||
fixture.runTestWithMethod(_compareNFirstCharsWithEmptyString);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("expected <>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("but was <Not empty string>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("difference starts at position 0");
|
||||
}
|
||||
|
||||
static void _compareNFirstCharsWithLastCharDifferent()
|
||||
{
|
||||
STRNCMP_EQUAL("Not empty string?", "Not empty string!", 17);
|
||||
TestTestingFixture::lineExecutedAfterCheck(); // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
TEST(UnitTestStringMacros, CompareNFirstCharsWithLastCharDifferent)
|
||||
{
|
||||
fixture.runTestWithMethod(_compareNFirstCharsWithLastCharDifferent);
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("expected <Not empty string?>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("but was <Not empty string!>");
|
||||
CHECK_TEST_FAILS_PROPER_WITH_TEXT("difference starts at position 16");
|
||||
}
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/CommandLineTestRunner.h"
|
||||
#include "CppUTest/TestHarness.h"
|
||||
#include "CppUTest/TestTestingFixture.h"
|
||||
#include "CppUTest/PlatformSpecificFunctions.h"
|
||||
#include "CppUTest/StandardCLibrary.h"
|
||||
#include "CppUTest/TestMemoryAllocator.h"
|
||||
|
||||
#if CPPUTEST_USE_STD_C_LIB
|
||||
|
||||
// This will cause a crash in VS2010 due to PlatformSpecificFree being uninitialized
|
||||
static const SimpleString str1("abc");
|
||||
static const SimpleString str2("def");
|
||||
static const SimpleString str3(str1 + str2);
|
||||
|
||||
TEST_GROUP(UTestPlatformsTest_PlatformSpecificRunTestInASeperateProcess)
|
||||
{
|
||||
TestTestingFixture fixture;
|
||||
};
|
||||
|
||||
#ifndef CPPUTEST_HAVE_FORK
|
||||
|
||||
TEST(UTestPlatformsTest_PlatformSpecificRunTestInASeperateProcess, DummyFailsWithMessage)
|
||||
{
|
||||
fixture.setRunTestsInSeperateProcess();
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("-p doesn't work on this platform, as it is lacking fork.\b");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void _failFunction()
|
||||
{
|
||||
FAIL("This test fails");
|
||||
}
|
||||
|
||||
static void _exitNonZeroFunction() _no_return_;
|
||||
static void _exitNonZeroFunction()
|
||||
{
|
||||
/* destructor of static objects will be called. If StringCache was there then the allocator will report invalid deallocations of static SimpleString */
|
||||
SimpleString::setStringAllocator(SimpleString::getStringAllocator()->actualAllocator());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
static int waitpid_while_debugging_stub_number_called = 0;
|
||||
static int waitpid_while_debugging_stub_forced_failures = 0;
|
||||
|
||||
extern "C" {
|
||||
|
||||
static int (*original_waitpid)(int, int*, int) = NULLPTR;
|
||||
|
||||
static int fork_failed_stub(void) { return -1; }
|
||||
|
||||
static int waitpid_while_debugging_stub(int pid, int* status, int options)
|
||||
{
|
||||
static int saved_status;
|
||||
|
||||
if (waitpid_while_debugging_stub_number_called++ < waitpid_while_debugging_stub_forced_failures) {
|
||||
saved_status = *status;
|
||||
errno=EINTR;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
*status = saved_status;
|
||||
return original_waitpid(pid, status, options);
|
||||
}
|
||||
}
|
||||
|
||||
static int waitpid_failed_stub(int, int*, int) { return -1; }
|
||||
}
|
||||
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
static void _stoppedTestFunction()
|
||||
{
|
||||
kill(getpid(), SIGSTOP);
|
||||
}
|
||||
|
||||
TEST(UTestPlatformsTest_PlatformSpecificRunTestInASeperateProcess, TestInSeparateProcessWorks)
|
||||
{
|
||||
fixture.setRunTestsInSeperateProcess();
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("OK (1 tests, 1 ran, 0 checks, 0 ignored, 0 filtered out");
|
||||
}
|
||||
|
||||
TEST(UTestPlatformsTest_PlatformSpecificRunTestInASeperateProcess, FailureInSeparateProcessWorks)
|
||||
{
|
||||
fixture.setRunTestsInSeperateProcess();
|
||||
fixture.setTestFunction(_failFunction);
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("Failed in separate process");
|
||||
fixture.assertPrintContains("Errors (1 failures, 1 tests, 1 ran, 0 checks, 0 ignored, 0 filtered out");
|
||||
}
|
||||
|
||||
#if (! CPPUTEST_SANITIZE_ADDRESS)
|
||||
|
||||
static int _accessViolationTestFunction()
|
||||
{
|
||||
return *(volatile int*) NULLPTR;
|
||||
}
|
||||
|
||||
TEST(UTestPlatformsTest_PlatformSpecificRunTestInASeperateProcess, AccessViolationInSeparateProcessWorks)
|
||||
{
|
||||
fixture.setRunTestsInSeperateProcess();
|
||||
fixture.setTestFunction((void(*)())_accessViolationTestFunction);
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("Failed in separate process - killed by signal 11");
|
||||
fixture.assertPrintContains("Errors (1 failures, 1 tests, 1 ran");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST(UTestPlatformsTest_PlatformSpecificRunTestInASeperateProcess, StoppedInSeparateProcessWorks)
|
||||
{
|
||||
fixture.setRunTestsInSeperateProcess();
|
||||
fixture.setTestFunction(_stoppedTestFunction);
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("Stopped in separate process - continuing");
|
||||
fixture.assertPrintContains("Errors (1 failures, 1 tests, 1 ran");
|
||||
}
|
||||
|
||||
TEST(UTestPlatformsTest_PlatformSpecificRunTestInASeperateProcess, CallToForkFailedInSeparateProcessWorks)
|
||||
{
|
||||
UT_PTR_SET(PlatformSpecificFork, fork_failed_stub);
|
||||
fixture.setRunTestsInSeperateProcess();
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("Call to fork() failed");
|
||||
fixture.assertPrintContains("Errors (1 failures, 1 tests, 1 ran");
|
||||
}
|
||||
|
||||
TEST(UTestPlatformsTest_PlatformSpecificRunTestInASeperateProcess, CallToWaitPidWhileDebuggingInSeparateProcessWorks)
|
||||
{
|
||||
UT_PTR_SET(original_waitpid, PlatformSpecificWaitPid);
|
||||
UT_PTR_SET(PlatformSpecificWaitPid, waitpid_while_debugging_stub);
|
||||
waitpid_while_debugging_stub_number_called = 0;
|
||||
waitpid_while_debugging_stub_forced_failures = 10;
|
||||
fixture.setRunTestsInSeperateProcess();
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("OK (1 tests, 1 ran, 0 checks, 0 ignored, 0 filtered out");
|
||||
// extra check to confirm that waitpid() was polled until it passed (and passed call adds one)
|
||||
CHECK(waitpid_while_debugging_stub_number_called > waitpid_while_debugging_stub_forced_failures);
|
||||
}
|
||||
|
||||
TEST(UTestPlatformsTest_PlatformSpecificRunTestInASeperateProcess, CallToWaitPidStopsAndReportsAnErrorAfter20TimesRetry)
|
||||
{
|
||||
UT_PTR_SET(original_waitpid, PlatformSpecificWaitPid);
|
||||
UT_PTR_SET(PlatformSpecificWaitPid, waitpid_while_debugging_stub);
|
||||
waitpid_while_debugging_stub_number_called = 0;
|
||||
waitpid_while_debugging_stub_forced_failures = 40;
|
||||
fixture.setRunTestsInSeperateProcess();
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("Call to waitpid() failed with EINTR. Tried 30 times and giving up! Sometimes happens in debugger");
|
||||
// extra check to confirm that waitpid() was polled until it passed (and passed call adds one)
|
||||
CHECK(waitpid_while_debugging_stub_number_called > 30);
|
||||
}
|
||||
|
||||
|
||||
TEST(UTestPlatformsTest_PlatformSpecificRunTestInASeperateProcess, CallToWaitPidFailedInSeparateProcessWorks)
|
||||
{
|
||||
UT_PTR_SET(PlatformSpecificWaitPid, waitpid_failed_stub);
|
||||
fixture.setRunTestsInSeperateProcess();
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("Call to waitpid() failed");
|
||||
fixture.assertPrintContains("Errors (1 failures, 1 tests, 1 ran");
|
||||
}
|
||||
|
||||
TEST(UTestPlatformsTest_PlatformSpecificRunTestInASeperateProcess, MultipleTestsInSeparateProcessAreCountedProperly)
|
||||
{
|
||||
fixture.setRunTestsInSeperateProcess();
|
||||
fixture.runTestWithMethod(NULLPTR);
|
||||
fixture.runTestWithMethod(_stoppedTestFunction);
|
||||
fixture.runTestWithMethod(NULLPTR);
|
||||
fixture.runTestWithMethod(_exitNonZeroFunction);
|
||||
fixture.runTestWithMethod(NULLPTR);
|
||||
fixture.assertPrintContains("Failed in separate process");
|
||||
fixture.assertPrintContains("Stopped in separate process");
|
||||
fixture.assertPrintContains("Errors (2 failures, 5 tests, 5 ran, 0 checks, 0 ignored, 0 filtered out");
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,537 @@
|
|||
/*
|
||||
* 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 <organization> 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 <copyright holder> 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/TestOutput.h"
|
||||
#include "CppUTest/TestTestingFixture.h"
|
||||
#include "CppUTest/PlatformSpecificFunctions.h"
|
||||
|
||||
TEST_GROUP(UtestShell)
|
||||
{
|
||||
TestTestingFixture fixture;
|
||||
};
|
||||
|
||||
static void _failMethod()
|
||||
{
|
||||
FAIL("This test fails");
|
||||
}
|
||||
|
||||
static void _passingTestMethod()
|
||||
{
|
||||
CHECK(true);
|
||||
}
|
||||
|
||||
static void _passingCheckEqualTestMethod()
|
||||
{
|
||||
CHECK_EQUAL(1, 1);
|
||||
}
|
||||
|
||||
static void _exitTestMethod()
|
||||
{
|
||||
TEST_EXIT;
|
||||
FAIL("Should not get here");
|
||||
}
|
||||
|
||||
static volatile double zero = 0.0;
|
||||
|
||||
TEST(UtestShell, compareDoubles)
|
||||
{
|
||||
double not_a_number = zero / zero;
|
||||
double infinity = 1 / zero;
|
||||
CHECK(doubles_equal(1.0, 1.001, 0.01));
|
||||
CHECK(!doubles_equal(not_a_number, 1.001, 0.01));
|
||||
CHECK(!doubles_equal(1.0, not_a_number, 0.01));
|
||||
CHECK(!doubles_equal(1.0, 1.001, not_a_number));
|
||||
CHECK(!doubles_equal(1.0, 1.1, 0.05));
|
||||
CHECK(!doubles_equal(infinity, 1.0, 0.01));
|
||||
CHECK(!doubles_equal(1.0, infinity, 0.01));
|
||||
CHECK(doubles_equal(1.0, -1.0, infinity));
|
||||
CHECK(doubles_equal(infinity, infinity, 0.01));
|
||||
CHECK(doubles_equal(infinity, infinity, infinity));
|
||||
double a = 1.2345678;
|
||||
CHECK(doubles_equal(a, a, 0.000000001));
|
||||
}
|
||||
|
||||
TEST(UtestShell, FailWillIncreaseTheAmountOfChecks)
|
||||
{
|
||||
fixture.setTestFunction(_failMethod);
|
||||
fixture.runAllTests();
|
||||
LONGS_EQUAL(1, fixture.getCheckCount());
|
||||
}
|
||||
|
||||
TEST(UtestShell, PassedCheckEqualWillIncreaseTheAmountOfChecks)
|
||||
{
|
||||
fixture.setTestFunction(_passingCheckEqualTestMethod);
|
||||
fixture.runAllTests();
|
||||
LONGS_EQUAL(1, fixture.getCheckCount());
|
||||
}
|
||||
|
||||
IGNORE_TEST(UtestShell, IgnoreTestAccessingFixture)
|
||||
{
|
||||
CHECK(&fixture != NULLPTR);
|
||||
}
|
||||
|
||||
TEST(UtestShell, MacrosUsedInSetup)
|
||||
{
|
||||
IGNORE_ALL_LEAKS_IN_TEST();
|
||||
fixture.setSetup(_failMethod);
|
||||
fixture.setTestFunction(_passingTestMethod);
|
||||
fixture.runAllTests();
|
||||
LONGS_EQUAL(1, fixture.getFailureCount());
|
||||
}
|
||||
|
||||
TEST(UtestShell, MacrosUsedInTearDown)
|
||||
{
|
||||
IGNORE_ALL_LEAKS_IN_TEST();
|
||||
fixture.setTeardown(_failMethod);
|
||||
fixture.setTestFunction(_passingTestMethod);
|
||||
fixture.runAllTests();
|
||||
LONGS_EQUAL(1, fixture.getFailureCount());
|
||||
}
|
||||
|
||||
TEST(UtestShell, ExitLeavesQuietly)
|
||||
{
|
||||
fixture.setTestFunction(_exitTestMethod);
|
||||
fixture.runAllTests();
|
||||
LONGS_EQUAL(0, fixture.getFailureCount());
|
||||
}
|
||||
|
||||
static bool cpputestHasCrashed;
|
||||
|
||||
static void crashMethod()
|
||||
{
|
||||
cpputestHasCrashed = true;
|
||||
}
|
||||
|
||||
TEST(UtestShell, FailWillNotCrashIfNotEnabled)
|
||||
{
|
||||
cpputestHasCrashed = false;
|
||||
UtestShell::setCrashMethod(crashMethod);
|
||||
|
||||
fixture.setTestFunction(_failMethod);
|
||||
fixture.runAllTests();
|
||||
|
||||
CHECK_FALSE(cpputestHasCrashed);
|
||||
LONGS_EQUAL(1, fixture.getFailureCount());
|
||||
|
||||
UtestShell::resetCrashMethod();
|
||||
}
|
||||
|
||||
TEST(UtestShell, FailWillCrashIfEnabled)
|
||||
{
|
||||
cpputestHasCrashed = false;
|
||||
UtestShell::setCrashOnFail();
|
||||
UtestShell::setCrashMethod(crashMethod);
|
||||
|
||||
fixture.setTestFunction(_failMethod);
|
||||
fixture.runAllTests();
|
||||
|
||||
CHECK(cpputestHasCrashed);
|
||||
|
||||
UtestShell::restoreDefaultTestTerminator();
|
||||
UtestShell::resetCrashMethod();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int teardownCalled = 0;
|
||||
|
||||
static void _teardownMethod()
|
||||
{
|
||||
teardownCalled++;
|
||||
}
|
||||
|
||||
TEST(UtestShell, TeardownCalledAfterTestFailure)
|
||||
{
|
||||
teardownCalled = 0;
|
||||
IGNORE_ALL_LEAKS_IN_TEST();
|
||||
fixture.setTeardown(_teardownMethod);
|
||||
fixture.setTestFunction(_failMethod);
|
||||
fixture.runAllTests();
|
||||
LONGS_EQUAL(1, fixture.getFailureCount());
|
||||
LONGS_EQUAL(1, teardownCalled);
|
||||
}
|
||||
|
||||
static int stopAfterFailure = 0;
|
||||
static void _stopAfterFailureMethod()
|
||||
{
|
||||
FAIL("fail");
|
||||
stopAfterFailure++;
|
||||
}
|
||||
|
||||
TEST(UtestShell, TestStopsAfterTestFailure)
|
||||
{
|
||||
IGNORE_ALL_LEAKS_IN_TEST();
|
||||
stopAfterFailure = 0;
|
||||
fixture.setTestFunction(_stopAfterFailureMethod);
|
||||
fixture.runAllTests();
|
||||
CHECK(fixture.hasTestFailed());
|
||||
LONGS_EQUAL(1, fixture.getFailureCount());
|
||||
LONGS_EQUAL(0, stopAfterFailure);
|
||||
}
|
||||
|
||||
TEST(UtestShell, TestStopsAfterSetupFailure)
|
||||
{
|
||||
stopAfterFailure = 0;
|
||||
fixture.setSetup(_stopAfterFailureMethod);
|
||||
fixture.setTeardown(_stopAfterFailureMethod);
|
||||
fixture.setTestFunction(_failMethod);
|
||||
fixture.runAllTests();
|
||||
LONGS_EQUAL(2, fixture.getFailureCount());
|
||||
LONGS_EQUAL(0, stopAfterFailure);
|
||||
}
|
||||
|
||||
TEST(UtestShell, veryVebose)
|
||||
{
|
||||
UtestShell shell("Group", "name", __FILE__, __LINE__);
|
||||
StringBufferTestOutput normalOutput;
|
||||
normalOutput.verbose(TestOutput::level_veryVerbose);
|
||||
NullTestPlugin plugin;
|
||||
|
||||
TestResult result(normalOutput);
|
||||
shell.runOneTestInCurrentProcess(&plugin, result);
|
||||
STRCMP_CONTAINS("\n------ before runTest", normalOutput.getOutput().asCharString());
|
||||
}
|
||||
|
||||
class defaultUtestShell: public UtestShell
|
||||
{
|
||||
};
|
||||
|
||||
TEST(UtestShell, this_test_covers_the_UtestShell_createTest_and_Utest_testBody_methods)
|
||||
{
|
||||
defaultUtestShell shell;
|
||||
fixture.addTest(&shell);
|
||||
fixture.runAllTests();
|
||||
LONGS_EQUAL(2, fixture.getTestCount());
|
||||
}
|
||||
|
||||
|
||||
static void StubPlatformSpecificRunTestInASeperateProcess(UtestShell* shell, TestPlugin*, TestResult* result)
|
||||
{
|
||||
result->addFailure(TestFailure(shell, "Failed in separate process"));
|
||||
}
|
||||
|
||||
TEST(UtestShell, RunInSeparateProcessTest)
|
||||
{
|
||||
UT_PTR_SET(PlatformSpecificRunTestInASeperateProcess, StubPlatformSpecificRunTestInASeperateProcess);
|
||||
fixture.getRegistry()->setRunTestsInSeperateProcess();
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("Failed in separate process");
|
||||
}
|
||||
|
||||
#ifndef CPPUTEST_HAVE_FORK
|
||||
|
||||
IGNORE_TEST(UtestShell, TestDefaultCrashMethodInSeparateProcessTest) {}
|
||||
|
||||
#else
|
||||
|
||||
#if !CPPUTEST_SANITIZE_ADDRESS
|
||||
|
||||
TEST(UtestShell, TestDefaultCrashMethodInSeparateProcessTest)
|
||||
{
|
||||
fixture.setTestFunction(UtestShell::crash);
|
||||
fixture.setRunTestsInSeperateProcess();
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("Failed in separate process - killed by signal");
|
||||
|
||||
/* Signal 11 usually happens, but with clang3.7 on Linux, it produced signal 4 */
|
||||
CHECK(fixture.getOutput().contains("signal 11") || fixture.getOutput().contains("signal 4"));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if CPPUTEST_USE_STD_CPP_LIB
|
||||
|
||||
static bool destructorWasCalledOnFailedTest = false;
|
||||
|
||||
static void _destructorCalledForLocalObjects()
|
||||
{
|
||||
SetBooleanOnDestructorCall pleaseCallTheDestructor(destructorWasCalledOnFailedTest);
|
||||
destructorWasCalledOnFailedTest = false;
|
||||
FAIL("fail");
|
||||
}
|
||||
|
||||
TEST(UtestShell, DestructorIsCalledForLocalObjectsWhenTheTestFails)
|
||||
{
|
||||
fixture.setTestFunction(_destructorCalledForLocalObjects);
|
||||
fixture.runAllTests();
|
||||
CHECK(destructorWasCalledOnFailedTest);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST_GROUP(IgnoredUtestShell)
|
||||
{
|
||||
TestTestingFixture fixture;
|
||||
IgnoredUtestShell ignoredTest;
|
||||
ExecFunctionTestShell normalUtestShell;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
fixture.addTest(&ignoredTest);
|
||||
fixture.addTest(&normalUtestShell);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(IgnoredUtestShell, doesIgnoreCount)
|
||||
{
|
||||
fixture.runAllTests();
|
||||
LONGS_EQUAL(1, fixture.getIgnoreCount());
|
||||
}
|
||||
|
||||
TEST(IgnoredUtestShell, printsIGNORE_TESTwhenVerbose)
|
||||
{
|
||||
fixture.setOutputVerbose();
|
||||
fixture.runAllTests();
|
||||
fixture.assertPrintContains("IGNORE_TEST");
|
||||
}
|
||||
|
||||
TEST(IgnoredUtestShell, runIgnoredOptionSpecifiedThenIncreaseRunCount)
|
||||
{
|
||||
ignoredTest.setRunIgnored();
|
||||
fixture.runAllTests();
|
||||
LONGS_EQUAL(3, fixture.getRunCount());
|
||||
LONGS_EQUAL(0, fixture.getIgnoreCount());
|
||||
}
|
||||
|
||||
TEST(IgnoredUtestShell, runIgnoredOptionNotSpecifiedThenIncreaseIgnoredCount)
|
||||
{
|
||||
fixture.runAllTests();
|
||||
LONGS_EQUAL(2, fixture.getRunCount());
|
||||
LONGS_EQUAL(1, fixture.getIgnoreCount());
|
||||
}
|
||||
|
||||
TEST(IgnoredUtestShell, runIgnoredOptionSpecifiedWillNotInfluenceNormalTestCount)
|
||||
{
|
||||
normalUtestShell.setRunIgnored();
|
||||
fixture.runAllTests();
|
||||
LONGS_EQUAL(2, fixture.getRunCount());
|
||||
LONGS_EQUAL(1, fixture.getIgnoreCount());
|
||||
}
|
||||
|
||||
TEST(IgnoredUtestShell, runIgnoredOptionSpecifiedThenReturnTESTInFormattedName)
|
||||
{
|
||||
ignoredTest.setGroupName("TestGroup");
|
||||
ignoredTest.setTestName("TestName");
|
||||
ignoredTest.setRunIgnored();
|
||||
fixture.runAllTests();
|
||||
STRCMP_EQUAL("TEST(TestGroup, TestName)", ignoredTest.getFormattedName().asCharString());
|
||||
}
|
||||
|
||||
TEST(IgnoredUtestShell, runIgnoredOptionNotSpecifiedThenReturnIGNORETESTInFormattedName)
|
||||
{
|
||||
ignoredTest.setGroupName("TestGroup");
|
||||
ignoredTest.setTestName("TestName");
|
||||
fixture.runAllTests();
|
||||
STRCMP_EQUAL("IGNORE_TEST(TestGroup, TestName)", ignoredTest.getFormattedName().asCharString());
|
||||
}
|
||||
|
||||
TEST(IgnoredUtestShell, runIgnoredOptionNotSpecifiedThenWillRunReturnFalse)
|
||||
{
|
||||
CHECK_FALSE(ignoredTest.willRun());
|
||||
}
|
||||
|
||||
TEST(IgnoredUtestShell, runIgnoredOptionSpecifiedThenWillRunReturnTrue)
|
||||
{
|
||||
ignoredTest.setRunIgnored();
|
||||
CHECK_TRUE(ignoredTest.willRun());
|
||||
}
|
||||
|
||||
TEST_BASE(MyOwnTest)
|
||||
{
|
||||
MyOwnTest() :
|
||||
inTest(false)
|
||||
{
|
||||
}
|
||||
bool inTest;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
CHECK(!inTest);
|
||||
inTest = true;
|
||||
}
|
||||
void teardown() _override
|
||||
{
|
||||
CHECK(inTest);
|
||||
inTest = false;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_GROUP_BASE(UtestMyOwn, MyOwnTest)
|
||||
{
|
||||
};
|
||||
|
||||
TEST(UtestMyOwn, test)
|
||||
{
|
||||
CHECK(inTest);
|
||||
}
|
||||
|
||||
class NullParameterTest: public UtestShell
|
||||
{
|
||||
};
|
||||
|
||||
TEST(UtestMyOwn, NullParameters)
|
||||
{
|
||||
NullParameterTest nullTest; /* Bug fix tests for creating a test without a name, fix in SimpleString */
|
||||
TestFilter emptyFilter;
|
||||
CHECK(nullTest.shouldRun(&emptyFilter, &emptyFilter));
|
||||
}
|
||||
|
||||
class AllocateAndDeallocateInConstructorAndDestructor
|
||||
{
|
||||
char* memory_;
|
||||
char* morememory_;
|
||||
public:
|
||||
AllocateAndDeallocateInConstructorAndDestructor()
|
||||
{
|
||||
memory_ = new char[100];
|
||||
morememory_ = NULLPTR;
|
||||
}
|
||||
void allocateMoreMemory()
|
||||
{
|
||||
morememory_ = new char[123];
|
||||
}
|
||||
|
||||
~AllocateAndDeallocateInConstructorAndDestructor()
|
||||
{
|
||||
delete [] memory_;
|
||||
delete [] morememory_;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_GROUP(CanHaveMemberVariablesInTestGroupThatAllocateMemoryWithoutCausingMemoryLeaks)
|
||||
{
|
||||
AllocateAndDeallocateInConstructorAndDestructor dummy;
|
||||
};
|
||||
|
||||
TEST(CanHaveMemberVariablesInTestGroupThatAllocateMemoryWithoutCausingMemoryLeaks, testInTestGroupName)
|
||||
{
|
||||
dummy.allocateMoreMemory();
|
||||
}
|
||||
|
||||
static int getZero()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getOne()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TEST_GROUP(UtestShellPointerArrayTest)
|
||||
{
|
||||
UtestShell* test0;
|
||||
UtestShell* test1;
|
||||
UtestShell* test2;
|
||||
|
||||
void setup() _override
|
||||
{
|
||||
test0 = new IgnoredUtestShell();
|
||||
test1 = new IgnoredUtestShell();
|
||||
test2 = new IgnoredUtestShell();
|
||||
|
||||
test0->addTest(test1);
|
||||
test1->addTest(test2);
|
||||
}
|
||||
|
||||
void teardown() _override
|
||||
{
|
||||
delete test0;
|
||||
delete test1;
|
||||
delete test2;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST(UtestShellPointerArrayTest, empty)
|
||||
{
|
||||
UtestShellPointerArray tests(NULLPTR);
|
||||
tests.shuffle(0);
|
||||
CHECK(NULLPTR == tests.getFirstTest());
|
||||
}
|
||||
|
||||
TEST(UtestShellPointerArrayTest, testsAreInOrder)
|
||||
{
|
||||
UtestShellPointerArray tests(test0);
|
||||
CHECK(tests.get(0) == test0);
|
||||
CHECK(tests.get(1) == test1);
|
||||
CHECK(tests.get(2) == test2);
|
||||
}
|
||||
|
||||
TEST(UtestShellPointerArrayTest, relinkingTestsWillKeepThemTheSameWhenNothingWasDone)
|
||||
{
|
||||
UtestShellPointerArray tests(test0);
|
||||
tests.relinkTestsInOrder();
|
||||
CHECK(tests.get(0) == test0);
|
||||
CHECK(tests.get(1) == test1);
|
||||
CHECK(tests.get(2) == test2);
|
||||
}
|
||||
|
||||
|
||||
TEST(UtestShellPointerArrayTest, firstTestisNotTheFirstTestWithSeed1234)
|
||||
{
|
||||
UtestShellPointerArray tests(test0);
|
||||
tests.shuffle(1234);
|
||||
CHECK(tests.getFirstTest() != test0);
|
||||
}
|
||||
|
||||
TEST(UtestShellPointerArrayTest, ShuffleListTestWithRandomAlwaysReturningZero)
|
||||
{
|
||||
UT_PTR_SET(PlatformSpecificRand, getZero);
|
||||
|
||||
UtestShellPointerArray tests(test0);
|
||||
tests.shuffle(3);
|
||||
CHECK(tests.get(0) == test1);
|
||||
CHECK(tests.get(1) == test2);
|
||||
CHECK(tests.get(2) == test0);
|
||||
}
|
||||
|
||||
// swaps with 4 mod 3 (1) then 4 mod 2 (0): 1, [2], [0] --> [1], [0], 2 --> 0, 1, 2
|
||||
TEST(UtestShellPointerArrayTest, ShuffleListTestWithRandomAlwaysReturningOne)
|
||||
{
|
||||
UT_PTR_SET(PlatformSpecificRand, getOne);
|
||||
|
||||
UtestShellPointerArray tests(test0);
|
||||
tests.shuffle(3);
|
||||
CHECK(tests.get(0) == test0);
|
||||
CHECK(tests.get(1) == test2);
|
||||
CHECK(tests.get(2) == test1);
|
||||
}
|
||||
|
||||
TEST(UtestShellPointerArrayTest, reverse)
|
||||
{
|
||||
UT_PTR_SET(PlatformSpecificRand, getOne);
|
||||
|
||||
UtestShellPointerArray tests(test0);
|
||||
tests.reverse();
|
||||
CHECK(tests.get(0) == test2);
|
||||
CHECK(tests.get(1) == test1);
|
||||
CHECK(tests.get(2) == test0);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue