OpenShot Audio Library | OpenShotAudio  0.6.0
juce_UnitTest.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2022 - Raw Material Software Limited
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 static String getTestNameString (const String& testName, const String& subCategory)
198 {
199  return testName + " / " + subCategory;
200 }
201 
202 void UnitTestRunner::beginNewTest (UnitTest* const test, const String& subCategory)
203 {
204  endTest();
205  currentTest = test;
206 
207  auto testName = test->getName();
208  results.add (new TestResult (testName, subCategory));
209 
210  logMessage ("-----------------------------------------------------------------");
211  logMessage ("Starting tests in: " + getTestNameString (testName, subCategory) + "...");
212 
213  resultsUpdated();
214 }
215 
216 void UnitTestRunner::endTest()
217 {
218  if (auto* r = results.getLast())
219  {
220  r->endTime = Time::getCurrentTime();
221 
222  if (r->failures > 0)
223  {
224  String m ("FAILED!! ");
225  m << r->failures << (r->failures == 1 ? " test" : " tests")
226  << " failed, out of a total of " << (r->passes + r->failures);
227 
228  logMessage (String());
229  logMessage (m);
230  logMessage (String());
231  }
232  else
233  {
234  logMessage ("Completed tests in " + getTestNameString (r->unitTestName, r->subcategoryName));
235  }
236  }
237 }
238 
239 void UnitTestRunner::addPass()
240 {
241  {
242  const ScopedLock sl (results.getLock());
243 
244  auto* r = results.getLast();
245  jassert (r != nullptr); // You need to call UnitTest::beginTest() before performing any tests!
246 
247  r->passes++;
248 
249  if (logPasses)
250  {
251  String message ("Test ");
252  message << (r->failures + r->passes) << " passed";
253  logMessage (message);
254  }
255  }
256 
257  resultsUpdated();
258 }
259 
260 void UnitTestRunner::addFail (const String& failureMessage)
261 {
262  {
263  const ScopedLock sl (results.getLock());
264 
265  auto* r = results.getLast();
266  jassert (r != nullptr); // You need to call UnitTest::beginTest() before performing any tests!
267 
268  r->failures++;
269 
270  String message ("!!! Test ");
271  message << (r->failures + r->passes) << " failed";
272 
273  if (failureMessage.isNotEmpty())
274  message << ": " << failureMessage;
275 
276  r->messages.add (message);
277 
278  logMessage (message);
279  }
280 
281  resultsUpdated();
282 
283  if (assertOnFailure) { jassertfalse; }
284 }
285 
286 } // 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:74
bool addIfNotAlreadyThere(const String &stringToAdd, bool ignoreCase=false)
bool isEmpty() const noexcept
Definition: juce_String.h:310
static String toHexString(IntegerType number)
Definition: juce_String.h:1097
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Definition: juce_Time.cpp:233
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)