Use template for UnitTest

This commit is contained in:
Vinnie Falco
2013-07-13 04:48:53 -07:00
parent d684d7742c
commit a937c379f6
15 changed files with 167 additions and 141 deletions

View File

@@ -194,6 +194,9 @@ namespace beast
// Order matters, since headers don't have their own #include lines. // Order matters, since headers don't have their own #include lines.
// Add new includes to the bottom. // Add new includes to the bottom.
#include "system/beast_PlatformDefs.h"
#include "system/beast_TargetPlatform.h"
#include "memory/beast_Uncopyable.h" #include "memory/beast_Uncopyable.h"
#include "maths/beast_MathsFunctions.h" #include "maths/beast_MathsFunctions.h"
#include "memory/beast_Atomic.h" #include "memory/beast_Atomic.h"
@@ -204,6 +207,14 @@ namespace beast
#include "containers/beast_LockFreeStack.h" #include "containers/beast_LockFreeStack.h"
#include "threads/beast_SpinDelay.h" #include "threads/beast_SpinDelay.h"
#include "memory/beast_StaticObject.h" #include "memory/beast_StaticObject.h"
#include "text/beast_String.h"
#include "text/beast_CharacterFunctions.h"
#include "text/beast_CharPointer_ASCII.h"
#include "text/beast_CharPointer_UTF16.h"
#include "text/beast_CharPointer_UTF32.h"
#include "text/beast_CharPointer_UTF8.h"
#include "time/beast_PerformedAtExit.h" #include "time/beast_PerformedAtExit.h"
#include "diagnostic/beast_LeakChecked.h" #include "diagnostic/beast_LeakChecked.h"
#include "memory/beast_Memory.h" #include "memory/beast_Memory.h"
@@ -280,19 +291,10 @@ namespace beast
#include "streams/beast_OutputStream.h" #include "streams/beast_OutputStream.h"
#include "streams/beast_SubregionStream.h" #include "streams/beast_SubregionStream.h"
#include "system/beast_Functional.h" #include "system/beast_Functional.h"
#include "system/beast_PlatformDefs.h"
#include "system/beast_StandardHeader.h"
#include "system/beast_SystemStats.h" #include "system/beast_SystemStats.h"
#include "system/beast_TargetPlatform.h"
#include "text/beast_CharacterFunctions.h"
#include "text/beast_CharPointer_ASCII.h"
#include "text/beast_CharPointer_UTF16.h"
#include "text/beast_CharPointer_UTF32.h"
#include "text/beast_CharPointer_UTF8.h"
#include "text/beast_Identifier.h" #include "text/beast_Identifier.h"
#include "text/beast_LocalisedStrings.h" #include "text/beast_LocalisedStrings.h"
#include "text/beast_NewLine.h" #include "text/beast_NewLine.h"
#include "text/beast_String.h"
#include "text/beast_StringArray.h" #include "text/beast_StringArray.h"
#include "text/beast_StringPairArray.h" #include "text/beast_StringPairArray.h"
#include "text/beast_StringPool.h" #include "text/beast_StringPool.h"

View File

@@ -125,13 +125,13 @@ void AbstractFifo::finishedRead (int numRead) noexcept
} }
//============================================================================== //==============================================================================
//==============================================================================
#if BEAST_UNIT_TESTS
class AbstractFifoTests : public UnitTest class AbstractFifoTests : public UnitTestType <AbstractFifoTests>
{ {
public: public:
AbstractFifoTests() : UnitTest ("Abstract Fifo") {} AbstractFifoTests() : UnitTestType <AbstractFifoTests> ("Abstract Fifo")
{
}
class WriteThread : public Thread class WriteThread : public Thread
{ {
@@ -201,7 +201,7 @@ public:
&& (size1 == 0 || (start1 >= 0 && start1 < fifo.getTotalSize())) && (size1 == 0 || (start1 >= 0 && start1 < fifo.getTotalSize()))
&& (size2 == 0 || (start2 >= 0 && start2 < fifo.getTotalSize()))) && (size2 == 0 || (start2 >= 0 && start2 < fifo.getTotalSize())))
{ {
expect (false, "prepareToRead returned -ve values"); expect (false, "prepareToRead returned negative values");
break; break;
} }
@@ -224,6 +224,6 @@ public:
} }
}; };
static AbstractFifoTests fifoUnitTests; #if BEAST_UNIT_TESTS
template class UnitTestType <AbstractFifoTests>;
#endif #endif

