Loading...
Searching...
No Matches
juce_UnitTest.cpp
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
To use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
UnitTest::UnitTest (const String& nm, const String& ctg)
: name (nm), category (ctg)
{
getAllTests().add (this);
}
UnitTest::~UnitTest()
{
getAllTests().removeFirstMatchingValue (this);
}
Array<UnitTest*>& UnitTest::getAllTests()
{
static Array<UnitTest*> tests;
return tests;
}
Array<UnitTest*> UnitTest::getTestsInCategory (const String& category)
{
if (category.isEmpty())
return getAllTests();
Array<UnitTest*> unitTests;
for (auto* test : getAllTests())
if (test->getCategory() == category)
unitTests.add (test);
return unitTests;
}
StringArray UnitTest::getAllCategories()
{
StringArray categories;
for (auto* test : getAllTests())
if (test->getCategory().isNotEmpty())
categories.addIfNotAlreadyThere (test->getCategory());
return categories;
}
void UnitTest::initialise() {}
void UnitTest::shutdown() {}
void UnitTest::performTest (UnitTestRunner* const newRunner)
{
jassert (newRunner != nullptr);
runner = newRunner;
initialise();
runTest();
shutdown();
}
void UnitTest::logMessage (const String& message)
{
// This method's only valid while the test is being run!
jassert (runner != nullptr);
runner->logMessage (message);
}
void UnitTest::beginTest (const String& testName)
{
// This method's only valid while the test is being run!
jassert (runner != nullptr);
runner->beginNewTest (this, testName);
}
void UnitTest::expect (const bool result, const String& failureMessage)
{
// This method's only valid while the test is being run!
jassert (runner != nullptr);
if (result)
runner->addPass();
else
runner->addFail (failureMessage);
}
Random UnitTest::getRandom() const
{
// This method's only valid while the test is being run!
jassert (runner != nullptr);
return runner->randomForTest;
}
//==============================================================================
UnitTestRunner::UnitTestRunner() {}
UnitTestRunner::~UnitTestRunner() {}
void UnitTestRunner::setAssertOnFailure (bool shouldAssert) noexcept
{
assertOnFailure = shouldAssert;
}
void UnitTestRunner::setPassesAreLogged (bool shouldDisplayPasses) noexcept
{
logPasses = shouldDisplayPasses;
}
int UnitTestRunner::getNumResults() const noexcept
{
return results.size();
}
const UnitTestRunner::TestResult* UnitTestRunner::getResult (int index) const noexcept
{
return results [index];
}
void UnitTestRunner::resultsUpdated()
{
}
void UnitTestRunner::runTests (const Array<UnitTest*>& tests, int64 randomSeed)
{
results.clear();
resultsUpdated();
if (randomSeed == 0)
randomSeed = Random().nextInt (0x7ffffff);
randomForTest = Random (randomSeed);
logMessage ("Random seed: 0x" + String::toHexString (randomSeed));
for (auto* t : tests)
{
if (shouldAbortTests())
break;
#if JUCE_EXCEPTIONS_DISABLED
t->performTest (this);
#else
try
{
t->performTest (this);
}
catch (...)
{
addFail ("An unhandled exception was thrown!");
}
#endif
}
endTest();
}
void UnitTestRunner::runAllTests (int64 randomSeed)
{
runTests (UnitTest::getAllTests(), randomSeed);
}
void UnitTestRunner::runTestsInCategory (const String& category, int64 randomSeed)
{
runTests (UnitTest::getTestsInCategory (category), randomSeed);
}
void UnitTestRunner::logMessage (const String& message)
{
Logger::writeToLog (message);
}
bool UnitTestRunner::shouldAbortTests()
{
return false;
}
static String getTestNameString (const String& testName, const String& subCategory)
{
return testName + " / " + subCategory;
}
void UnitTestRunner::beginNewTest (UnitTest* const test, const String& subCategory)
{
endTest();
currentTest = test;
auto testName = test->getName();
results.add (new TestResult (testName, subCategory));
logMessage ("-----------------------------------------------------------------");
logMessage ("Starting tests in: " + getTestNameString (testName, subCategory) + "...");
resultsUpdated();
}
void UnitTestRunner::endTest()
{
if (auto* r = results.getLast())
{
r->endTime = Time::getCurrentTime();
if (r->failures > 0)
{
String m ("FAILED!! ");
m << r->failures << (r->failures == 1 ? " test" : " tests")
<< " failed, out of a total of " << (r->passes + r->failures);
logMessage (String());
logMessage (m);
logMessage (String());
}
else
{
logMessage ("Completed tests in " + getTestNameString (r->unitTestName, r->subcategoryName));
}
}
}
void UnitTestRunner::addPass()
{
{
const ScopedLock sl (results.getLock());
auto* r = results.getLast();
jassert (r != nullptr); // You need to call UnitTest::beginTest() before performing any tests!
r->passes++;
if (logPasses)
{
String message ("Test ");
message << (r->failures + r->passes) << " passed";
logMessage (message);
}
}
resultsUpdated();
}
void UnitTestRunner::addFail (const String& failureMessage)
{
{
const ScopedLock sl (results.getLock());
auto* r = results.getLast();
jassert (r != nullptr); // You need to call UnitTest::beginTest() before performing any tests!
r->failures++;
String message ("!!! Test ");
message << (r->failures + r->passes) << " failed";
if (failureMessage.isNotEmpty())
message << ": " << failureMessage;
r->messages.add (message);
logMessage (message);
}
resultsUpdated();
if (assertOnFailure) { jassertfalse; }
}
} // namespace juce
juce::Array
Definition juce_Array.h:56
juce::Array::add
void add(const ElementType &newElement)
Definition juce_Array.h:418
juce::Logger::writeToLog
static void JUCE_CALLTYPE writeToLog(const String &message)
Definition juce_Logger.cpp:40
juce::Random
Definition juce_Random.h:35
juce::Random::nextInt
int nextInt() noexcept
Definition juce_Random.cpp:74
juce::StringArray
Definition juce_StringArray.h:35
juce::StringArray::addIfNotAlreadyThere
bool addIfNotAlreadyThere(const String &stringToAdd, bool ignoreCase=false)
Definition juce_StringArray.cpp:150
juce::String
Definition juce_String.h:53
juce::String::toHexString
static String toHexString(IntegerType number)
Definition juce_String.h:1097
juce::Time::getCurrentTime
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Definition juce_Time.cpp:233
juce::UnitTestRunner
Definition juce_UnitTest.h:325
juce::UnitTestRunner::runAllTests
void runAllTests(int64 randomSeed=0)
Definition juce_UnitTest.cpp:177
juce::UnitTestRunner::runTestsInCategory
void runTestsInCategory(const String &category, int64 randomSeed=0)
Definition juce_UnitTest.cpp:182
juce::UnitTestRunner::~UnitTestRunner
virtual ~UnitTestRunner()
Definition juce_UnitTest.cpp:118
juce::UnitTestRunner::shouldAbortTests
virtual bool shouldAbortTests()
Definition juce_UnitTest.cpp:192
juce::UnitTestRunner::getResult
const TestResult * getResult(int index) const noexcept
Definition juce_UnitTest.cpp:135
juce::UnitTestRunner::getNumResults
int getNumResults() const noexcept
Definition juce_UnitTest.cpp:130
juce::UnitTestRunner::setAssertOnFailure
void setAssertOnFailure(bool shouldAssert) noexcept
Definition juce_UnitTest.cpp:120
juce::UnitTestRunner::runTests
void runTests(const Array< UnitTest * > &tests, int64 randomSeed=0)
Definition juce_UnitTest.cpp:144
juce::UnitTestRunner::setPassesAreLogged
void setPassesAreLogged(bool shouldDisplayPasses) noexcept
Definition juce_UnitTest.cpp:125
juce::UnitTestRunner::logMessage
virtual void logMessage(const String &message)
Definition juce_UnitTest.cpp:187
juce::UnitTestRunner::resultsUpdated
virtual void resultsUpdated()
Definition juce_UnitTest.cpp:140
juce::UnitTest::getName
const String & getName() const noexcept
Definition juce_UnitTest.h:80
juce::UnitTest::logMessage
void logMessage(const String &message)
Definition juce_UnitTest.cpp:81
juce::UnitTest::getAllCategories
static StringArray getAllCategories()
Definition juce_UnitTest.cpp:57
juce::UnitTest::getTestsInCategory
static Array< UnitTest * > getTestsInCategory(const String &category)
Definition juce_UnitTest.cpp:43
juce::UnitTest::initialise
virtual void initialise()
Definition juce_UnitTest.cpp:68
juce::UnitTest::UnitTest
UnitTest(const String &name, const String &category=String())
Definition juce_UnitTest.cpp:26
juce::UnitTest::getAllTests
static Array< UnitTest * > & getAllTests()
Definition juce_UnitTest.cpp:37
juce::UnitTest::beginTest
void beginTest(const String &testName)
Definition juce_UnitTest.cpp:89
juce::UnitTest::expect
void expect(bool testResult, const String &failureMessage=String())
Definition juce_UnitTest.cpp:97
juce::UnitTest::shutdown
virtual void shutdown()
Definition juce_UnitTest.cpp:69
juce::UnitTest::runTest
virtual void runTest()=0
juce::UnitTest::getRandom
Random getRandom() const
Definition juce_UnitTest.cpp:108
juce::UnitTest::~UnitTest
virtual ~UnitTest()
Definition juce_UnitTest.cpp:32
juce::UnitTest::performTest
void performTest(UnitTestRunner *runner)
Definition juce_UnitTest.cpp:71
juce::UnitTestRunner::TestResult
Definition juce_UnitTest.h:378