Skip to content

Commit

Permalink
Merge 08a452e into d289eaf
Browse files Browse the repository at this point in the history
  • Loading branch information
basvodde committed May 8, 2020
2 parents d289eaf + 08a452e commit c6917b0
Show file tree
Hide file tree
Showing 21 changed files with 297 additions and 59 deletions.
15 changes: 15 additions & 0 deletions include/CppUTest/SimpleString.h
Expand Up @@ -199,6 +199,7 @@ class SimpleStringInternalCache
void clearCache();
void clearAllIncludingCurrentlyUsedMemory();
private:
void printDeallocatingUnknownMemory(char* memory);

enum { amountOfInternalCacheNodes = 5};
bool isCached(size_t size);
Expand All @@ -221,6 +222,20 @@ class SimpleStringInternalCache
TestMemoryAllocator* allocator_;
SimpleStringInternalCacheNode* cache_;
SimpleStringMemoryBlock* nonCachedAllocations_;
bool hasWarnedAboutDeallocations;
};

class SimpleStringCacheAllocator;
class GlobalSimpleStringCache
{
SimpleStringCacheAllocator* allocator_;
SimpleStringInternalCache cache_;

public:
GlobalSimpleStringCache();
~GlobalSimpleStringCache();

TestMemoryAllocator* getAllocator();
};

SimpleString StringFrom(bool value);
Expand Down
2 changes: 2 additions & 0 deletions include/CppUTest/TestMemoryAllocator.h
Expand Up @@ -161,6 +161,7 @@ class MemoryAccountant
{
public:
MemoryAccountant();
~MemoryAccountant();

void useCacheSizes(size_t sizes[], size_t length);

Expand Down Expand Up @@ -272,6 +273,7 @@ class SimpleStringCacheAllocator : public TestMemoryAllocator
virtual const char* free_name() const _override;

virtual TestMemoryAllocator* actualAllocator() _override;
TestMemoryAllocator* originalAllocator();
private:
SimpleStringInternalCache& cache_;
TestMemoryAllocator* originalAllocator_;
Expand Down
3 changes: 3 additions & 0 deletions include/CppUTestExt/MockCheckedActualCall.h
Expand Up @@ -221,10 +221,13 @@ class MockActualCallTrace : public MockActualCall
const char* getTraceOutput();
void clear();
static MockActualCallTrace& instance();
static void clearInstance();

private:
SimpleString traceBuffer_;

static MockActualCallTrace* instance_;

void addParameterName(const SimpleString& name);
};

Expand Down
3 changes: 2 additions & 1 deletion src/CppUTest/MemoryLeakDetector.cpp
Expand Up @@ -681,8 +681,9 @@ void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* mem
allocatNodesSeperately = true;
#endif
if (!allocator->hasBeenDestroyed()) {
size_t size = node->size_;
checkForCorruption(node, file, line, allocator, allocatNodesSeperately);
allocator->free_memory((char*) memory, node->size_, file, line);
allocator->free_memory((char*) memory, size, file, line);
}
}

