mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Updated the UnitTest class to provide a shared, reproducible random seed for each run, to allow failures to be re-created. Also converted a few Strings to StringRefs.
This commit is contained in:
parent
14cfa338b6
commit
435089e89b
23 changed files with 178 additions and 133 deletions
|
|
@ -482,17 +482,16 @@ public:
|
|||
template <class F1, class E1, class F2, class E2>
|
||||
struct Test5
|
||||
{
|
||||
static void test (UnitTest& unitTest)
|
||||
static void test (UnitTest& unitTest, Random& r)
|
||||
{
|
||||
test (unitTest, false);
|
||||
test (unitTest, true);
|
||||
test (unitTest, false, r);
|
||||
test (unitTest, true, r);
|
||||
}
|
||||
|
||||
static void test (UnitTest& unitTest, bool inPlace)
|
||||
static void test (UnitTest& unitTest, bool inPlace, Random& r)
|
||||
{
|
||||
const int numSamples = 2048;
|
||||
int32 original [numSamples], converted [numSamples], reversed [numSamples];
|
||||
Random r;
|
||||
|
||||
{
|
||||
AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst> d (original);
|
||||
|
|
@ -549,49 +548,50 @@ public:
|
|||
template <class F1, class E1, class FormatType>
|
||||
struct Test3
|
||||
{
|
||||
static void test (UnitTest& unitTest)
|
||||
static void test (UnitTest& unitTest, Random& r)
|
||||
{
|
||||
Test5 <F1, E1, FormatType, AudioData::BigEndian>::test (unitTest);
|
||||
Test5 <F1, E1, FormatType, AudioData::LittleEndian>::test (unitTest);
|
||||
Test5 <F1, E1, FormatType, AudioData::BigEndian>::test (unitTest, r);
|
||||
Test5 <F1, E1, FormatType, AudioData::LittleEndian>::test (unitTest, r);
|
||||
}
|
||||
};
|
||||
|
||||
template <class FormatType, class Endianness>
|
||||
struct Test2
|
||||
{
|
||||
static void test (UnitTest& unitTest)
|
||||
static void test (UnitTest& unitTest, Random& r)
|
||||
{
|
||||
Test3 <FormatType, Endianness, AudioData::Int8>::test (unitTest);
|
||||
Test3 <FormatType, Endianness, AudioData::UInt8>::test (unitTest);
|
||||
Test3 <FormatType, Endianness, AudioData::Int16>::test (unitTest);
|
||||
Test3 <FormatType, Endianness, AudioData::Int24>::test (unitTest);
|
||||
Test3 <FormatType, Endianness, AudioData::Int32>::test (unitTest);
|
||||
Test3 <FormatType, Endianness, AudioData::Float32>::test (unitTest);
|
||||
Test3 <FormatType, Endianness, AudioData::Int8>::test (unitTest, r);
|
||||
Test3 <FormatType, Endianness, AudioData::UInt8>::test (unitTest, r);
|
||||
Test3 <FormatType, Endianness, AudioData::Int16>::test (unitTest, r);
|
||||
Test3 <FormatType, Endianness, AudioData::Int24>::test (unitTest, r);
|
||||
Test3 <FormatType, Endianness, AudioData::Int32>::test (unitTest, r);
|
||||
Test3 <FormatType, Endianness, AudioData::Float32>::test (unitTest, r);
|
||||
}
|
||||
};
|
||||
|
||||
template <class FormatType>
|
||||
struct Test1
|
||||
{
|
||||
static void test (UnitTest& unitTest)
|
||||
static void test (UnitTest& unitTest, Random& r)
|
||||
{
|
||||
Test2 <FormatType, AudioData::BigEndian>::test (unitTest);
|
||||
Test2 <FormatType, AudioData::LittleEndian>::test (unitTest);
|
||||
Test2 <FormatType, AudioData::BigEndian>::test (unitTest, r);
|
||||
Test2 <FormatType, AudioData::LittleEndian>::test (unitTest, r);
|
||||
}
|
||||
};
|
||||
|
||||
void runTest()
|
||||
{
|
||||
Random r = getRandom();
|
||||
beginTest ("Round-trip conversion: Int8");
|
||||
Test1 <AudioData::Int8>::test (*this);
|
||||
Test1 <AudioData::Int8>::test (*this, r);
|
||||
beginTest ("Round-trip conversion: Int16");
|
||||
Test1 <AudioData::Int16>::test (*this);
|
||||
Test1 <AudioData::Int16>::test (*this, r);
|
||||
beginTest ("Round-trip conversion: Int24");
|
||||
Test1 <AudioData::Int24>::test (*this);
|
||||
Test1 <AudioData::Int24>::test (*this, r);
|
||||
beginTest ("Round-trip conversion: Int32");
|
||||
Test1 <AudioData::Int32>::test (*this);
|
||||
Test1 <AudioData::Int32>::test (*this, r);
|
||||
beginTest ("Round-trip conversion: Float32");
|
||||
Test1 <AudioData::Float32>::test (*this);
|
||||
Test1 <AudioData::Float32>::test (*this, r);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -141,8 +141,8 @@ public:
|
|||
class WriteThread : public Thread
|
||||
{
|
||||
public:
|
||||
WriteThread (AbstractFifo& fifo_, int* buffer_)
|
||||
: Thread ("fifo writer"), fifo (fifo_), buffer (buffer_)
|
||||
WriteThread (AbstractFifo& f, int* b, Random rng)
|
||||
: Thread ("fifo writer"), fifo (f), buffer (b), random (rng)
|
||||
{
|
||||
startThread();
|
||||
}
|
||||
|
|
@ -155,11 +155,10 @@ public:
|
|||
void run()
|
||||
{
|
||||
int n = 0;
|
||||
Random r;
|
||||
|
||||
while (! threadShouldExit())
|
||||
{
|
||||
int num = r.nextInt (2000) + 1;
|
||||
int num = random.nextInt (2000) + 1;
|
||||
|
||||
int start1, size1, start2, size2;
|
||||
fifo.prepareToWrite (num, start1, size1, start2, size2);
|
||||
|
|
@ -181,6 +180,7 @@ public:
|
|||
private:
|
||||
AbstractFifo& fifo;
|
||||
int* buffer;
|
||||
Random random;
|
||||
};
|
||||
|
||||
void runTest()
|
||||
|
|
@ -190,10 +190,11 @@ public:
|
|||
int buffer [5000];
|
||||
AbstractFifo fifo (numElementsInArray (buffer));
|
||||
|
||||
WriteThread writer (fifo, buffer);
|
||||
WriteThread writer (fifo, buffer, getRandom());
|
||||
|
||||
int n = 0;
|
||||
Random r;
|
||||
Random r = getRandom();
|
||||
r.combineSeed (12345);
|
||||
|
||||
for (int count = 100000; --count >= 0;)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -616,8 +616,7 @@ public:
|
|||
void runTest()
|
||||
{
|
||||
beginTest ("JSON");
|
||||
Random r;
|
||||
r.setSeedRandomly();
|
||||
Random r = getRandom();
|
||||
|
||||
expect (JSON::parse (String::empty) == var::null);
|
||||
expect (JSON::parse ("{}").isObject());
|
||||
|
|
|
|||
|
|
@ -953,10 +953,10 @@ String BigInteger::toString (const int base, const int minimumNumCharacters) con
|
|||
return isNegative() ? "-" + s : s;
|
||||
}
|
||||
|
||||
void BigInteger::parseString (const String& text, const int base)
|
||||
void BigInteger::parseString (StringRef text, const int base)
|
||||
{
|
||||
clear();
|
||||
String::CharPointerType t (text.getCharPointer().findEndOfWhitespace());
|
||||
String::CharPointerType t (text.text.findEndOfWhitespace());
|
||||
|
||||
setNegative (*t == (juce_wchar) '-');
|
||||
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ public:
|
|||
Specify a base such as 2 (binary), 8 (octal), 10 (decimal), 16 (hex).
|
||||
Any invalid characters will be ignored.
|
||||
*/
|
||||
void parseString (const String& text, int base);
|
||||
void parseString (StringRef text, int base);
|
||||
|
||||
//==============================================================================
|
||||
/** Turns the number into a block of binary data.
|
||||
|
|
|
|||
|
|
@ -26,13 +26,11 @@
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
Random::Random (const int64 seedValue) noexcept
|
||||
: seed (seedValue)
|
||||
Random::Random (const int64 seedValue) noexcept : seed (seedValue)
|
||||
{
|
||||
}
|
||||
|
||||
Random::Random()
|
||||
: seed (1)
|
||||
Random::Random() : seed (1)
|
||||
{
|
||||
setSeedRandomly();
|
||||
}
|
||||
|
|
@ -163,24 +161,20 @@ public:
|
|||
{
|
||||
beginTest ("Random");
|
||||
|
||||
for (int j = 10; --j >= 0;)
|
||||
Random r = getRandom();
|
||||
|
||||
for (int i = 2000; --i >= 0;)
|
||||
{
|
||||
Random r;
|
||||
r.setSeedRandomly();
|
||||
expect (r.nextDouble() >= 0.0 && r.nextDouble() < 1.0);
|
||||
expect (r.nextFloat() >= 0.0f && r.nextFloat() < 1.0f);
|
||||
expect (r.nextInt (5) >= 0 && r.nextInt (5) < 5);
|
||||
expect (r.nextInt (1) == 0);
|
||||
|
||||
for (int i = 20; --i >= 0;)
|
||||
{
|
||||
expect (r.nextDouble() >= 0.0 && r.nextDouble() < 1.0);
|
||||
expect (r.nextFloat() >= 0.0f && r.nextFloat() < 1.0f);
|
||||
expect (r.nextInt (5) >= 0 && r.nextInt (5) < 5);
|
||||
expect (r.nextInt (1) == 0);
|
||||
int n = r.nextInt (50) + 1;
|
||||
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
|
||||
|
||||
int n = r.nextInt (50) + 1;
|
||||
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
|
||||
|
||||
n = r.nextInt (0x7ffffffe) + 1;
|
||||
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
|
||||
}
|
||||
n = r.nextInt (0x7ffffffe) + 1;
|
||||
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ public:
|
|||
~Random() noexcept;
|
||||
|
||||
/** Returns the next random 32 bit integer.
|
||||
|
||||
@returns a random integer from the full range 0x80000000 to 0x7fffffff
|
||||
*/
|
||||
int nextInt() noexcept;
|
||||
|
|
@ -71,29 +70,24 @@ public:
|
|||
int nextInt (int maxValue) noexcept;
|
||||
|
||||
/** Returns the next 64-bit random number.
|
||||
|
||||
@returns a random integer from the full range 0x8000000000000000 to 0x7fffffffffffffff
|
||||
*/
|
||||
int64 nextInt64() noexcept;
|
||||
|
||||
/** Returns the next random floating-point number.
|
||||
|
||||
@returns a random value in the range 0 to 1.0
|
||||
*/
|
||||
float nextFloat() noexcept;
|
||||
|
||||
/** Returns the next random floating-point number.
|
||||
|
||||
@returns a random value in the range 0 to 1.0
|
||||
*/
|
||||
double nextDouble() noexcept;
|
||||
|
||||
/** Returns the next random boolean value.
|
||||
*/
|
||||
/** Returns the next random boolean value. */
|
||||
bool nextBool() noexcept;
|
||||
|
||||
/** Returns a BigInteger containing a random number.
|
||||
|
||||
@returns a random value in the range 0 to (maximumValue - 1).
|
||||
*/
|
||||
BigInteger nextLargeNumber (const BigInteger& maximumValue);
|
||||
|
|
@ -108,6 +102,9 @@ public:
|
|||
/** Resets this Random object to a given seed value. */
|
||||
void setSeed (int64 newSeed) noexcept;
|
||||
|
||||
/** Returns the RNG's current seed. */
|
||||
int64 getSeed() const noexcept { return seed; }
|
||||
|
||||
/** Merges this object's seed with another value.
|
||||
This sets the seed to be a value created by combining the current seed and this
|
||||
new value.
|
||||
|
|
|
|||
|
|
@ -317,11 +317,11 @@ void MemoryBlock::setBitRange (const size_t bitRangeStart, size_t numBits, int b
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
void MemoryBlock::loadFromHexString (const String& hex)
|
||||
void MemoryBlock::loadFromHexString (StringRef hex)
|
||||
{
|
||||
ensureSize ((size_t) hex.length() >> 1);
|
||||
char* dest = data;
|
||||
String::CharPointerType t (hex.getCharPointer());
|
||||
String::CharPointerType t (hex.text);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
|
@ -373,27 +373,27 @@ String MemoryBlock::toBase64Encoding() const
|
|||
return destString;
|
||||
}
|
||||
|
||||
bool MemoryBlock::fromBase64Encoding (const String& s)
|
||||
bool MemoryBlock::fromBase64Encoding (StringRef s)
|
||||
{
|
||||
const int startPos = s.indexOfChar ('.') + 1;
|
||||
String::CharPointerType dot (CharacterFunctions::find (s.text, CharPointer_ASCII (".")));
|
||||
|
||||
if (startPos <= 0)
|
||||
if (dot.isEmpty())
|
||||
return false;
|
||||
|
||||
const int numBytesNeeded = s.substring (0, startPos - 1).getIntValue();
|
||||
const int numBytesNeeded = String (s.text, dot).getIntValue();
|
||||
|
||||
setSize ((size_t) numBytesNeeded, true);
|
||||
|
||||
const int numChars = s.length() - startPos;
|
||||
|
||||
String::CharPointerType srcChars (s.getCharPointer());
|
||||
srcChars += startPos;
|
||||
String::CharPointerType srcChars (dot + 1);
|
||||
int pos = 0;
|
||||
|
||||
for (int i = 0; i < numChars; ++i)
|
||||
for (;;)
|
||||
{
|
||||
const char c = (char) srcChars.getAndAdvance();
|
||||
|
||||
if (c == 0)
|
||||
return true;
|
||||
|
||||
for (int j = 0; j < 64; ++j)
|
||||
{
|
||||
if (base64EncodingTable[j] == c)
|
||||
|
|
@ -404,6 +404,4 @@ bool MemoryBlock::fromBase64Encoding (const String& s)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ public:
|
|||
|
||||
@see String::toHexString()
|
||||
*/
|
||||
void loadFromHexString (const String& sourceHexString);
|
||||
void loadFromHexString (StringRef sourceHexString);
|
||||
|
||||
//==============================================================================
|
||||
/** Sets a number of bits in the memory block, treating it as a long binary sequence. */
|
||||
|
|
@ -235,7 +235,7 @@ public:
|
|||
|
||||
@see toBase64Encoding
|
||||
*/
|
||||
bool fromBase64Encoding (const String& encodedString);
|
||||
bool fromBase64Encoding (StringRef encodedString);
|
||||
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -104,12 +104,12 @@ public:
|
|||
void runTest()
|
||||
{
|
||||
beginTest ("Basics");
|
||||
Random r;
|
||||
Random r = getRandom();
|
||||
|
||||
int randomInt = r.nextInt();
|
||||
int64 randomInt64 = r.nextInt64();
|
||||
double randomDouble = r.nextDouble();
|
||||
String randomString (createRandomWideCharString());
|
||||
String randomString (createRandomWideCharString (r));
|
||||
|
||||
MemoryOutputStream mo;
|
||||
mo.writeInt (randomInt);
|
||||
|
|
@ -132,10 +132,9 @@ public:
|
|||
expect (mi.readDoubleBigEndian() == randomDouble);
|
||||
}
|
||||
|
||||
static String createRandomWideCharString()
|
||||
static String createRandomWideCharString (Random& r)
|
||||
{
|
||||
juce_wchar buffer [50] = { 0 };
|
||||
Random r;
|
||||
|
||||
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2075,6 +2075,10 @@ String String::fromUTF8 (const char* const buffer, int bufferSizeBytes)
|
|||
#endif
|
||||
|
||||
//==============================================================================
|
||||
StringRef::StringRef() noexcept : text ("\0\0\0")
|
||||
{
|
||||
}
|
||||
|
||||
StringRef::StringRef (const String::CharPointerType::CharType* stringLiteral) noexcept : text (stringLiteral)
|
||||
{
|
||||
jassert (stringLiteral != nullptr); // This must be a valid string literal, not a null pointer!!
|
||||
|
|
@ -2086,8 +2090,8 @@ StringRef::StringRef (const String::CharPointerType::CharType* stringLiteral) no
|
|||
create them. The source data could be UTF-8, ASCII or one of many local code-pages.
|
||||
|
||||
To get around this problem, you must be more explicit when you pass an ambiguous 8-bit
|
||||
string to the String class - so for example if your source data is actually UTF-8,
|
||||
you'd call String (CharPointer_UTF8 ("my utf8 string..")), and it would be able to
|
||||
string to the StringRef class - so for example if your source data is actually UTF-8,
|
||||
you'd call StringRef (CharPointer_UTF8 ("my utf8 string..")), and it would be able to
|
||||
correctly convert the multi-byte characters to unicode. It's *highly* recommended that
|
||||
you use UTF-8 with escape characters in your source code to represent extended characters,
|
||||
because there's no other way to represent these strings in a way that isn't dependent on
|
||||
|
|
@ -2116,9 +2120,9 @@ public:
|
|||
template <class CharPointerType>
|
||||
struct TestUTFConversion
|
||||
{
|
||||
static void test (UnitTest& test)
|
||||
static void test (UnitTest& test, Random& r)
|
||||
{
|
||||
String s (createRandomWideCharString());
|
||||
String s (createRandomWideCharString (r));
|
||||
|
||||
typename CharPointerType::CharType buffer [300];
|
||||
|
||||
|
|
@ -2138,10 +2142,9 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
static String createRandomWideCharString()
|
||||
static String createRandomWideCharString (Random& r)
|
||||
{
|
||||
juce_wchar buffer[50] = { 0 };
|
||||
Random r;
|
||||
|
||||
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
|
||||
{
|
||||
|
|
@ -2162,6 +2165,8 @@ public:
|
|||
|
||||
void runTest()
|
||||
{
|
||||
Random r = getRandom();
|
||||
|
||||
{
|
||||
beginTest ("Basics");
|
||||
|
||||
|
|
@ -2402,9 +2407,9 @@ public:
|
|||
{
|
||||
beginTest ("UTF conversions");
|
||||
|
||||
TestUTFConversion <CharPointer_UTF32>::test (*this);
|
||||
TestUTFConversion <CharPointer_UTF8>::test (*this);
|
||||
TestUTFConversion <CharPointer_UTF16>::test (*this);
|
||||
TestUTFConversion <CharPointer_UTF32>::test (*this, r);
|
||||
TestUTFConversion <CharPointer_UTF8>::test (*this, r);
|
||||
TestUTFConversion <CharPointer_UTF16>::test (*this, r);
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -86,6 +86,9 @@ public:
|
|||
*/
|
||||
StringRef (const String& string) noexcept;
|
||||
|
||||
/** Creates a StringRef pointer to an empty string. */
|
||||
StringRef() noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a raw pointer to the underlying string data. */
|
||||
operator const String::CharPointerType::CharType*() const noexcept { return text.getAddress(); }
|
||||
|
|
|
|||
|
|
@ -191,10 +191,9 @@ class DiffTests : public UnitTest
|
|||
public:
|
||||
DiffTests() : UnitTest ("TextDiff class") {}
|
||||
|
||||
static String createString()
|
||||
static String createString (Random& r)
|
||||
{
|
||||
juce_wchar buffer[50] = { 0 };
|
||||
Random r;
|
||||
|
||||
for (int i = r.nextInt (49); --i >= 0;)
|
||||
{
|
||||
|
|
@ -224,6 +223,8 @@ public:
|
|||
{
|
||||
beginTest ("TextDiff");
|
||||
|
||||
Random r = getRandom();
|
||||
|
||||
testDiff (String::empty, String::empty);
|
||||
testDiff ("x", String::empty);
|
||||
testDiff (String::empty, "x");
|
||||
|
|
@ -234,9 +235,9 @@ public:
|
|||
|
||||
for (int i = 5000; --i >= 0;)
|
||||
{
|
||||
String s (createString());
|
||||
testDiff (s, createString());
|
||||
testDiff (s + createString(), s + createString());
|
||||
String s (createString (r));
|
||||
testDiff (s, createString (r));
|
||||
testDiff (s + createString (r), s + createString (r));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
UnitTest::UnitTest (const String& name_)
|
||||
: name (name_), runner (nullptr)
|
||||
UnitTest::UnitTest (const String& nm)
|
||||
: name (nm), runner (nullptr)
|
||||
{
|
||||
getAllTests().add (this);
|
||||
}
|
||||
|
|
@ -46,10 +46,10 @@ Array<UnitTest*>& UnitTest::getAllTests()
|
|||
void UnitTest::initialise() {}
|
||||
void UnitTest::shutdown() {}
|
||||
|
||||
void UnitTest::performTest (UnitTestRunner* const runner_)
|
||||
void UnitTest::performTest (UnitTestRunner* const newRunner)
|
||||
{
|
||||
jassert (runner_ != nullptr);
|
||||
runner = runner_;
|
||||
jassert (newRunner != nullptr);
|
||||
runner = newRunner;
|
||||
|
||||
initialise();
|
||||
runTest();
|
||||
|
|
@ -58,22 +58,39 @@ void UnitTest::performTest (UnitTestRunner* const runner_)
|
|||
|
||||
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()
|
||||
: currentTest (nullptr),
|
||||
|
|
@ -110,11 +127,17 @@ void UnitTestRunner::resultsUpdated()
|
|||
{
|
||||
}
|
||||
|
||||
void UnitTestRunner::runTests (const Array<UnitTest*>& tests)
|
||||
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 (int i = 0; i < tests.size(); ++i)
|
||||
{
|
||||
if (shouldAbortTests())
|
||||
|
|
@ -133,9 +156,9 @@ void UnitTestRunner::runTests (const Array<UnitTest*>& tests)
|
|||
endTest();
|
||||
}
|
||||
|
||||
void UnitTestRunner::runAllTests()
|
||||
void UnitTestRunner::runAllTests (int64 randomSeed)
|
||||
{
|
||||
runTests (UnitTest::getAllTests());
|
||||
runTests (UnitTest::getAllTests(), randomSeed);
|
||||
}
|
||||
|
||||
void UnitTestRunner::logMessage (const String& message)
|
||||
|
|
|
|||
|
|
@ -163,6 +163,22 @@ public:
|
|||
*/
|
||||
void logMessage (const String& message);
|
||||
|
||||
/** Returns a shared RNG that all unit tests should use.
|
||||
If a test needs random numbers, it's important that when an error is found, the
|
||||
exact circumstances can be re-created in order to re-test the problem, by
|
||||
repeating the test with the same random seed value.
|
||||
To make this possible, the UnitTestRunner class creates a master seed value
|
||||
for the run, writes this number to the log, and then this method returns a
|
||||
Random object based on that seed. All tests should only use this method to
|
||||
create any Random objects that they need.
|
||||
|
||||
Note that this method will return an identical object each time it's called
|
||||
for a given run, so if you need several different Random objects, the best
|
||||
way to do that is to call Random::combineSeed() on the result to permute it
|
||||
with a constant value.
|
||||
*/
|
||||
Random getRandom() const;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
const String name;
|
||||
|
|
@ -198,13 +214,19 @@ public:
|
|||
|
||||
The tests are performed in order, and the results are logged. To run all the
|
||||
registered UnitTest objects that exist, use runAllTests().
|
||||
|
||||
If you want to run the tests with a predetermined seed, you can pass that into
|
||||
the randomSeed argument, or pass 0 to have a randomly-generated seed chosen.
|
||||
*/
|
||||
void runTests (const Array<UnitTest*>& tests);
|
||||
void runTests (const Array<UnitTest*>& tests, int64 randomSeed = 0);
|
||||
|
||||
/** Runs all the UnitTest objects that currently exist.
|
||||
This calls runTests() for all the objects listed in UnitTest::getAllTests().
|
||||
|
||||
If you want to run the tests with a predetermined seed, you can pass that into
|
||||
the randomSeed argument, or pass 0 to have a randomly-generated seed chosen.
|
||||
*/
|
||||
void runAllTests();
|
||||
void runAllTests (int64 randomSeed = 0);
|
||||
|
||||
/** Sets a flag to indicate whether an assertion should be triggered if a test fails.
|
||||
This is true by default.
|
||||
|
|
@ -274,6 +296,7 @@ private:
|
|||
String currentSubCategory;
|
||||
OwnedArray <TestResult, CriticalSection> results;
|
||||
bool assertOnFailure, logPasses;
|
||||
Random randomForTest;
|
||||
|
||||
void beginNewTest (UnitTest* test, const String& subCategory);
|
||||
void endTest();
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ public:
|
|||
void runTest()
|
||||
{
|
||||
beginTest ("GZIP");
|
||||
Random rng;
|
||||
Random rng = getRandom();
|
||||
|
||||
for (int i = 100; --i >= 0;)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -221,10 +221,10 @@ MD5::MD5 (CharPointer_UTF8 utf8) noexcept
|
|||
processData (utf8.getAddress(), utf8.sizeInBytes() - 1);
|
||||
}
|
||||
|
||||
MD5 MD5::fromUTF32 (const String& text)
|
||||
MD5 MD5::fromUTF32 (StringRef text)
|
||||
{
|
||||
MD5Generator generator;
|
||||
String::CharPointerType t (text.getCharPointer());
|
||||
String::CharPointerType t (text.text);
|
||||
|
||||
while (! t.isEmpty())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ public:
|
|||
this operation on it. In new code, you shouldn't use this, and are recommended to
|
||||
use the constructor that takes a CharPointer_UTF8 instead.
|
||||
*/
|
||||
static MD5 fromUTF32 (const String&);
|
||||
static MD5 fromUTF32 (StringRef);
|
||||
|
||||
//==============================================================================
|
||||
bool operator== (const MD5&) const noexcept;
|
||||
|
|
|
|||
|
|
@ -1019,11 +1019,10 @@ class ValueTreeTests : public UnitTest
|
|||
public:
|
||||
ValueTreeTests() : UnitTest ("ValueTrees") {}
|
||||
|
||||
static String createRandomIdentifier()
|
||||
static String createRandomIdentifier (Random& r)
|
||||
{
|
||||
char buffer[50] = { 0 };
|
||||
const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-:";
|
||||
Random r;
|
||||
|
||||
for (int i = 1 + r.nextInt (numElementsInArray (buffer) - 2); --i >= 0;)
|
||||
buffer[i] = chars [r.nextInt (sizeof (chars) - 1)];
|
||||
|
|
@ -1031,10 +1030,9 @@ public:
|
|||
return CharPointer_ASCII (buffer);
|
||||
}
|
||||
|
||||
static String createRandomWideCharString()
|
||||
static String createRandomWideCharString (Random& r)
|
||||
{
|
||||
juce_wchar buffer[50] = { 0 };
|
||||
Random r;
|
||||
|
||||
for (int i = r.nextInt (numElementsInArray (buffer) - 1); --i >= 0;)
|
||||
{
|
||||
|
|
@ -1053,20 +1051,19 @@ public:
|
|||
return CharPointer_UTF32 (buffer);
|
||||
}
|
||||
|
||||
static ValueTree createRandomTree (UndoManager* undoManager, int depth)
|
||||
static ValueTree createRandomTree (UndoManager* undoManager, int depth, Random& r)
|
||||
{
|
||||
Random r;
|
||||
ValueTree v (createRandomIdentifier());
|
||||
ValueTree v (createRandomIdentifier (r));
|
||||
|
||||
for (int i = r.nextInt (10); --i >= 0;)
|
||||
{
|
||||
switch (r.nextInt (5))
|
||||
{
|
||||
case 0: v.setProperty (createRandomIdentifier(), createRandomWideCharString(), undoManager); break;
|
||||
case 1: v.setProperty (createRandomIdentifier(), r.nextInt(), undoManager); break;
|
||||
case 2: if (depth < 5) v.addChild (createRandomTree (undoManager, depth + 1), r.nextInt (v.getNumChildren() + 1), undoManager); break;
|
||||
case 3: v.setProperty (createRandomIdentifier(), r.nextBool(), undoManager); break;
|
||||
case 4: v.setProperty (createRandomIdentifier(), r.nextDouble(), undoManager); break;
|
||||
case 0: v.setProperty (createRandomIdentifier (r), createRandomWideCharString (r), undoManager); break;
|
||||
case 1: v.setProperty (createRandomIdentifier (r), r.nextInt(), undoManager); break;
|
||||
case 2: if (depth < 5) v.addChild (createRandomTree (undoManager, depth + 1, r), r.nextInt (v.getNumChildren() + 1), undoManager); break;
|
||||
case 3: v.setProperty (createRandomIdentifier (r), r.nextBool(), undoManager); break;
|
||||
case 4: v.setProperty (createRandomIdentifier (r), r.nextDouble(), undoManager); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1077,11 +1074,12 @@ public:
|
|||
void runTest()
|
||||
{
|
||||
beginTest ("ValueTree");
|
||||
Random r = getRandom();
|
||||
|
||||
for (int i = 10; --i >= 0;)
|
||||
{
|
||||
MemoryOutputStream mo;
|
||||
ValueTree v1 (createRandomTree (nullptr, 0));
|
||||
ValueTree v1 (createRandomTree (nullptr, 0, r));
|
||||
v1.writeToStream (mo);
|
||||
|
||||
MemoryInputStream mi (mo.getData(), mo.getDataSize(), false);
|
||||
|
|
|
|||
|
|
@ -1475,12 +1475,12 @@ String Path::toString() const
|
|||
return s.toUTF8();
|
||||
}
|
||||
|
||||
void Path::restoreFromString (const String& stringVersion)
|
||||
void Path::restoreFromString (StringRef stringVersion)
|
||||
{
|
||||
clear();
|
||||
setUsingNonZeroWinding (true);
|
||||
|
||||
String::CharPointerType t (stringVersion.getCharPointer());
|
||||
String::CharPointerType t (stringVersion.text);
|
||||
juce_wchar marker = 'm';
|
||||
int numValues = 2;
|
||||
float values [6];
|
||||
|
|
|
|||
|
|
@ -740,7 +740,7 @@ public:
|
|||
/** Restores this path from a string that was created with the toString() method.
|
||||
@see toString()
|
||||
*/
|
||||
void restoreFromString (const String& stringVersion);
|
||||
void restoreFromString (StringRef stringVersion);
|
||||
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -25,20 +25,21 @@
|
|||
class CodeDocumentLine
|
||||
{
|
||||
public:
|
||||
CodeDocumentLine (const String::CharPointerType l,
|
||||
CodeDocumentLine (const String::CharPointerType startOfLine,
|
||||
const String::CharPointerType endOfLine,
|
||||
const int lineLen,
|
||||
const int numNewLineChars,
|
||||
const int startInFile)
|
||||
: line (l, (size_t) lineLen),
|
||||
: line (startOfLine, endOfLine),
|
||||
lineStartInFile (startInFile),
|
||||
lineLength (lineLen),
|
||||
lineLengthWithoutNewLines (lineLen - numNewLineChars)
|
||||
{
|
||||
}
|
||||
|
||||
static void createLines (Array <CodeDocumentLine*>& newLines, const String& text)
|
||||
static void createLines (Array<CodeDocumentLine*>& newLines, StringRef text)
|
||||
{
|
||||
String::CharPointerType t (text.getCharPointer());
|
||||
String::CharPointerType t (text.text);
|
||||
int charNumInFile = 0;
|
||||
bool finished = false;
|
||||
|
||||
|
|
@ -84,7 +85,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
newLines.add (new CodeDocumentLine (startOfLine, lineLength,
|
||||
newLines.add (new CodeDocumentLine (startOfLine, t, lineLength,
|
||||
numNewLineChars, startOfLineInFile));
|
||||
}
|
||||
|
||||
|
|
@ -791,7 +792,8 @@ void CodeDocument::checkLastLineStatus()
|
|||
if (lastLine != nullptr && lastLine->endsWithLineBreak())
|
||||
{
|
||||
// check that there's an empty line at the end if the preceding one ends in a newline..
|
||||
lines.add (new CodeDocumentLine (String::empty.getCharPointer(), 0, 0, lastLine->lineStartInFile + lastLine->lineLength));
|
||||
lines.add (new CodeDocumentLine (StringRef(), StringRef(), 0, 0,
|
||||
lastLine->lineStartInFile + lastLine->lineLength));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -227,9 +227,9 @@ private:
|
|||
|
||||
namespace CodeEditorHelpers
|
||||
{
|
||||
static int findFirstNonWhitespaceChar (const String& line) noexcept
|
||||
static int findFirstNonWhitespaceChar (StringRef line) noexcept
|
||||
{
|
||||
String::CharPointerType t (line.getCharPointer());
|
||||
String::CharPointerType t (line.text);
|
||||
int i = 0;
|
||||
|
||||
while (! t.isEmpty())
|
||||
|
|
@ -1418,7 +1418,8 @@ String CodeEditorComponent::getTabString (const int numSpaces) const
|
|||
|
||||
int CodeEditorComponent::indexToColumn (int lineNum, int index) const noexcept
|
||||
{
|
||||
String::CharPointerType t (document.getLine (lineNum).getCharPointer());
|
||||
const String line (document.getLine (lineNum));
|
||||
String::CharPointerType t (line.getCharPointer());
|
||||
|
||||
int col = 0;
|
||||
for (int i = 0; i < index; ++i)
|
||||
|
|
@ -1440,7 +1441,8 @@ int CodeEditorComponent::indexToColumn (int lineNum, int index) const noexcept
|
|||
|
||||
int CodeEditorComponent::columnToIndex (int lineNum, int column) const noexcept
|
||||
{
|
||||
String::CharPointerType t (document.getLine (lineNum).getCharPointer());
|
||||
const String line (document.getLine (lineNum));
|
||||
String::CharPointerType t (line.getCharPointer());
|
||||
|
||||
int i = 0, col = 0;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue