OpenShot Library | OpenShotAudio  0.2.2
juce_UnitTest.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 UnitTest::UnitTest (const String& nm, const String& ctg)
27  : name (nm), category (ctg)
28 {
29  getAllTests().add (this);
30 }
31 
33 {
34  getAllTests().removeFirstMatchingValue (this);
35 }
36 
38 {
39  static Array<UnitTest*> tests;
40  return tests;
41 }
42 
44 {
45  if (category.isEmpty())
46  return getAllTests();
47 
48  Array<UnitTest*> unitTests;
49 
50  for (auto* test : getAllTests())
51  if (test->getCategory() == category)
52  unitTests.add (test);
53 
54  return unitTests;
55 }
56 
58 {
59  StringArray categories;
60 
61  for (auto* test : getAllTests())
62  if (test->getCategory().isNotEmpty())
63  categories.addIfNotAlreadyThere (test->getCategory());
64 
65  return categories;
66 }
67 
70 
71 void UnitTest::performTest (UnitTestRunner* const newRunner)
72 {
73  jassert (newRunner != nullptr);
74  runner = newRunner;
75 
76  initialise();
77  runTest();
78  shutdown();
79 }
80 
81 void UnitTest::logMessage (const String& message)
82 {
83  // This method's only valid while the test is being run!
84  jassert (runner != nullptr);
85 
86  runner->logMessage (message);
87 }
88 
89 void UnitTest::beginTest (const String& testName)
90 {
91  // This method's only valid while the test is being run!
92  jassert (runner != nullptr);
93 
94  runner->beginNewTest (this, testName);
95 }
96 
97 void UnitTest::expect (const bool result, const String& failureMessage)
98 {
99  // This method's only valid while the test is being run!
100  jassert (runner != nullptr);
101 
102  if (result)
103  runner->addPass();
104  else
105  runner->addFail (failureMessage);
106 }
107 
109 {
110  // This method's only valid while the test is being run!
111  jassert (runner != nullptr);
112 
113  return runner->randomForTest;
114 }
115 
116 //==============================================================================
117 UnitTestRunner::UnitTestRunner() {}
119 
120 void UnitTestRunner::setAssertOnFailure (bool shouldAssert) noexcept
121 {
122  assertOnFailure = shouldAssert;
123 }
124 
125 void UnitTestRunner::setPassesAreLogged (bool shouldDisplayPasses) noexcept
126 {
127  logPasses = shouldDisplayPasses;
128 }
129 
130 int UnitTestRunner::getNumResults() const noexcept
131 {
132  return results.size();
133 }
134 
135 const UnitTestRunner::TestResult* UnitTestRunner::getResult (int index) const noexcept
136 {
137  return results [index];
138 }
139 
141 {
142 }
143 
144 void UnitTestRunner::runTests (const Array<UnitTest*>& tests, int64 randomSeed)
145 {
146  results.clear();
147  resultsUpdated();
148 
149  if (randomSeed == 0)
150  randomSeed = Random().nextInt (0x7ffffff);
151 
152  randomForTest = Random (randomSeed);
153  logMessage ("Random seed: 0x" + String::toHexString (randomSeed));
154 
155  for (auto* t : tests)
156  {
157  if (shouldAbortTests())
158  break;
159 
160  #if JUCE_EXCEPTIONS_DISABLED
161  t->performTest (this);
162  #else
163  try
164  {
165  t->performTest (this);
166  }
167  catch (...)
168  {
169  addFail ("An unhandled exception was thrown!");
170  }
171  #endif
172  }
173 
174  endTest();
175 }
176 
177 void UnitTestRunner::runAllTests (int64 randomSeed)
178 {
179  runTests (UnitTest::getAllTests(), randomSeed);
180 }
181 
182 void UnitTestRunner::runTestsInCategory (const String& category, int64 randomSeed)
183 {
184  runTests (UnitTest::getTestsInCategory (category), randomSeed);
185 }
186 
187 void UnitTestRunner::logMessage (const String& message)
188 {
189  Logger::writeToLog (message);
190 }
191 
193 {
194  return false;
195 }
196 
197 void UnitTestRunner::beginNewTest (UnitTest* const test, const String& subCategory)
198 {
199  endTest();
200  currentTest = test;
201 
202  auto* r = new TestResult();
203  results.add (r);
204  r->unitTestName = test->getName();
205  r->subcategoryName = subCategory;
206  r->passes = 0;
207  r->failures = 0;
208 
209  logMessage ("-----------------------------------------------------------------");
210  logMessage ("Starting test: " + r->unitTestName + " / " + subCategory + "...");
211 
212  resultsUpdated();
213 }
214 
215 void UnitTestRunner::endTest()
216 {
217  if (auto* r = results.getLast())
218  {
219  if (r->failures > 0)
220  {
221  String m ("FAILED!! ");
222  m << r->failures << (r->failures == 1 ? " test" : " tests")
223  << " failed, out of a total of " << (r->passes + r->failures);
224 
225  logMessage (String());
226  logMessage (m);
227  logMessage (String());
228  }
229  else
230  {
231  logMessage ("All tests completed successfully");
232  }
233  }
234 }
235 
236 void UnitTestRunner::addPass()
237 {
238  {
239  const ScopedLock sl (results.getLock());
240 
241  auto* r = results.getLast();
242  jassert (r != nullptr); // You need to call UnitTest::beginTest() before performing any tests!
243 
244  r->passes++;
245 
246  if (logPasses)
247  {
248  String message ("Test ");
249  message << (r->failures + r->passes) << " passed";
250  logMessage (message);
251  }
252  }
253 
254  resultsUpdated();
255 }
256 
257 void UnitTestRunner::addFail (const String& failureMessage)
258 {
259  {
260  const ScopedLock sl (results.getLock());
261 
262  auto* r = results.getLast();
263  jassert (r != nullptr); // You need to call UnitTest::beginTest() before performing any tests!
264 
265  r->failures++;
266 
267  String message ("!!! Test ");
268  message << (r->failures + r->passes) << " failed";
269 
270  if (failureMessage.isNotEmpty())
271  message << ": " << failureMessage;
272 
273  r->messages.add (message);
274 
275  logMessage (message);
276  }
277 
278  resultsUpdated();
279 
280  if (assertOnFailure) { jassertfalse; }
281 }
282 
283 } // namespace juce
void runAllTests(int64 randomSeed=0)
Runs all the UnitTest objects that currently exist.
virtual void resultsUpdated()
Called when the list of results changes.
bool isNotEmpty() const noexcept
Returns true if the string contains at least one character.
Definition: juce_String.h:306
static Array< UnitTest * > getTestsInCategory(const String &category)
Returns the set of UnitTests in a specified category.
virtual void logMessage(const String &message)
Logs a message about the current test progress.
int nextInt() noexcept
Returns the next random 32 bit integer.
Definition: juce_Random.cpp:78
void add(const ElementType &newElement)
Appends a new element at the end of the array.
Definition: juce_Array.h:422
UnitTest(const String &name, const String &category=String())
Creates a test with the given name and optionally places it in a category.
const String & getName() const noexcept
Returns the name of the test.
Definition: juce_UnitTest.h:84
void performTest(UnitTestRunner *runner)
Runs the test, using the specified UnitTestRunner.
void logMessage(const String &message)
Writes a message to the test log.
A special array for holding a list of strings.
The JUCE String class!
Definition: juce_String.h:42
virtual void runTest()=0
Implement this method in your subclass to actually run your tests.
void runTestsInCategory(const String &category, int64 randomSeed=0)
Runs all the UnitTest objects within a specified category.
virtual void shutdown()
You can optionally implement this method to clear up after your test has been run.
This is a base class for classes that perform a unit test.
Definition: juce_UnitTest.h:73
virtual bool shouldAbortTests()
This can be overridden to let the runner know that it should abort the tests as soon as possible...
virtual ~UnitTest()
Destructor.
const TestResult * getResult(int index) const noexcept
Returns one of the TestResult objects that describes a test that has been run.
void beginTest(const String &testName)
Tells the system that a new subsection of tests is beginning.
Runs a set of unit tests.
void runTests(const Array< UnitTest *> &tests, int64 randomSeed=0)
Runs a set of tests.
static StringArray getAllCategories()
Returns a StringArray containing all of the categories of UnitTests that have been registered...
static String toHexString(IntegerType number)
Returns a string representing this numeric value in hexadecimal.
Definition: juce_String.h:1057
virtual void initialise()
You can optionally implement this method to set up your test.
Random getRandom() const
Returns a shared RNG that all unit tests should use.
bool addIfNotAlreadyThere(const String &stringToAdd, bool ignoreCase=false)
Adds a string to the array as long as it&#39;s not already in there.
static Array< UnitTest * > & getAllTests()
Returns the set of all UnitTest objects that currently exist.
Holds a resizable array of primitive or copy-by-value objects.
Definition: juce_Array.h:59
int getNumResults() const noexcept
Returns the number of TestResult objects that have been performed.
bool isEmpty() const noexcept
Returns true if the string contains no characters.
Definition: juce_String.h:300
void setAssertOnFailure(bool shouldAssert) noexcept
Sets a flag to indicate whether an assertion should be triggered if a test fails. ...
void expect(bool testResult, const String &failureMessage=String())
Checks that the result of a test is true, and logs this result.
static void JUCE_CALLTYPE writeToLog(const String &message)
Writes a string to the current logger.
Definition: juce_Logger.cpp:40
A random number generator.
Definition: juce_Random.h:38
Contains the results of a test.
virtual ~UnitTestRunner()
Destructor.
void setPassesAreLogged(bool shouldDisplayPasses) noexcept
Sets a flag to indicate whether successful tests should be logged.
Automatically locks and unlocks a mutex object.