OpenShot Audio Library | OpenShotAudio  0.3.1
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)
virtual void resultsUpdated()
bool isNotEmpty() const noexcept
Definition: juce_String.h:302
static Array< UnitTest * > getTestsInCategory(const String &category)
virtual void logMessage(const String &message)
int nextInt() noexcept
Definition: juce_Random.cpp:78
void add(const ElementType &newElement)
Definition: juce_Array.h:418
UnitTest(const String &name, const String &category=String())
const String & getName() const noexcept
Definition: juce_UnitTest.h:80
void performTest(UnitTestRunner *runner)
void logMessage(const String &message)
virtual void runTest()=0
void runTestsInCategory(const String &category, int64 randomSeed=0)
virtual void shutdown()
virtual bool shouldAbortTests()
virtual ~UnitTest()
const TestResult * getResult(int index) const noexcept
void beginTest(const String &testName)
void runTests(const Array< UnitTest *> &tests, int64 randomSeed=0)
static StringArray getAllCategories()
static String toHexString(IntegerType number)
Definition: juce_String.h:1053
virtual void initialise()
Random getRandom() const
bool addIfNotAlreadyThere(const String &stringToAdd, bool ignoreCase=false)
static Array< UnitTest * > & getAllTests()
int getNumResults() const noexcept
bool isEmpty() const noexcept
Definition: juce_String.h:296
void setAssertOnFailure(bool shouldAssert) noexcept
void expect(bool testResult, const String &failureMessage=String())
static void JUCE_CALLTYPE writeToLog(const String &message)
Definition: juce_Logger.cpp:40
void setPassesAreLogged(bool shouldDisplayPasses) noexcept