View File

@@ -41,7 +41,7 @@ Array<UnitTest*>& UnitTest::getAllTests()
void UnitTest::initialise() {} void UnitTest::initialise() {}
void UnitTest::shutdown() {} void UnitTest::shutdown() {}
void UnitTest::performTest (UnitTestRunner* const runner_) void UnitTest::performTest (UnitTests* const runner_)
{ {
bassert (runner_ != nullptr); bassert (runner_ != nullptr);
runner = runner_; runner = runner_;
@@ -70,42 +70,42 @@ void UnitTest::expect (const bool result, const String& failureMessage)
} }
//============================================================================== //==============================================================================
UnitTestRunner::UnitTestRunner() UnitTests::UnitTests()
: currentTest (nullptr), : currentTest (nullptr),
assertOnFailure (true), assertOnFailure (true),
logPasses (false) logPasses (false)
{ {
} }
UnitTestRunner::~UnitTestRunner() UnitTests::~UnitTests()
{ {
} }
void UnitTestRunner::setAssertOnFailure (bool shouldAssert) noexcept void UnitTests::setAssertOnFailure (bool shouldAssert) noexcept
{ {
assertOnFailure = shouldAssert; assertOnFailure = shouldAssert;
} }
void UnitTestRunner::setPassesAreLogged (bool shouldDisplayPasses) noexcept void UnitTests::setPassesAreLogged (bool shouldDisplayPasses) noexcept
{ {
logPasses = shouldDisplayPasses; logPasses = shouldDisplayPasses;
} }
int UnitTestRunner::getNumResults() const noexcept int UnitTests::getNumResults() const noexcept
{ {
return results.size(); return results.size();
} }
const UnitTestRunner::TestResult* UnitTestRunner::getResult (int index) const noexcept const UnitTests::TestResult* UnitTests::getResult (int index) const noexcept
{ {
return results [index]; return results [index];
} }
void UnitTestRunner::resultsUpdated() void UnitTests::resultsUpdated()
{ {
} }
void UnitTestRunner::runTests (const Array<UnitTest*>& tests) void UnitTests::runTests (const Array<UnitTest*>& tests)
{ {
results.clear(); results.clear();
resultsUpdated(); resultsUpdated();
@@ -128,22 +128,22 @@ void UnitTestRunner::runTests (const Array<UnitTest*>& tests)
endTest(); endTest();
} }
void UnitTestRunner::runAllTests() void UnitTests::runAllTests()
{ {
runTests (UnitTest::getAllTests()); runTests (UnitTest::getAllTests());
} }
void UnitTestRunner::logMessage (const String& message) void UnitTests::logMessage (const String& message)
{ {
Logger::writeToLog (message); Logger::writeToLog (message);
} }
bool UnitTestRunner::shouldAbortTests() bool UnitTests::shouldAbortTests()
{ {
return false; return false;
} }
void UnitTestRunner::beginNewTest (UnitTest* const test, const String& subCategory) void UnitTests::beginNewTest (UnitTest* const test, const String& subCategory)
{ {
endTest(); endTest();
currentTest = test; currentTest = test;
@@ -160,7 +160,7 @@ void UnitTestRunner::beginNewTest (UnitTest* const test, const String& subCatego
resultsUpdated(); resultsUpdated();
} }
void UnitTestRunner::endTest() void UnitTests::endTest()
{ {
if (results.size() > 0) if (results.size() > 0)
{ {
@@ -183,7 +183,7 @@ void UnitTestRunner::endTest()
} }
} }
void UnitTestRunner::addPass() void UnitTests::addPass()
{ {
{ {
const ScopedLock sl (results.getLock()); const ScopedLock sl (results.getLock());
@@ -204,7 +204,7 @@ void UnitTestRunner::addPass()
resultsUpdated(); resultsUpdated();
} }
void UnitTestRunner::addFail (const String& failureMessage) void UnitTests::addFail (const String& failureMessage)
{ {
{ {
const ScopedLock sl (results.getLock()); const ScopedLock sl (results.getLock());

View File

@@ -26,46 +26,9 @@
#include "../text/beast_StringArray.h" #include "../text/beast_StringArray.h"
#include "../containers/beast_OwnedArray.h" #include "../containers/beast_OwnedArray.h"
class UnitTestRunner; class UnitTests;
/** Factored base class for unit test template.
//==============================================================================
/**
This is a base class for classes that perform a unit test.
To write a test using this class, your code should look something like this:
@code
class MyTest : public UnitTest
{
public:
MyTest() : UnitTest ("Foobar testing") {}
void runTest()
{
beginTest ("Part 1");
expect (myFoobar.doesSomething());
expect (myFoobar.doesSomethingElse());
beginTest ("Part 2");
expect (myOtherFoobar.doesSomething());
expect (myOtherFoobar.doesSomethingElse());
...etc..
}
};
// Creating a static instance will automatically add the instance to the array
// returned by UnitTest::getAllTests(), so the test will be included when you call
// UnitTestRunner::runAllTests()
static MyTest test;
@endcode
To run a test, use the UnitTestRunner class.
@see UnitTestRunner
*/ */
class BEAST_API UnitTest : Uncopyable class BEAST_API UnitTest : Uncopyable
{ {
@@ -80,11 +43,11 @@ public:
/** Returns the name of the test. */ /** Returns the name of the test. */
const String& getName() const noexcept { return name; } const String& getName() const noexcept { return name; }
/** Runs the test, using the specified UnitTestRunner. /** Runs the test, using the specified UnitTests.
You shouldn't need to call this method directly - use You shouldn't need to call this method directly - use
UnitTestRunner::runTests() instead. UnitTests::runTests() instead.
*/ */
void performTest (UnitTestRunner* runner); void performTest (UnitTests* runner);
/** Returns the set of all UnitTest objects that currently exist. */ /** Returns the set of all UnitTest objects that currently exist. */
static Array<UnitTest*>& getAllTests(); static Array<UnitTest*>& getAllTests();
@@ -163,10 +126,9 @@ public:
private: private:
//============================================================================== //==============================================================================
const String name; const String name;
UnitTestRunner* runner; UnitTests* runner;
}; };
//============================================================================== //==============================================================================
/** /**
Runs a set of unit tests. Runs a set of unit tests.
@@ -174,20 +136,20 @@ private:
You can instantiate one of these objects and use it to invoke tests on a set of You can instantiate one of these objects and use it to invoke tests on a set of
UnitTest objects. UnitTest objects.
By using a subclass of UnitTestRunner, you can intercept logging messages and By using a subclass of UnitTests, you can intercept logging messages and
perform custom behaviour when each test completes. perform custom behaviour when each test completes.
@see UnitTest @see UnitTest
*/ */
class BEAST_API UnitTestRunner : Uncopyable class BEAST_API UnitTests : Uncopyable
{ {
public: public:
//============================================================================== //==============================================================================
/** */ /** */
UnitTestRunner(); UnitTests();
/** Destructor. */ /** Destructor. */
virtual ~UnitTestRunner(); virtual ~UnitTests();
/** Runs a set of tests. /** Runs a set of tests.
@@ -199,7 +161,7 @@ public:
/** Runs all the UnitTest objects that currently exist. /** Runs all the UnitTest objects that currently exist.
This calls runTests() for all the objects listed in UnitTest::getAllTests(). This calls runTests() for all the objects listed in UnitTest::getAllTests().
*/ */
void runAllTests(); void runAllTests ();
/** Sets a flag to indicate whether an assertion should be triggered if a test fails. /** Sets a flag to indicate whether an assertion should be triggered if a test fails.
This is true by default. This is true by default.
@@ -222,11 +184,13 @@ public:
{ {
/** The main name of this test (i.e. the name of the UnitTest object being run). */ /** The main name of this test (i.e. the name of the UnitTest object being run). */
String unitTestName; String unitTestName;
/** The name of the current subcategory (i.e. the name that was set when UnitTest::beginTest() was called). */ /** The name of the current subcategory (i.e. the name that was set when UnitTest::beginTest() was called). */
String subcategoryName; String subcategoryName;
/** The number of UnitTest::expect() calls that succeeded. */ /** The number of UnitTest::expect() calls that succeeded. */
int passes; int passes;
/** The number of UnitTest::expect() calls that failed. */ /** The number of UnitTest::expect() calls that failed. */
int failures; int failures;
@@ -248,34 +212,87 @@ protected:
/** Called when the list of results changes. /** Called when the list of results changes.
You can override this to perform some sort of behaviour when results are added. You can override this to perform some sort of behaviour when results are added.
*/ */
virtual void resultsUpdated(); virtual void resultsUpdated ();
/** Logs a message about the current test progress. /** Logs a message about the current test progress.
By default this just writes the message to the Logger class, but you could override By default this just writes the message to the Logger class, but you could override
this to do something else with the data. this to do something else with the data.
*/ */
virtual void logMessage (const String& message); virtual void logMessage (String const& message);
/** This can be overridden to let the runner know that it should abort the tests /** This can be overridden to let the runner know that it should abort the tests
as soon as possible, e.g. because the thread needs to stop. as soon as possible, e.g. because the thread needs to stop.
*/ */
virtual bool shouldAbortTests(); virtual bool shouldAbortTests ();
private: private:
//==============================================================================
friend class UnitTest; friend class UnitTest;
UnitTest* currentTest;
String currentSubCategory;
OwnedArray <TestResult, CriticalSection> results;
bool assertOnFailure, logPasses;
void beginNewTest (UnitTest* test, const String& subCategory); void beginNewTest (UnitTest* test, const String& subCategory);
void endTest(); void endTest();
void addPass(); void addPass();
void addFail (const String& failureMessage); void addFail (const String& failureMessage);
UnitTest* currentTest;
String currentSubCategory;
OwnedArray <TestResult, CriticalSection> results;
bool assertOnFailure;
bool logPasses;
}; };
//------------------------------------------------------------------------------
#endif // BEAST_UNITTEST_BEASTHEADER /** This is a base class for classes that perform a unit test.
To write a test using this class, your code should look something like this:
@code
class MyTest : public UnitTestType <MyTest>
{
public:
MyTest() : UnitTestType <MyTest> ("Foobar testing") { }
void runTest()
{
beginTest ("Part 1");
expect (myFoobar.doesSomething());
expect (myFoobar.doesSomethingElse());
beginTest ("Part 2");
expect (myOtherFoobar.doesSomething());
expect (myOtherFoobar.doesSomethingElse());
//...
}
};
// Explicit template instantiation is required to make the unit
// test get automatically added to the set of unit tests.
template class UnitTestType <MyTest>;
@endcode
To run one or more unit tests, use the UnitTests class.
@see UnitTests
*/
template <class Type>
class UnitTestType : public UnitTest
{
public:
explicit UnitTestType (String const& name)
: UnitTest (name)
{
}
static Type s_test;
};
template <class Type>
Type UnitTestType <Type>::s_test;
#endif

View File

@@ -921,14 +921,12 @@ MemoryMappedFile::MemoryMappedFile (const File& file, const Range<int64>& fileRa
openInternal (file, mode); openInternal (file, mode);
} }
//============================================================================== //==============================================================================
#if BEAST_UNIT_TESTS
class FileTests : public UnitTest class FileTests : public UnitTestType <FileTests>
{ {
public: public:
FileTests() : UnitTest ("Files") {} FileTests() : UnitTestType <FileTests> ("File") {}
void runTest() void runTest()
{ {
@@ -1108,6 +1106,7 @@ public:
} }
}; };
static FileTests fileUnitTests; #if BEAST_UNIT_TESTS
template class UnitTestType <FileTests>;
#endif #endif

View File

@@ -531,12 +531,11 @@ void JSON::writeToStream (OutputStream& output, const var& data, const bool allO
//============================================================================== //==============================================================================
//============================================================================== //==============================================================================
#if BEAST_UNIT_TESTS
class JSONTests : public UnitTest class JSONTests : public UnitTestType <JSONTests>
{ {
public: public:
JSONTests() : UnitTest ("JSON") {} JSONTests() : UnitTestType <JSONTests> ("JSON") {}
static String createRandomWideCharString (Random& r) static String createRandomWideCharString (Random& r)
{ {
@@ -640,6 +639,6 @@ public:
} }
}; };
static JSONTests JSONUnitTests; #if BEAST_UNIT_TESTS
template class UnitTestType <JSONTests>;
#endif #endif

View File

@@ -133,12 +133,11 @@ void Random::fillBitsRandomly (BigInteger& arrayToChange, int startBit, int numB
} }
//============================================================================== //==============================================================================
#if BEAST_UNIT_TESTS
class RandomTests : public UnitTest class RandomTests : public UnitTestType <RandomTests>
{ {
public: public:
RandomTests() : UnitTest ("Random") {} RandomTests() : UnitTestType <RandomTests> ("Random") {}
void runTest() void runTest()
{ {
@@ -166,6 +165,6 @@ public:
} }
}; };
static RandomTests randomTests; #if BEAST_UNIT_TESTS
template class UnitTestType <RandomTests>;
#endif #endif

View File

@@ -87,14 +87,12 @@ int64 MemoryInputStream::getPosition()
return position; return position;
} }
//============================================================================== //==============================================================================
#if BEAST_UNIT_TESTS
class MemoryStreamTests : public UnitTest class MemoryStreamTests : public UnitTestType <MemoryStreamTests>
{ {
public: public:
MemoryStreamTests() : UnitTest ("MemoryInputStream & MemoryOutputStream") {} MemoryStreamTests() : UnitTestType <MemoryStreamTests> ("MemoryStream") {}
void runTest() void runTest()
{ {
@@ -150,6 +148,7 @@ public:
} }
}; };
static MemoryStreamTests memoryInputStreamUnitTests; #if BEAST_UNIT_TESTS
template class UnitTestType <MemoryStreamTests>;
#endif #endif

View File

@@ -2074,12 +2074,11 @@ String String::fromUTF8 (const char* const buffer, int bufferSizeBytes)
//============================================================================== //==============================================================================
//============================================================================== //==============================================================================
#if BEAST_UNIT_TESTS
class StringTests : public UnitTest class StringTests : public UnitTestType <StringTests>
{ {
public: public:
StringTests() : UnitTest ("String class") {} StringTests() : UnitTestType <StringTests> ("String") {}
template <class CharPointerType> template <class CharPointerType>
struct TestUTFConversion struct TestUTFConversion
@@ -2403,6 +2402,6 @@ public:
} }
}; };
static StringTests stringUnitTests; #if BEAST_UNIT_TESTS
template class UnitTestType <StringTests>;
#endif #endif

View File

@@ -173,13 +173,11 @@ String TextDiff::Change::appliedTo (const String& text) const noexcept
} }
//============================================================================== //==============================================================================
//==============================================================================
#if BEAST_UNIT_TESTS
class DiffTests : public UnitTest class DiffTests : public UnitTestType <DiffTests>
{ {
public: public:
DiffTests() : UnitTest ("TextDiff class") {} DiffTests() : UnitTestType <DiffTests> ("TextDiff") {}
static String createString() static String createString()
{ {
@@ -231,6 +229,6 @@ public:
} }
}; };
static DiffTests diffTests; #if BEAST_UNIT_TESTS
template class UnitTestType <DiffTests>;
#endif #endif