Expand Down
41 changes: 39 additions & 2 deletions src/CppUTest/SimpleString.cpp
Expand Up @@ -74,7 +74,7 @@ void GlobalSimpleStringMemoryAccountant::useCacheSizes(size_t cacheSizes[], size
void GlobalSimpleStringMemoryAccountant::start()
{
if (allocator_ != NULLPTR)
FAIL("Global SimpleString allocator start called twice!");
return;

allocator_ = new AccountingTestMemoryAllocator(*accountant_, SimpleString::getStringAllocator());

Expand Down Expand Up @@ -116,7 +116,7 @@ struct SimpleStringInternalCacheNode
};

SimpleStringInternalCache::SimpleStringInternalCache()
: allocator_(defaultMallocAllocator()), cache_(NULLPTR), nonCachedAllocations_(NULLPTR)
: allocator_(defaultMallocAllocator()), cache_(NULLPTR), nonCachedAllocations_(NULLPTR), hasWarnedAboutDeallocations(false)
{
cache_ = createInternalCacheNodes();
}
Expand Down Expand Up @@ -222,6 +222,17 @@ SimpleStringMemoryBlock* SimpleStringInternalCache::allocateNewCacheBlockFrom(Si
return block;
}

void SimpleStringInternalCache::printDeallocatingUnknownMemory(char* memory)
{
if (!hasWarnedAboutDeallocations) {
hasWarnedAboutDeallocations = true;
UtestShell::getCurrent()->print(StringFromFormat("\nWARNING: Attempting to deallocate a String buffer that was allocated while not caching. Ignoring it!\n"
"This is likely due statics and will cause problems.\n"
"Only warning once to avoid recursive warnings.\n"
"String we are deallocating: \"%s\"\n", memory).asCharString(), __FILE__, __LINE__);
}
}

void SimpleStringInternalCache::releaseCachedBlockFrom(char* memory, SimpleStringInternalCacheNode* node)
{
if (node->usedMemoryHead_ && node->usedMemoryHead_->memory_ == memory) {
Expand All @@ -236,8 +247,11 @@ void SimpleStringInternalCache::releaseCachedBlockFrom(char* memory, SimpleStrin
SimpleStringMemoryBlock* blockToFree = block->next_;
block->next_ = block->next_->next_;
node->freeMemoryHead_ = addToSimpleStringMemoryBlockList(blockToFree, node->freeMemoryHead_);
return;
}
}
printDeallocatingUnknownMemory(memory);

}

void SimpleStringInternalCache::releaseNonCachedMemory(char* memory, size_t size)
Expand All @@ -254,8 +268,11 @@ void SimpleStringInternalCache::releaseNonCachedMemory(char* memory, size_t size
SimpleStringMemoryBlock* blockToFree = block->next_;
block->next_ = block->next_->next_;
destroySimpleStringMemoryBlock(blockToFree, size);
return;
}
}

printDeallocatingUnknownMemory(memory);
}

char* SimpleStringInternalCache::alloc(size_t size)
Expand Down Expand Up @@ -298,10 +315,29 @@ void SimpleStringInternalCache::clearAllIncludingCurrentlyUsedMemory()
cache_[i].freeMemoryHead_ = NULLPTR;
cache_[i].usedMemoryHead_ = NULLPTR;
}

destroySimpleStringMemoryBlockList(nonCachedAllocations_, 0);
nonCachedAllocations_ = NULLPTR;
}

GlobalSimpleStringCache::GlobalSimpleStringCache()
{
allocator_ = new SimpleStringCacheAllocator(cache_, SimpleString::getStringAllocator());
SimpleString::setStringAllocator(allocator_);
}

GlobalSimpleStringCache::~GlobalSimpleStringCache()
{
SimpleString::setStringAllocator(allocator_->originalAllocator());
cache_.clearAllIncludingCurrentlyUsedMemory();
delete allocator_;
}

TestMemoryAllocator* GlobalSimpleStringCache::getAllocator()
{
return allocator_;
}

TestMemoryAllocator* SimpleString::stringAllocator_ = NULLPTR;

TestMemoryAllocator* SimpleString::getStringAllocator()
Expand Down Expand Up @@ -461,6 +497,7 @@ void SimpleString::setInternalBufferToNewBuffer(size_t size)

bufferSize_ = size;
buffer_ = allocStringBuffer(bufferSize_, __FILE__, __LINE__);
buffer_[0] = '\0';
}

void SimpleString::setInternalBufferTo(char* buffer, size_t size)
Expand Down
11 changes: 11 additions & 0 deletions src/CppUTest/TestMemoryAllocator.cpp
Expand Up @@ -426,6 +426,11 @@ MemoryAccountant::MemoryAccountant()
{
}

MemoryAccountant::~MemoryAccountant()
{
clear();
}

void MemoryAccountant::createCacheSizeNodes(size_t sizes[], size_t length)
{
for (size_t i = 0; i < length; i++)
Expand Down Expand Up @@ -467,6 +472,7 @@ void MemoryAccountant::clear()
node = node->next_;
destroyAccountantAllocationNode(to_be_deleted);
}
head_ = NULLPTR;
}

MemoryAccountantAllocationNode* MemoryAccountant::findNodeOfSize(size_t size) const
Expand Down Expand Up @@ -825,3 +831,8 @@ TestMemoryAllocator* SimpleStringCacheAllocator::actualAllocator()
return originalAllocator_->actualAllocator();
}

