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