View File

@@ -57,12 +57,11 @@ String ChildProcess::readAllProcessOutput()
} }
//============================================================================== //==============================================================================
#if BEAST_UNIT_TESTS
class ChildProcessTests : public UnitTest class ChildProcessTests : public UnitTestType <ChildProcessTests>
{ {
public: public:
ChildProcessTests() : UnitTest ("ChildProcess") {} ChildProcessTests() : UnitTestType <ChildProcessTests> ("ChildProcess") {}
void runTest() void runTest()
{ {
@@ -83,6 +82,6 @@ public:
} }
}; };
static ChildProcessTests childProcessUnitTests; #if BEAST_UNIT_TESTS
template class UnitTestType <ChildProcessTests>;
#endif #endif

View File

@@ -251,12 +251,11 @@ void SpinLock::enter() const noexcept
} }
//============================================================================== //==============================================================================
#if BEAST_UNIT_TESTS
class AtomicTests : public UnitTest class AtomicTests : public UnitTestType <AtomicTests>
{ {
public: public:
AtomicTests() : UnitTest ("Atomics") {} AtomicTests() : UnitTestType <AtomicTests> ("Atomic") {}
void runTest() void runTest()
{ {
@@ -351,6 +350,6 @@ public:
}; };
}; };
static AtomicTests atomicUnitTests; #if BEAST_UNIT_TESTS
template class UnitTestType <AtomicTests>;
#endif #endif