TestMemoryAllocator* SimpleStringCacheAllocator::originalAllocator()
{
return originalAllocator_;
}

13 changes: 11 additions & 2 deletions src/CppUTestExt/MockActualCall.cpp
Expand Up @@ -1003,10 +1003,19 @@ const char* MockActualCallTrace::getTraceOutput()
return traceBuffer_.asCharString();
}

MockActualCallTrace* MockActualCallTrace::instance_ = NULLPTR;

MockActualCallTrace& MockActualCallTrace::instance()
{
static MockActualCallTrace call;
return call;
if (instance_ == NULLPTR)
instance_ = new MockActualCallTrace;
return *instance_;
}

void MockActualCallTrace::clearInstance()
{
delete instance_;
instance_ = NULLPTR;
}

MockIgnoredActualCall& MockIgnoredActualCall::instance()
Expand Down
2 changes: 1 addition & 1 deletion src/CppUTestExt/MockSupport.cpp
Expand Up @@ -116,7 +116,7 @@ void MockSupport::clear()
lastActualFunctionCall_ = NULLPTR;

tracing_ = false;
MockActualCallTrace::instance().clear();
MockActualCallTrace::clearInstance();

expectations_.deleteAllExpectationsAndClearList();
ignoreOtherCalls_ = false;
Expand Down
21 changes: 13 additions & 8 deletions tests/CppUTest/AllTests.cpp
Expand Up @@ -32,21 +32,26 @@

int main(int ac, char **av)
{
/* These checks are here to make sure assertions outside test runs don't crash */
CHECK(true);
LONGS_EQUAL(1, 1);
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();
GlobalMemoryAccountant accountant;
accountant.start();
#endif

int returnValue = CommandLineTestRunner::RunAllTests(ac, av); /* cover alternate method */
CommandLineTestRunner::RunAllTests(ac, av); /* cover alternate method */

#if SHOW_MEMORY_REPORT
accountant.stop();
printf("%s", accountant.report().asCharString());
accountant.stop();
printf("%s", accountant.report().asCharString());
#endif
}

return returnValue;
}
Expand Down
54 changes: 37 additions & 17 deletions tests/CppUTest/CommandLineTestRunnerTest.cpp
Expand Up @@ -300,77 +300,97 @@ 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;
}
~FakeOutput()

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)
{
file += str;
currentFake->file += str;
}

static void fclose_fake(PlatformSpecificFile)
{
}

static int putchar_fake(int c)
{
console += StringFrom((char)c);
currentFake->console += StringFrom((char)c);
return c;
}
static SimpleString file;
static SimpleString console;

SimpleString file;
SimpleString console;

static FakeOutput* currentFake;
private:
FOpenFunc SaveFOpen;
FPutsFunc SaveFPuts;
FCloseFunc SaveFClose;
PutcharFunc SavePutchar;
};

SimpleString FakeOutput::console = "";
SimpleString FakeOutput::file = "";
FakeOutput* FakeOutput::currentFake = NULLPTR;

TEST(CommandLineTestRunner, realJunitOutputShouldBeCreatedAndWorkProperly)
{
const char* argv[] = { "tests.exe", "-ojunit", "-v", "-kpackage", };

FakeOutput* fakeOutput = new FakeOutput; /* UT_PTR_SET() is not reentrant */
FakeOutput fakeOutput; /* UT_PTR_SET() is not reentrant */

CommandLineTestRunner commandLineTestRunner(4, argv, &registry);
commandLineTestRunner.runAllTestsMain();

delete fakeOutput; /* Original output must be restored before further output occurs */
fakeOutput.restoreOriginals();

STRCMP_CONTAINS("<testcase classname=\"package.group1\" name=\"test1\"", fakeOutput.file.asCharString());
STRCMP_CONTAINS("TEST(group1, test1)", fakeOutput.console.asCharString());

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 = new FakeOutput; /* UT_PTR_SET() is not reentrant */
FakeOutput fakeOutput; /* UT_PTR_SET() is not reentrant */

CommandLineTestRunner commandLineTestRunner(4, argv, &registry);
commandLineTestRunner.runAllTestsMain();

delete fakeOutput; /* Original output must be restored before further output occurs */
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());
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());
}


Expand Down

0 comments on commit c6917b0

Please sign in to comment.