View File

@@ -157,12 +157,11 @@ bool GZIPCompressorOutputStream::setPosition (int64 /*newPosition*/)
} }
//============================================================================== //==============================================================================
#if BEAST_UNIT_TESTS
class GZIPTests : public UnitTest class GZIPTests : public UnitTestType <GZIPTests>
{ {
public: public:
GZIPTests() : UnitTest ("GZIP") {} GZIPTests() : UnitTestType <GZIPTests> ("GZIP") {}
void runTest() void runTest()
{ {
@@ -206,6 +205,6 @@ public:
} }
}; };
static GZIPTests gzipTests; #if BEAST_UNIT_TESTS
template class UnitTestType <GZIPTests>;
#endif #endif

View File

@@ -2,6 +2,8 @@
RIPPLE TODO RIPPLE TODO
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
- Examples for different backend key/value config settings
- Unit Test attention - Unit Test attention
- NodeStore backend unit test - NodeStore backend unit test
@@ -313,6 +315,21 @@ What we want from the unique node list:
ChosenValidators ChosenValidators
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
David:
I've cut 2 of the 6 active client-facing servers to hyper. Since then, we've
had 5 spinouts on 3 servers, none of them on the 2 I've cut over. But they
are also the most recently restarted servers, so it's not a 100% fair test.
Maybe OC should have a URL that you can query to get the latest list of URI's
for OC-approved organzations that publish lists of validators. The server and
client can ship with that master trust URL and also the list of URI's at the
time it's released, in case for some reason it can't pull from OC. That would
make the default installation safe even against major changes in the
organizations that publish validator lists.
The difference is that if an organization that provides lists of validators
goes rogue, administrators don't have to act.
TODO: TODO:
Write up from end-user perspective on the deployment and administration Write up from end-user perspective on the deployment and administration
of this feature, on the wiki. "DRAFT" or "PROPOSE" to mark it as provisional. of this feature, on the wiki. "DRAFT" or "PROPOSE" to mark it as provisional.

View File

@@ -119,7 +119,7 @@ void printHelp (const po::options_description& desc)
*/ */
static void runBeastUnitTests () static void runBeastUnitTests ()
{ {
UnitTestRunner tr; UnitTests tr;
tr.setAssertOnFailure (false); tr.setAssertOnFailure (false);
tr.setPassesAreLogged (false); tr.setPassesAreLogged (false);
@@ -129,7 +129,7 @@ static void runBeastUnitTests ()
// Report // Report
for (int i = 0; i < tr.getNumResults (); ++i) for (int i = 0; i < tr.getNumResults (); ++i)
{ {
UnitTestRunner::TestResult const& r (*tr.getResult (i)); UnitTests::TestResult const& r (*tr.getResult (i));
for (int j = 0; j < r.messages.size (); ++i) for (int j = 0; j < r.messages.size (); ++i)
Log::out () << r.messages [j].toStdString (); Log::out () << r.messages [j].toStdString ();