Initial commit
This commit is contained in:
1
test/.gitignore
vendored
Normal file
1
test/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/engine-data
|
||||
5
test/README
Normal file
5
test/README
Normal file
@@ -0,0 +1,5 @@
|
||||
This directory contains some unit tests for ScummVM. They are based on
|
||||
CxxTest <http://cxxtest.com/>, which you can find in the cxxtest
|
||||
subdirectory, including its manual.
|
||||
|
||||
To run the unit tests, simply use "make test".
|
||||
208
test/audio/audiostream.h
Normal file
208
test/audio/audiostream.h
Normal file
@@ -0,0 +1,208 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "audio/audiostream.h"
|
||||
|
||||
#include "helper.h"
|
||||
|
||||
class AudioStreamTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_convertTimeToStreamPos() {
|
||||
const Audio::Timestamp a = Audio::convertTimeToStreamPos(Audio::Timestamp(500, 1000), 11025, true);
|
||||
// The last bit has to be 0 in any case for a stereo stream.
|
||||
TS_ASSERT_EQUALS(a.totalNumberOfFrames() & 1, 0);
|
||||
|
||||
// TODO: This test is rather hacky... actually converTimeToStreamPos might also return 11026
|
||||
// instead of 11024 and it would still be a valid sample position for ~500ms.
|
||||
TS_ASSERT_EQUALS(a.totalNumberOfFrames(), 11024);
|
||||
|
||||
const Audio::Timestamp b = Audio::convertTimeToStreamPos(Audio::Timestamp(500, 1000), 11025, false);
|
||||
TS_ASSERT_EQUALS(b.totalNumberOfFrames(), 500 * 11025 / 1000);
|
||||
|
||||
// Test Audio CD positioning
|
||||
|
||||
// for 44kHz and stereo
|
||||
const Audio::Timestamp c = Audio::convertTimeToStreamPos(Audio::Timestamp(0, 50, 75), 44100, true);
|
||||
TS_ASSERT_EQUALS(c.totalNumberOfFrames(), 50 * 44100 * 2 / 75);
|
||||
|
||||
// for 11kHz and mono
|
||||
const Audio::Timestamp d = Audio::convertTimeToStreamPos(Audio::Timestamp(0, 50, 75), 11025, false);
|
||||
TS_ASSERT_EQUALS(d.totalNumberOfFrames(), 50 * 11025 / 75);
|
||||
|
||||
// Some misc test
|
||||
const Audio::Timestamp e = Audio::convertTimeToStreamPos(Audio::Timestamp(1, 1, 4), 11025, false);
|
||||
TS_ASSERT_EQUALS(e.totalNumberOfFrames(), 5 * 11025 / 4);
|
||||
}
|
||||
|
||||
private:
|
||||
void testLoopingAudioStreamFixedIter(const int sampleRate, const bool isStereo) {
|
||||
const int secondLength = sampleRate * (isStereo ? 2 : 1);
|
||||
|
||||
int16 *sine = 0;
|
||||
Audio::SeekableAudioStream *s = createSineStream<int16>(sampleRate, 1, &sine, false, isStereo);
|
||||
Audio::LoopingAudioStream *loop = new Audio::LoopingAudioStream(s, 7);
|
||||
|
||||
int16 *buffer = new int16[secondLength * 3];
|
||||
|
||||
// Check parameters
|
||||
TS_ASSERT_EQUALS(loop->isStereo(), isStereo);
|
||||
TS_ASSERT_EQUALS(loop->getRate(), sampleRate);
|
||||
TS_ASSERT_EQUALS(loop->endOfData(), false);
|
||||
TS_ASSERT_EQUALS(loop->getCompleteIterations(), (uint)0);
|
||||
|
||||
// Read one second
|
||||
TS_ASSERT_EQUALS(loop->readBuffer(buffer, secondLength), secondLength);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer, sine, secondLength * sizeof(int16)), 0);
|
||||
|
||||
TS_ASSERT_EQUALS(loop->getCompleteIterations(), (uint)1);
|
||||
TS_ASSERT_EQUALS(loop->endOfData(), false);
|
||||
|
||||
// Read two seconds
|
||||
TS_ASSERT_EQUALS(loop->readBuffer(buffer, secondLength * 2), secondLength * 2);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer, sine, secondLength * sizeof(int16)), 0);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer + secondLength, sine, secondLength * sizeof(int16)), 0);
|
||||
|
||||
TS_ASSERT_EQUALS(loop->getCompleteIterations(), (uint)3);
|
||||
TS_ASSERT_EQUALS(loop->endOfData(), false);
|
||||
|
||||
// Read three seconds
|
||||
TS_ASSERT_EQUALS(loop->readBuffer(buffer, secondLength * 3), secondLength * 3);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer, sine, secondLength * sizeof(int16)), 0);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer + secondLength, sine, secondLength * sizeof(int16)), 0);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer + secondLength * 2, sine, secondLength * sizeof(int16)), 0);
|
||||
|
||||
TS_ASSERT_EQUALS(loop->getCompleteIterations(), (uint)6);
|
||||
TS_ASSERT_EQUALS(loop->endOfData(), false);
|
||||
|
||||
// Read the last second in two parts
|
||||
const int firstStep = secondLength / 2;
|
||||
const int secondStep = secondLength - firstStep;
|
||||
|
||||
TS_ASSERT_EQUALS(loop->readBuffer(buffer, firstStep), firstStep);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer, sine, firstStep * sizeof(int16)), 0);
|
||||
|
||||
TS_ASSERT_EQUALS(loop->getCompleteIterations(), (uint)6);
|
||||
TS_ASSERT_EQUALS(loop->endOfData(), false);
|
||||
|
||||
TS_ASSERT_EQUALS(loop->readBuffer(buffer, secondLength), secondStep);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer, sine + firstStep, secondStep * sizeof(int16)), 0);
|
||||
|
||||
TS_ASSERT_EQUALS(loop->getCompleteIterations(), (uint)7);
|
||||
TS_ASSERT_EQUALS(loop->endOfData(), true);
|
||||
|
||||
// Try to read beyond the end of the stream
|
||||
TS_ASSERT_EQUALS(loop->readBuffer(buffer, secondLength), 0);
|
||||
TS_ASSERT_EQUALS(loop->getCompleteIterations(), (uint)7);
|
||||
TS_ASSERT_EQUALS(loop->endOfData(), true);
|
||||
|
||||
delete[] buffer;
|
||||
delete loop;
|
||||
delete[] sine;
|
||||
}
|
||||
|
||||
public:
|
||||
void test_looping_audio_stream_mono_11025_fixed_iter() {
|
||||
testLoopingAudioStreamFixedIter(11025, false);
|
||||
}
|
||||
|
||||
void test_looping_audio_stream_mono_22050_fixed_iter() {
|
||||
testLoopingAudioStreamFixedIter(22050, false);
|
||||
}
|
||||
|
||||
void test_looping_audio_stream_stereo_11025_fixed_iter() {
|
||||
testLoopingAudioStreamFixedIter(11025, true);
|
||||
}
|
||||
|
||||
void test_looping_audio_stream_stereo_22050_fixed_iter() {
|
||||
testLoopingAudioStreamFixedIter(22050, true);
|
||||
}
|
||||
|
||||
private:
|
||||
void testSubLoopingAudioStreamFixedIter(const int sampleRate, const bool isStereo, const int time, const int loopEndTime) {
|
||||
const int secondLength = sampleRate * (isStereo ? 2 : 1);
|
||||
|
||||
const Audio::Timestamp loopStart(500, 1000), loopEnd(loopEndTime * 1000, 1000);
|
||||
|
||||
const int32 loopStartPos = Audio::convertTimeToStreamPos(loopStart, sampleRate, isStereo).totalNumberOfFrames();
|
||||
const int32 loopEndPos = Audio::convertTimeToStreamPos(loopEnd, sampleRate, isStereo).totalNumberOfFrames();
|
||||
|
||||
const int32 loopIteration = loopEndPos - loopStartPos;
|
||||
|
||||
int16 *sine = 0;
|
||||
Audio::SeekableAudioStream *s = createSineStream<int16>(sampleRate, time, &sine, false, isStereo);
|
||||
Audio::SubLoopingAudioStream *loop = new Audio::SubLoopingAudioStream(s, 5, loopStart, loopEnd);
|
||||
|
||||
const int32 bufferLen = MAX<int32>(loopIteration * 3, loopEndPos);
|
||||
int16 *buffer = new int16[bufferLen];
|
||||
|
||||
// Check parameters
|
||||
TS_ASSERT_EQUALS(loop->isStereo(), isStereo);
|
||||
TS_ASSERT_EQUALS(loop->getRate(), sampleRate);
|
||||
TS_ASSERT_EQUALS(loop->endOfData(), false);
|
||||
|
||||
// Read the non-looped part + one iteration
|
||||
TS_ASSERT_EQUALS(loop->readBuffer(buffer, loopEndPos), loopEndPos);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer, sine, loopEndPos * sizeof(int16)), 0);
|
||||
TS_ASSERT_EQUALS(loop->endOfData(), false);
|
||||
|
||||
// We should have one full iteration now
|
||||
|
||||
// Read another loop iteration
|
||||
TS_ASSERT_EQUALS(loop->readBuffer(buffer, loopIteration), loopIteration);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer, sine + loopStartPos, loopIteration * sizeof(int16)), 0);
|
||||
TS_ASSERT_EQUALS(loop->endOfData(), false);
|
||||
|
||||
// We should have two full iterations now
|
||||
|
||||
// Read three loop iterations at once
|
||||
TS_ASSERT_EQUALS(loop->readBuffer(buffer, loopIteration * 3), loopIteration * 3);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer + loopIteration * 0, sine + loopStartPos, loopIteration * sizeof(int16)), 0);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer + loopIteration * 1, sine + loopStartPos, loopIteration * sizeof(int16)), 0);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer + loopIteration * 2, sine + loopStartPos, loopIteration * sizeof(int16)), 0);
|
||||
TS_ASSERT_EQUALS(loop->endOfData(), true);
|
||||
|
||||
// We should have five full iterations now, thus the stream should be done
|
||||
|
||||
// Try to read beyond the end of the stream (note this only applies, till we define that SubLoopingAudioStream should
|
||||
// stop playing after the looped area).
|
||||
TS_ASSERT_EQUALS(loop->readBuffer(buffer, secondLength), 0);
|
||||
TS_ASSERT_EQUALS(loop->endOfData(), true);
|
||||
|
||||
delete[] buffer;
|
||||
delete loop;
|
||||
delete[] sine;
|
||||
}
|
||||
|
||||
public:
|
||||
void test_sub_looping_audio_stream_mono_11025_mid_fixed_iter() {
|
||||
testSubLoopingAudioStreamFixedIter(11025, false, 2, 1);
|
||||
}
|
||||
|
||||
void test_sub_looping_audio_stream_mono_22050_mid_fixed_iter() {
|
||||
testSubLoopingAudioStreamFixedIter(22050, false, 2, 1);
|
||||
}
|
||||
|
||||
void test_sub_looping_audio_stream_stereo_11025_mid_fixed_iter() {
|
||||
testSubLoopingAudioStreamFixedIter(11025, true, 2, 1);
|
||||
}
|
||||
|
||||
void test_sub_looping_audio_stream_stereo_22050_mid_fixed_iter() {
|
||||
testSubLoopingAudioStreamFixedIter(22050, true, 2, 1);
|
||||
}
|
||||
|
||||
void test_sub_looping_audio_stream_mono_11025_end_fixed_iter() {
|
||||
testSubLoopingAudioStreamFixedIter(11025, false, 2, 2);
|
||||
}
|
||||
|
||||
void test_sub_looping_audio_stream_mono_22050_end_fixed_iter() {
|
||||
testSubLoopingAudioStreamFixedIter(22050, false, 2, 2);
|
||||
}
|
||||
|
||||
void test_sub_looping_audio_stream_stereo_11025_end_fixed_iter() {
|
||||
testSubLoopingAudioStreamFixedIter(11025, true, 2, 2);
|
||||
}
|
||||
|
||||
void test_sub_looping_audio_stream_stereo_22050_end_fixed_iter() {
|
||||
testSubLoopingAudioStreamFixedIter(22050, true, 2, 2);
|
||||
}
|
||||
};
|
||||
68
test/audio/helper.h
Normal file
68
test/audio/helper.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef TEST_SOUND_HELPER_H
|
||||
#define TEST_SOUND_HELPER_H
|
||||
|
||||
#include "audio/decoders/raw.h"
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "common/endian.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <limits>
|
||||
|
||||
template<typename T>
|
||||
static T *createSine(const int sampleRate, const int time) {
|
||||
T *sine = (T *)malloc(sizeof(T) * time * sampleRate);
|
||||
|
||||
const bool isUnsigned = !std::numeric_limits<T>::is_signed;
|
||||
const T xorMask = isUnsigned ? (1 << (std::numeric_limits<T>::digits - 1)) : 0;
|
||||
const T maxValue = std::numeric_limits<T>::max() ^ xorMask;
|
||||
|
||||
for (int i = 0; i < time * sampleRate; ++i)
|
||||
sine[i] = ((T)(sin((double)i / sampleRate * 2 * M_PI) * maxValue)) ^ xorMask;
|
||||
|
||||
return sine;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static Audio::SeekableAudioStream *createSineStream(const int sampleRate, const int time, int16 **comp, bool le, bool isStereo) {
|
||||
T *sine = createSine<T>(sampleRate, time * (isStereo ? 2 : 1));
|
||||
|
||||
const bool isUnsigned = !std::numeric_limits<T>::is_signed;
|
||||
const T xorMask = isUnsigned ? (1 << (std::numeric_limits<T>::digits - 1)) : 0;
|
||||
const bool is16Bits = (sizeof(T) == 2);
|
||||
assert(sizeof(T) == 2 || sizeof(T) == 1);
|
||||
|
||||
const int samples = sampleRate * time * (isStereo ? 2 : 1);
|
||||
|
||||
if (comp) {
|
||||
*comp = new int16[samples];
|
||||
for (int i = 0; i < samples; ++i) {
|
||||
if (is16Bits)
|
||||
(*comp)[i] = sine[i] ^ xorMask;
|
||||
else
|
||||
(*comp)[i] = (sine[i] ^ xorMask) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (is16Bits) {
|
||||
if (le) {
|
||||
for (int i = 0; i < samples; ++i)
|
||||
WRITE_LE_UINT16(&sine[i], sine[i]);
|
||||
} else {
|
||||
for (int i = 0; i < samples; ++i)
|
||||
WRITE_BE_UINT16(&sine[i], sine[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Audio::SeekableAudioStream *s = 0;
|
||||
Common::SeekableReadStream *sD = new Common::MemoryReadStream((const byte *)sine, sizeof(T) * samples, DisposeAfterUse::YES);
|
||||
s = Audio::makeRawStream(sD, sampleRate,
|
||||
(is16Bits ? Audio::FLAG_16BITS : 0)
|
||||
| (isUnsigned ? Audio::FLAG_UNSIGNED : 0)
|
||||
| (le ? Audio::FLAG_LITTLE_ENDIAN : 0)
|
||||
| (isStereo ? Audio::FLAG_STEREO : 0));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif
|
||||
291
test/audio/raw.h
Normal file
291
test/audio/raw.h
Normal file
@@ -0,0 +1,291 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "audio/decoders/raw.h"
|
||||
#include "audio/audiostream.h"
|
||||
|
||||
#include "helper.h"
|
||||
|
||||
class RawStreamTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
void readBufferTestTemplate(const int sampleRate, const int time, const bool le, const bool isStereo) {
|
||||
int16 *sine;
|
||||
Audio::SeekableAudioStream *s = createSineStream<int8>(sampleRate, time, &sine, le, isStereo);
|
||||
|
||||
const int totalSamples = sampleRate * time * (isStereo ? 2 : 1);
|
||||
int16 *buffer = new int16[totalSamples];
|
||||
TS_ASSERT_EQUALS(s->readBuffer(buffer, totalSamples), totalSamples);
|
||||
TS_ASSERT_EQUALS(memcmp(sine, buffer, sizeof(int16) * totalSamples), 0);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), true);
|
||||
|
||||
delete[] sine;
|
||||
delete[] buffer;
|
||||
delete s;
|
||||
}
|
||||
|
||||
public:
|
||||
void test_read_buffer_8_bit_signed_mono() {
|
||||
readBufferTestTemplate<int8>(11025, 2, false, false);
|
||||
}
|
||||
|
||||
void test_read_buffer_8_bit_signed_stereo() {
|
||||
readBufferTestTemplate<int8>(11025, 2, false, true);
|
||||
}
|
||||
|
||||
void test_read_buffer_8_bit_unsigned_mono() {
|
||||
readBufferTestTemplate<uint8>(11025, 2, false, false);
|
||||
}
|
||||
|
||||
void test_read_buffer_16_bit_signed_be_mono() {
|
||||
readBufferTestTemplate<int16>(11025, 2, false, false);
|
||||
}
|
||||
|
||||
void test_read_buffer_16_bit_signed_be_stereo() {
|
||||
readBufferTestTemplate<int16>(11025, 2, false, true);
|
||||
}
|
||||
|
||||
void test_read_buffer_16_bit_unsigned_be_mono() {
|
||||
readBufferTestTemplate<uint16>(11025, 2, false, false);
|
||||
}
|
||||
|
||||
void test_read_buffer_16_bit_unsigned_be_stereo() {
|
||||
readBufferTestTemplate<uint16>(11025, 2, false, true);
|
||||
}
|
||||
|
||||
void test_read_buffer_16_bit_signed_le_mono() {
|
||||
readBufferTestTemplate<int16>(11025, 2, true, false);
|
||||
}
|
||||
|
||||
void test_read_buffer_16_bit_signed_le_stereo() {
|
||||
readBufferTestTemplate<int16>(11025, 2, true, true);
|
||||
}
|
||||
|
||||
void test_read_buffer_16_bit_unsigned_le_mono() {
|
||||
readBufferTestTemplate<uint16>(11025, 2, true, false);
|
||||
}
|
||||
|
||||
void test_read_buffer_16_bit_unsigned_le_stereo() {
|
||||
readBufferTestTemplate<uint16>(11025, 2, true, true);
|
||||
}
|
||||
|
||||
private:
|
||||
void partialReadTest() {
|
||||
const int sampleRate = 11025;
|
||||
const int time = 4;
|
||||
|
||||
int16 *sine;
|
||||
Audio::SeekableAudioStream *s = createSineStream<int8>(sampleRate, time, &sine, false, false);
|
||||
int16 *buffer = new int16[sampleRate * time];
|
||||
|
||||
TS_ASSERT_EQUALS(s->readBuffer(buffer, sampleRate), sampleRate);
|
||||
TS_ASSERT_EQUALS(memcmp(sine, buffer, sampleRate), 0);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), false);
|
||||
|
||||
TS_ASSERT_EQUALS(s->readBuffer(buffer, sampleRate * 2), sampleRate * 2);
|
||||
TS_ASSERT_EQUALS(memcmp(sine + sampleRate, buffer, sampleRate * 2), 0);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), false);
|
||||
|
||||
TS_ASSERT_EQUALS(s->readBuffer(buffer, sampleRate), sampleRate);
|
||||
TS_ASSERT_EQUALS(memcmp(sine + sampleRate * 3, buffer, sampleRate), 0);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), true);
|
||||
|
||||
delete[] sine;
|
||||
delete[] buffer;
|
||||
delete s;
|
||||
}
|
||||
public:
|
||||
void test_partial_read() {
|
||||
partialReadTest();
|
||||
}
|
||||
|
||||
private:
|
||||
void readAfterEndTest() {
|
||||
const int sampleRate = 11025;
|
||||
const int time = 1;
|
||||
Audio::SeekableAudioStream *s = createSineStream<int8>(sampleRate, time, 0, false, false);
|
||||
int16 *buffer = new int16[sampleRate * time];
|
||||
|
||||
TS_ASSERT_EQUALS(s->readBuffer(buffer, sampleRate * time), sampleRate * time);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), true);
|
||||
|
||||
TS_ASSERT_EQUALS(s->readBuffer(buffer, sampleRate * time), 0);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), true);
|
||||
|
||||
delete[] buffer;
|
||||
delete s;
|
||||
}
|
||||
|
||||
public:
|
||||
void test_read_after_end() {
|
||||
readAfterEndTest();
|
||||
}
|
||||
|
||||
private:
|
||||
void rewindTest() {
|
||||
const int sampleRate = 11025;
|
||||
const int time = 2;
|
||||
Audio::SeekableAudioStream *s = createSineStream<int8>(sampleRate, time, 0, false, false);
|
||||
int16 *buffer = new int16[sampleRate * time];
|
||||
|
||||
TS_ASSERT_EQUALS(s->readBuffer(buffer, sampleRate * time), sampleRate * time);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), true);
|
||||
|
||||
s->rewind();
|
||||
TS_ASSERT_EQUALS(s->endOfData(), false);
|
||||
|
||||
TS_ASSERT_EQUALS(s->readBuffer(buffer, sampleRate * time), sampleRate * time);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), true);
|
||||
|
||||
delete[] buffer;
|
||||
delete s;
|
||||
}
|
||||
public:
|
||||
void test_rewind() {
|
||||
rewindTest();
|
||||
}
|
||||
|
||||
private:
|
||||
void lengthTest() {
|
||||
int sampleRate = 0;
|
||||
const int time = 4;
|
||||
|
||||
Audio::SeekableAudioStream *s = 0;
|
||||
|
||||
// 11025 Hz tests
|
||||
sampleRate = 11025;
|
||||
s = createSineStream<int8>(sampleRate, time, 0, false, false);
|
||||
TS_ASSERT_EQUALS(s->getLength().totalNumberOfFrames(), sampleRate * time);
|
||||
delete s;
|
||||
|
||||
s = createSineStream<uint16>(sampleRate, time, 0, false, false);
|
||||
TS_ASSERT_EQUALS(s->getLength().totalNumberOfFrames(), sampleRate * time);
|
||||
delete s;
|
||||
|
||||
// 48000 Hz tests
|
||||
sampleRate = 48000;
|
||||
s = createSineStream<int8>(sampleRate, time, 0, false, false);
|
||||
TS_ASSERT_EQUALS(s->getLength().totalNumberOfFrames(), sampleRate * time);
|
||||
delete s;
|
||||
|
||||
s = createSineStream<uint16>(sampleRate, time, 0, true, false);
|
||||
TS_ASSERT_EQUALS(s->getLength().totalNumberOfFrames(), sampleRate * time);
|
||||
delete s;
|
||||
|
||||
// 11840 Hz tests
|
||||
sampleRate = 11840;
|
||||
s = createSineStream<int8>(sampleRate, time, 0, false, false);
|
||||
TS_ASSERT_EQUALS(s->getLength().totalNumberOfFrames(), sampleRate * time);
|
||||
delete s;
|
||||
|
||||
s = createSineStream<uint16>(sampleRate, time, 0, false, false);
|
||||
TS_ASSERT_EQUALS(s->getLength().totalNumberOfFrames(), sampleRate * time);
|
||||
delete s;
|
||||
|
||||
// 11111 Hz tests
|
||||
sampleRate = 11111;
|
||||
s = createSineStream<int8>(sampleRate, time, 0, false, false);
|
||||
TS_ASSERT_EQUALS(s->getLength().totalNumberOfFrames(), sampleRate * time);
|
||||
delete s;
|
||||
|
||||
s = createSineStream<uint16>(sampleRate, time, 0, false, false);
|
||||
TS_ASSERT_EQUALS(s->getLength().totalNumberOfFrames(), sampleRate * time);
|
||||
delete s;
|
||||
|
||||
// 22050 Hz stereo test
|
||||
sampleRate = 22050;
|
||||
s = createSineStream<int8>(sampleRate, time, 0, false, true);
|
||||
TS_ASSERT_EQUALS(s->getLength().totalNumberOfFrames(), sampleRate * time);
|
||||
delete s;
|
||||
|
||||
s = createSineStream<uint16>(sampleRate, time, 0, true, true);
|
||||
TS_ASSERT_EQUALS(s->getLength().totalNumberOfFrames(), sampleRate * time);
|
||||
delete s;
|
||||
}
|
||||
|
||||
public:
|
||||
void test_length() {
|
||||
lengthTest();
|
||||
}
|
||||
|
||||
private:
|
||||
void seekTest(const int sampleRate, const int time, const bool isStereo) {
|
||||
const int totalFrames = sampleRate * time * (isStereo ? 2 : 1);
|
||||
int readData = 0, offset = 0;
|
||||
|
||||
int16 *buffer = new int16[totalFrames];
|
||||
Audio::SeekableAudioStream *s = 0;
|
||||
int16 *sine = 0;
|
||||
|
||||
s = createSineStream<int8>(sampleRate, time, &sine, false, isStereo);
|
||||
|
||||
// Seek to 500ms
|
||||
const Audio::Timestamp a(0, 1, 2);
|
||||
offset = Audio::convertTimeToStreamPos(a, sampleRate, isStereo).totalNumberOfFrames();
|
||||
readData = totalFrames - offset;
|
||||
|
||||
TS_ASSERT_EQUALS(s->seek(a), true);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), false);
|
||||
TS_ASSERT_EQUALS(s->readBuffer(buffer, readData), readData);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer, sine + offset, readData * sizeof(int16)), 0);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), true);
|
||||
|
||||
// Seek to 3/4 of a second
|
||||
const Audio::Timestamp b(0, 3, 4);
|
||||
offset = Audio::convertTimeToStreamPos(b, sampleRate, isStereo).totalNumberOfFrames();
|
||||
readData = totalFrames - offset;
|
||||
|
||||
TS_ASSERT_EQUALS(s->seek(b), true);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), false);
|
||||
TS_ASSERT_EQUALS(s->readBuffer(buffer, readData), readData);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer, sine + offset, readData * sizeof(int16)), 0);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), true);
|
||||
|
||||
// Seek to the start of the stream
|
||||
TS_ASSERT_EQUALS(s->seek(0), true);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), false);
|
||||
|
||||
// Seek to the mid of the stream
|
||||
const Audio::Timestamp c(time * 1000 / 2, 1000);
|
||||
offset = Audio::convertTimeToStreamPos(c, sampleRate, isStereo).totalNumberOfFrames();
|
||||
readData = totalFrames - offset;
|
||||
|
||||
TS_ASSERT_EQUALS(s->seek(c), true);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), false);
|
||||
TS_ASSERT_EQUALS(s->readBuffer(buffer, readData), readData);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer, sine + offset, readData * sizeof(int16)), 0);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), true);
|
||||
|
||||
// Seek to the 1/4th of the last second of the stream
|
||||
const Audio::Timestamp d(time - 1, 1, 4);
|
||||
offset = Audio::convertTimeToStreamPos(d, sampleRate, isStereo).totalNumberOfFrames();
|
||||
readData = totalFrames - offset;
|
||||
|
||||
TS_ASSERT_EQUALS(s->seek(d), true);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), false);
|
||||
TS_ASSERT_EQUALS(s->readBuffer(buffer, readData), readData);
|
||||
TS_ASSERT_EQUALS(memcmp(buffer, sine + offset, readData * sizeof(int16)), 0);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), true);
|
||||
|
||||
// Try to seek after the end of the stream
|
||||
TS_ASSERT_EQUALS(s->seek(Audio::Timestamp(time, 1, 100000)), false);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), true);
|
||||
|
||||
// Try to seek exactly at the end of the stream
|
||||
TS_ASSERT_EQUALS(s->seek(Audio::Timestamp(time * 1000, 1000)), true);
|
||||
TS_ASSERT_EQUALS(s->endOfData(), true);
|
||||
|
||||
delete[] sine;
|
||||
delete s;
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
public:
|
||||
void test_seek_mono() {
|
||||
seekTest(11025, 2, false);
|
||||
}
|
||||
|
||||
void test_seek_stereo() {
|
||||
seekTest(11025, 2, true);
|
||||
}
|
||||
};
|
||||
252
test/audio/timestamp.h
Normal file
252
test/audio/timestamp.h
Normal file
@@ -0,0 +1,252 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "audio/timestamp.h"
|
||||
|
||||
class TimestampTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_diff_add_frames() {
|
||||
const Audio::Timestamp a(10000, 1000);
|
||||
const Audio::Timestamp b(10001, 1000);
|
||||
const Audio::Timestamp c(10002, 1000);
|
||||
|
||||
TS_ASSERT_EQUALS(a.frameDiff(b), -1);
|
||||
TS_ASSERT_EQUALS(b.frameDiff(a), 1);
|
||||
TS_ASSERT_EQUALS(c.frameDiff(a), 2);
|
||||
TS_ASSERT_EQUALS(b.addFrames(2000).frameDiff(a), 2001);
|
||||
TS_ASSERT_EQUALS(a.frameDiff(b), -1);
|
||||
TS_ASSERT_EQUALS(b.frameDiff(a), 1);
|
||||
TS_ASSERT_EQUALS(c.frameDiff(a), 2);
|
||||
TS_ASSERT_EQUALS(b.addFrames(2000).frameDiff(a.addFrames(-1000)), 3001);
|
||||
TS_ASSERT_EQUALS(a.frameDiff(b), -1);
|
||||
TS_ASSERT_EQUALS(b.frameDiff(a), 1);
|
||||
TS_ASSERT_EQUALS(c.frameDiff(a), 2);
|
||||
}
|
||||
|
||||
void test_diff_add_msecs() {
|
||||
Audio::Timestamp ts0(3, 22050);
|
||||
Audio::Timestamp ts1(0, 22050);
|
||||
Audio::Timestamp ts2(0, 22050);
|
||||
|
||||
TS_ASSERT_EQUALS(ts0.msecs(), 3);
|
||||
TS_ASSERT_EQUALS(ts0.totalNumberOfFrames(), 3 * 22050 / 1000);
|
||||
TS_ASSERT_EQUALS(ts0.numberOfFrames(), 3 * 22050 / 1000);
|
||||
|
||||
ts1 = ts1.addFrames(53248);
|
||||
TS_ASSERT_EQUALS(ts1.secs(), 2);
|
||||
TS_ASSERT_EQUALS(ts1.msecs(), 53248 * 1000 / 22050);
|
||||
TS_ASSERT_EQUALS(ts1.totalNumberOfFrames(), 53248);
|
||||
TS_ASSERT_EQUALS(ts1.numberOfFrames(), 53248 - 2 * 22050);
|
||||
ts1 = ts1.addMsecs(47);
|
||||
TS_ASSERT_EQUALS(ts1.secs(), 2);
|
||||
TS_ASSERT_EQUALS(ts1.msecs(), 2414+47);
|
||||
TS_ASSERT_EQUALS(ts1.totalNumberOfFrames(), 47*22050 / 1000 + 53248);
|
||||
TS_ASSERT_EQUALS(ts1.numberOfFrames(), 47*22050 / 1000 + 53248 - 2 * 22050);
|
||||
|
||||
ts2 = ts2.addMsecs(47);
|
||||
TS_ASSERT_EQUALS(ts2.secs(), 0);
|
||||
TS_ASSERT_EQUALS(ts2.msecs(), 47);
|
||||
TS_ASSERT_EQUALS(ts2.totalNumberOfFrames(), 47*22050 / 1000);
|
||||
TS_ASSERT_EQUALS(ts2.numberOfFrames(), 47*22050 / 1000);
|
||||
ts2 = ts2.addFrames(53248);
|
||||
TS_ASSERT_EQUALS(ts2.secs(), 2);
|
||||
TS_ASSERT_EQUALS(ts2.msecs(), 2414+47);
|
||||
TS_ASSERT_EQUALS(ts2.totalNumberOfFrames(), 47*22050 / 1000 + 53248);
|
||||
TS_ASSERT_EQUALS(ts2.numberOfFrames(), 47*22050 / 1000 + 53248 - 2 * 22050);
|
||||
}
|
||||
|
||||
void test_ticks() {
|
||||
const Audio::Timestamp a(1234, 60);
|
||||
const Audio::Timestamp b(5678, 60);
|
||||
|
||||
TS_ASSERT_EQUALS(a.msecs(), 1234);
|
||||
TS_ASSERT_EQUALS(b.msecs(), 5678);
|
||||
|
||||
TS_ASSERT_EQUALS(a.secs(), 1);
|
||||
TS_ASSERT_EQUALS(b.secs(), 5);
|
||||
|
||||
TS_ASSERT_EQUALS(a.msecsDiff(b), 1234 - 5678);
|
||||
TS_ASSERT_EQUALS(b.msecsDiff(a), 5678 - 1234);
|
||||
|
||||
TS_ASSERT_EQUALS(a.frameDiff(b), (1234 - 5678) * 60 / 1000);
|
||||
TS_ASSERT_EQUALS(b.frameDiff(a), (5678 - 1234) * 60 / 1000);
|
||||
|
||||
TS_ASSERT_EQUALS(a.addFrames(1).msecs(), (1234 + 1000 * 1/60));
|
||||
TS_ASSERT_EQUALS(a.addFrames(59).msecs(), (1234 + 1000 * 59/60));
|
||||
TS_ASSERT_EQUALS(a.addFrames(60).msecs(), (1234 + 1000 * 60/60));
|
||||
|
||||
// As soon as we go back even by only one frame, the msec value
|
||||
// has to drop by at least one.
|
||||
TS_ASSERT_EQUALS(a.addFrames(-1).msecs(), (1234 - 1000 * 1/60 - 1));
|
||||
TS_ASSERT_EQUALS(a.addFrames(-59).msecs(), (1234 - 1000 * 59/60 - 1));
|
||||
TS_ASSERT_EQUALS(a.addFrames(-60).msecs(), (1234 - 1000 * 60/60));
|
||||
}
|
||||
|
||||
void test_more_add_diff() {
|
||||
const Audio::Timestamp c(10002, 1000);
|
||||
|
||||
for (int i = -10000; i < 10000; i++) {
|
||||
int v = c.addFrames(i).frameDiff(c);
|
||||
TS_ASSERT_EQUALS(v, i);
|
||||
}
|
||||
}
|
||||
|
||||
void test_negate() {
|
||||
const Audio::Timestamp a = Audio::Timestamp(0, 60).addFrames(13);
|
||||
const Audio::Timestamp b = -a;
|
||||
|
||||
TS_ASSERT_EQUALS(a.msecs() + 1, -b.msecs());
|
||||
TS_ASSERT_EQUALS(a.totalNumberOfFrames(), -b.totalNumberOfFrames());
|
||||
TS_ASSERT_EQUALS(a.numberOfFrames(), 60 - b.numberOfFrames());
|
||||
}
|
||||
|
||||
void test_add_sub() {
|
||||
const Audio::Timestamp a = Audio::Timestamp(0, 60).addFrames(13);
|
||||
const Audio::Timestamp b = -a;
|
||||
const Audio::Timestamp c = Audio::Timestamp(0, 60).addFrames(20);
|
||||
|
||||
TS_ASSERT_EQUALS((a+a).secs(), 0);
|
||||
TS_ASSERT_EQUALS((a+a).numberOfFrames(), 2*13);
|
||||
|
||||
TS_ASSERT_EQUALS((a+b).secs(), 0);
|
||||
TS_ASSERT_EQUALS((a+b).numberOfFrames(), 0);
|
||||
|
||||
TS_ASSERT_EQUALS((a+c).secs(), 0);
|
||||
TS_ASSERT_EQUALS((a+c).numberOfFrames(), 13+20);
|
||||
|
||||
TS_ASSERT_EQUALS((a-a).secs(), 0);
|
||||
TS_ASSERT_EQUALS((a-a).numberOfFrames(), 0);
|
||||
|
||||
TS_ASSERT_EQUALS((a-b).secs(), 0);
|
||||
TS_ASSERT_EQUALS((a-b).numberOfFrames(), 2*13);
|
||||
|
||||
TS_ASSERT_EQUALS((a-c).secs(), -1);
|
||||
TS_ASSERT_EQUALS((a-c).numberOfFrames(), 60 + (13 - 20));
|
||||
}
|
||||
|
||||
void test_diff_with_conversion() {
|
||||
const Audio::Timestamp a = Audio::Timestamp(10, 1000).addFrames(20);
|
||||
const Audio::Timestamp b = Audio::Timestamp(10, 1000/5).addFrames(20/5);
|
||||
const Audio::Timestamp c = Audio::Timestamp(10, 1000*2).addFrames(20*2);
|
||||
|
||||
TS_ASSERT_EQUALS(a.frameDiff(a), 0);
|
||||
TS_ASSERT_EQUALS(a.frameDiff(b), 0);
|
||||
TS_ASSERT_EQUALS(a.frameDiff(c), 0);
|
||||
|
||||
TS_ASSERT_EQUALS(b.frameDiff(a), 0);
|
||||
TS_ASSERT_EQUALS(b.frameDiff(b), 0);
|
||||
TS_ASSERT_EQUALS(b.frameDiff(c), 0);
|
||||
|
||||
TS_ASSERT_EQUALS(c.frameDiff(a), 0);
|
||||
TS_ASSERT_EQUALS(c.frameDiff(b), 0);
|
||||
TS_ASSERT_EQUALS(c.frameDiff(c), 0);
|
||||
}
|
||||
|
||||
|
||||
void test_convert() {
|
||||
const Audio::Timestamp a = Audio::Timestamp(10, 1000).addFrames(20);
|
||||
const Audio::Timestamp b = Audio::Timestamp(10, 1000/5).addFrames(20/5);
|
||||
const Audio::Timestamp c = Audio::Timestamp(10, 1000*2).addFrames(20*2);
|
||||
|
||||
TS_ASSERT_EQUALS(a.convertToFramerate(1000/5), b);
|
||||
TS_ASSERT_EQUALS(a.convertToFramerate(1000*2), c);
|
||||
}
|
||||
|
||||
void test_equals() {
|
||||
const Audio::Timestamp a = Audio::Timestamp(500, 1000);
|
||||
Audio::Timestamp b = Audio::Timestamp(0, 1000);
|
||||
Audio::Timestamp c = Audio::Timestamp(0, 100);
|
||||
|
||||
TS_ASSERT_EQUALS(a, Audio::Timestamp(0, 500, 1000));
|
||||
|
||||
TS_ASSERT(a != b);
|
||||
TS_ASSERT(a != c);
|
||||
TS_ASSERT(b == c);
|
||||
|
||||
b = b.addFrames(500);
|
||||
c = c.addFrames(50);
|
||||
|
||||
TS_ASSERT(a == b);
|
||||
TS_ASSERT(a == c);
|
||||
TS_ASSERT(b == c);
|
||||
}
|
||||
|
||||
|
||||
void test_compare() {
|
||||
const Audio::Timestamp a = Audio::Timestamp(60, 1000);
|
||||
Audio::Timestamp b = Audio::Timestamp(60, 60);
|
||||
Audio::Timestamp c = Audio::Timestamp(60, 44100);
|
||||
|
||||
TS_ASSERT(a <= b);
|
||||
TS_ASSERT(b <= c);
|
||||
TS_ASSERT(a <= c);
|
||||
|
||||
TS_ASSERT(b >= a);
|
||||
TS_ASSERT(c >= b);
|
||||
TS_ASSERT(c >= a);
|
||||
|
||||
b = b.addFrames(60 / 12);
|
||||
c = c.addFrames(44100 / 10);
|
||||
|
||||
TS_ASSERT(a < b);
|
||||
TS_ASSERT(b < c);
|
||||
TS_ASSERT(a < c);
|
||||
|
||||
TS_ASSERT(b > a);
|
||||
TS_ASSERT(c > b);
|
||||
TS_ASSERT(c > a);
|
||||
|
||||
TS_ASSERT(a <= b);
|
||||
TS_ASSERT(b <= c);
|
||||
TS_ASSERT(a <= c);
|
||||
|
||||
TS_ASSERT(b >= a);
|
||||
TS_ASSERT(c >= b);
|
||||
TS_ASSERT(c >= a);
|
||||
}
|
||||
|
||||
|
||||
void test_framerate() {
|
||||
const Audio::Timestamp a = Audio::Timestamp(500, 1000);
|
||||
const Audio::Timestamp b = Audio::Timestamp(500, 67);
|
||||
const Audio::Timestamp c = Audio::Timestamp(500, 100);
|
||||
const Audio::Timestamp d = Audio::Timestamp(500, 44100);
|
||||
|
||||
TS_ASSERT_EQUALS(a.framerate(), (uint)1000);
|
||||
TS_ASSERT_EQUALS(b.framerate(), (uint)67);
|
||||
TS_ASSERT_EQUALS(c.framerate(), (uint)100);
|
||||
TS_ASSERT_EQUALS(d.framerate(), (uint)44100);
|
||||
}
|
||||
|
||||
void test_direct_query() {
|
||||
const Audio::Timestamp a = Audio::Timestamp(0, 22050);
|
||||
const Audio::Timestamp b = a.addFrames(11025);
|
||||
const Audio::Timestamp c = Audio::Timestamp(1500, 22050);
|
||||
|
||||
TS_ASSERT_EQUALS(a.secs(), 0);
|
||||
TS_ASSERT_EQUALS(a.msecs(), 0);
|
||||
TS_ASSERT_EQUALS(a.numberOfFrames(), 0);
|
||||
TS_ASSERT_EQUALS(a.totalNumberOfFrames(), 0);
|
||||
|
||||
TS_ASSERT_EQUALS(b.secs(), 0);
|
||||
TS_ASSERT_EQUALS(b.msecs(), 500);
|
||||
TS_ASSERT_EQUALS(b.numberOfFrames(), 11025);
|
||||
TS_ASSERT_EQUALS(b.totalNumberOfFrames(), 11025);
|
||||
|
||||
TS_ASSERT_EQUALS(c.secs(), 1);
|
||||
TS_ASSERT_EQUALS(c.msecs(), 1500);
|
||||
TS_ASSERT_EQUALS(c.numberOfFrames(), 11025);
|
||||
TS_ASSERT_EQUALS(c.totalNumberOfFrames(), 33075);
|
||||
}
|
||||
|
||||
void test_no_overflow() {
|
||||
// The constructor should not overflow and give incoherent values
|
||||
const Audio::Timestamp a = Audio::Timestamp(0, UINT_MAX, 1000);
|
||||
|
||||
int secs = UINT_MAX / 1000;
|
||||
int frames = UINT_MAX % 1000;
|
||||
|
||||
TS_ASSERT_EQUALS(a.secs(), secs);
|
||||
TS_ASSERT_EQUALS(a.numberOfFrames(), frames);
|
||||
}
|
||||
};
|
||||
273
test/common/algorithm.h
Normal file
273
test/common/algorithm.h
Normal file
@@ -0,0 +1,273 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/util.h"
|
||||
#include "common/func.h"
|
||||
#include "common/algorithm.h"
|
||||
#include "common/list.h"
|
||||
#include "common/array.h"
|
||||
#include "common/str.h"
|
||||
|
||||
class AlgorithmTestSuite : public CxxTest::TestSuite {
|
||||
template<typename T, class StrictWeakOrdering>
|
||||
bool checkSort(T first, T last, StrictWeakOrdering comp = StrictWeakOrdering()) {
|
||||
if (first == last)
|
||||
return true;
|
||||
|
||||
// Check whether the container is sorted by the given binary predicate, which
|
||||
// decides whether the first value passed precedes the second value passed.
|
||||
//
|
||||
// To do that it checks an item and its follower in the container with the
|
||||
// given predicate in reverse order, when it returns false everything is
|
||||
// fine, when it returns false, the follower precedes the item and thus
|
||||
// the order is violated.
|
||||
for (T prev = first++; first != last; ++prev, ++first) {
|
||||
if (comp(*first, *prev))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auxiliary function to check the equality of two generic collections (A and B), from one_first to one_last.
|
||||
*
|
||||
* @note: It assumes that other has at least (one_last - one-first) length, starting from other_first.
|
||||
*
|
||||
* @param one_first: The first element of the first collection to be compared.
|
||||
* @param one_last: The last element of the first collection to be compared.
|
||||
* @param other_first: The first element of the collection to be compared.
|
||||
* @return true if, for each index i in [one_first, one_last), A[i] == B[i], false otherwise.
|
||||
*/
|
||||
template<typename It>
|
||||
bool checkEqual(It one_first, It one_last, It other_first) {
|
||||
if (one_first == one_last)
|
||||
return true;
|
||||
|
||||
// Check whether two containers have the same items in the same order,
|
||||
// starting from some iterators one_first and other_first
|
||||
//
|
||||
// It iterates through the containers, comparing the elements one by one.
|
||||
// If it finds a discrepancy, it returns false. Otherwise, it returns true.
|
||||
|
||||
for (; one_first != one_last; ++one_first, ++other_first)
|
||||
if (*one_first != *other_first)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct Item {
|
||||
int value;
|
||||
Item(int v) : value(v) {}
|
||||
|
||||
bool operator<(const Item &r) const {
|
||||
return value < r.value;
|
||||
}
|
||||
};
|
||||
public:
|
||||
void test_check_sort() {
|
||||
const int arraySorted[] = { 1, 2, 3, 3, 4, 5 };
|
||||
const int arrayUnsorted[] = { 5, 3, 1, 2, 4, 3 };
|
||||
|
||||
TS_ASSERT_EQUALS(checkSort(arraySorted, ARRAYEND(arraySorted), Common::Less<int>()), true);
|
||||
TS_ASSERT_EQUALS(checkSort(arraySorted, ARRAYEND(arraySorted), Common::Greater<int>()), false);
|
||||
|
||||
TS_ASSERT_EQUALS(checkSort(arrayUnsorted, ARRAYEND(arrayUnsorted), Common::Less<int>()), false);
|
||||
TS_ASSERT_EQUALS(checkSort(arrayUnsorted, ARRAYEND(arrayUnsorted), Common::Greater<int>()), false);
|
||||
}
|
||||
|
||||
void test_pod_sort() {
|
||||
{
|
||||
int dummy;
|
||||
Common::sort(&dummy, &dummy);
|
||||
TS_ASSERT_EQUALS(checkSort(&dummy, &dummy, Common::Less<int>()), true);
|
||||
}
|
||||
{
|
||||
int array[] = { 12 };
|
||||
Common::sort(array, ARRAYEND(array));
|
||||
TS_ASSERT_EQUALS(checkSort(array, ARRAYEND(array), Common::Less<int>()), true);
|
||||
|
||||
// already sorted
|
||||
Common::sort(array, ARRAYEND(array));
|
||||
TS_ASSERT_EQUALS(checkSort(array, ARRAYEND(array), Common::Less<int>()), true);
|
||||
}
|
||||
{
|
||||
int array[] = { 63, 11, 31, 72, 1, 48, 32, 69, 38, 31 };
|
||||
Common::sort(array, ARRAYEND(array));
|
||||
TS_ASSERT_EQUALS(checkSort(array, ARRAYEND(array), Common::Less<int>()), true);
|
||||
|
||||
int sortedArray[] = { 1, 11, 31, 31, 32, 38, 48, 63, 69, 72 };
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
TS_ASSERT_EQUALS(array[i], sortedArray[i]);
|
||||
|
||||
// already sorted
|
||||
Common::sort(array, ARRAYEND(array));
|
||||
TS_ASSERT_EQUALS(checkSort(array, ARRAYEND(array), Common::Less<int>()), true);
|
||||
}
|
||||
{
|
||||
int array[] = { 90, 80, 70, 60, 50, 40, 30, 20, 10 };
|
||||
Common::sort(array, ARRAYEND(array));
|
||||
TS_ASSERT_EQUALS(checkSort(array, ARRAYEND(array), Common::Less<int>()), true);
|
||||
|
||||
Common::sort(array, ARRAYEND(array), Common::Greater<int>());
|
||||
TS_ASSERT_EQUALS(checkSort(array, ARRAYEND(array), Common::Greater<int>()), true);
|
||||
}
|
||||
}
|
||||
|
||||
void test_container_sort() {
|
||||
const int n = 1000;
|
||||
|
||||
Common::List<Item> list;
|
||||
for(int i = 0; i < n; ++i)
|
||||
list.push_back(Item(i * 0xDEADBEEF % 1337));
|
||||
|
||||
Common::sort(list.begin(), list.end(), Common::Less<Item>());
|
||||
TS_ASSERT_EQUALS(checkSort(list.begin(), list.end(), Common::Less<Item>()), true);
|
||||
|
||||
// already sorted
|
||||
Common::sort(list.begin(), list.end());
|
||||
TS_ASSERT_EQUALS(checkSort(list.begin(), list.end(), Common::Less<Item>()), true);
|
||||
}
|
||||
|
||||
void test_string_replace() {
|
||||
|
||||
Common::String original = "Hello World";
|
||||
Common::String expected = "Hells Wsrld";
|
||||
|
||||
Common::replace(original.begin(), original.end(), 'o', 's');
|
||||
|
||||
TS_ASSERT_EQUALS(original, expected);
|
||||
}
|
||||
|
||||
void test_container_replace() {
|
||||
|
||||
Common::List<int> original;
|
||||
Common::List<int> expected;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
original.push_back(i);
|
||||
if (i == 3) {
|
||||
expected.push_back(5);
|
||||
} else {
|
||||
expected.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
Common::replace(original.begin(), original.end(), 3, 5);
|
||||
|
||||
TS_ASSERT_EQUALS(checkEqual(original.begin(), original.end(), expected.begin()), true);
|
||||
}
|
||||
|
||||
void test_container_remove() {
|
||||
{
|
||||
Common::Array<int> original {1, 2, 3, 10, 4, 5};
|
||||
Common::Array<int> expected {1, 2, 3, 4, 5};
|
||||
|
||||
Common::Array<int>::iterator r = Common::remove(original.begin(), original.end(), 10);
|
||||
|
||||
TS_ASSERT_EQUALS(checkEqual(original.begin(), r, expected.begin()), true);
|
||||
}
|
||||
{
|
||||
Common::Array<int> original {1, 2, 2, 3, 4, 4, 2, 1, 0};
|
||||
Common::Array<int> expected {1, 3, 4, 4, 1, 0};
|
||||
|
||||
Common::Array<int>::iterator r = Common::remove(original.begin(), original.end(), 2);
|
||||
|
||||
TS_ASSERT_EQUALS(checkEqual(original.begin(), r, expected.begin()), true);
|
||||
}
|
||||
{
|
||||
Common::Array<int> original {0, 1, 2, 3, 0, 3, 2, 1, 0};
|
||||
Common::Array<int> expected {1, 2, 3, 3, 2, 1};
|
||||
|
||||
Common::Array<int>::iterator r = Common::remove(original.begin(), original.end(), 0);
|
||||
|
||||
TS_ASSERT_EQUALS(checkEqual(original.begin(), r, expected.begin()), true);
|
||||
}
|
||||
}
|
||||
|
||||
void test_lower_bound_equal_found() {
|
||||
const auto test = [](const int *first, const int *last, int value) {
|
||||
const auto it = Common::lowerBound(first, last, value);
|
||||
TS_ASSERT(first <= it && it < last);
|
||||
TS_ASSERT_EQUALS(*it, value);
|
||||
};
|
||||
const int one[] = {1};
|
||||
const int values[] = {1, 2, 4, 10, 50, 100, 900, 1000};
|
||||
test(one, one + ARRAYSIZE(one), 1);
|
||||
test(values, values + ARRAYSIZE(values), 1);
|
||||
test(values, values + ARRAYSIZE(values), 1000);
|
||||
test(values, values + ARRAYSIZE(values), 4);
|
||||
}
|
||||
|
||||
void test_lower_bound_greater_found() {
|
||||
const auto test = [](const int *first, const int *last, int value, int expected) {
|
||||
const auto it = Common::lowerBound(first, last, value);
|
||||
TS_ASSERT(first <= it && it < last);
|
||||
TS_ASSERT_EQUALS(*it, expected);
|
||||
};
|
||||
const int one[] = {1};
|
||||
const int values[] = {2, 3, 4, 10, 50, 100, 900, 1000};
|
||||
test(one, one + ARRAYSIZE(one), 0, 1);
|
||||
test(values, values + ARRAYSIZE(values), 1, 2);
|
||||
test(values, values + ARRAYSIZE(values), 950, 1000);
|
||||
test(values, values + ARRAYSIZE(values), 20, 50);
|
||||
}
|
||||
|
||||
void test_lower_bound_element_nothing_found() {
|
||||
const int values[] = {1, 2, 3, 6, 8, 10, 20, 50};
|
||||
const auto last = values + ARRAYSIZE(values);
|
||||
const auto it = Common::lowerBound(values, last, 100);
|
||||
TS_ASSERT_EQUALS(it, last);
|
||||
}
|
||||
|
||||
void test_lower_bound_empty_input() {
|
||||
{
|
||||
const int values[] = {1};
|
||||
const auto last = values + ARRAYSIZE(values);
|
||||
const auto it = Common::lowerBound(last, last, 1);
|
||||
TS_ASSERT_EQUALS(it, last);
|
||||
}
|
||||
{
|
||||
const auto it = Common::lowerBound((int *)nullptr, (int *)nullptr, 1);
|
||||
TS_ASSERT_EQUALS(it, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void test_upper_bound_element_found() {
|
||||
const auto test = [](const int *first, const int *last, int value, int expected) {
|
||||
const auto it = Common::upperBound(first, last, value);
|
||||
TS_ASSERT(first <= it && it < last);
|
||||
TS_ASSERT_EQUALS(*it, expected);
|
||||
};
|
||||
const int one[] = {1};
|
||||
const int values[] = {2, 3, 4, 10, 50, 100, 900, 1000};
|
||||
test(one, one + ARRAYSIZE(one), 0, 1);
|
||||
test(values, values + ARRAYSIZE(values), 1, 2);
|
||||
test(values, values + ARRAYSIZE(values), 950, 1000);
|
||||
test(values, values + ARRAYSIZE(values), 20, 50);
|
||||
}
|
||||
|
||||
void test_upper_bound_nothing_found() {
|
||||
const int values[] = {1, 2, 3, 6, 8, 10, 20, 50};
|
||||
const auto last = values + ARRAYSIZE(values);
|
||||
{
|
||||
const auto it = Common::upperBound(values, last, 50);
|
||||
TS_ASSERT_EQUALS(it, last);
|
||||
}
|
||||
{
|
||||
const auto it = Common::upperBound(values, last, 100);
|
||||
TS_ASSERT_EQUALS(it, last);
|
||||
}
|
||||
}
|
||||
|
||||
void test_upper_bound_empty_input() {
|
||||
{
|
||||
const int values[] = {1};
|
||||
const auto last = values + ARRAYSIZE(values);
|
||||
const auto it = Common::upperBound(last, last, 1);
|
||||
TS_ASSERT_EQUALS(it, last);
|
||||
}
|
||||
{
|
||||
const auto it = Common::upperBound((int *)nullptr, (int *)nullptr, 1);
|
||||
TS_ASSERT_EQUALS(it, nullptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
617
test/common/array.h
Normal file
617
test/common/array.h
Normal file
@@ -0,0 +1,617 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/noncopyable.h"
|
||||
#include "common/str.h"
|
||||
|
||||
|
||||
struct ArrayTestMovable {
|
||||
ArrayTestMovable() : _value(0), _wasMoveConstructed(false), _wasMovedFrom(false) {}
|
||||
|
||||
explicit ArrayTestMovable(int value) : _value(value), _wasMoveConstructed(false), _wasMovedFrom(false) {}
|
||||
|
||||
ArrayTestMovable(const ArrayTestMovable &other)
|
||||
: _value(other._value), _wasMoveConstructed(false), _wasMovedFrom(false) {
|
||||
}
|
||||
|
||||
ArrayTestMovable(ArrayTestMovable &&other) noexcept
|
||||
: _value(other._value), _wasMoveConstructed(true), _wasMovedFrom(false) {
|
||||
other._wasMovedFrom = true;
|
||||
}
|
||||
|
||||
int _value;
|
||||
bool _wasMoveConstructed;
|
||||
bool _wasMovedFrom;
|
||||
};
|
||||
|
||||
// Hopefully temporary until Common::Pair can be updated to have move constructor/assign operator
|
||||
struct ArrayTestMovablePair {
|
||||
ArrayTestMovablePair(ArrayTestMovable &&pFirst, ArrayTestMovable &&pSecond)
|
||||
: first(Common::move(pFirst)), second(Common::move(pSecond)) {
|
||||
}
|
||||
|
||||
ArrayTestMovablePair(const ArrayTestMovable &&pFirst, const ArrayTestMovable &&pSecond)
|
||||
: first(pFirst), second(pSecond) {
|
||||
}
|
||||
|
||||
ArrayTestMovable first;
|
||||
ArrayTestMovable second;
|
||||
};
|
||||
|
||||
class ArrayTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_empty_clear() {
|
||||
Common::Array<int> array;
|
||||
TS_ASSERT(array.empty());
|
||||
array.push_back(17);
|
||||
array.push_back(33);
|
||||
TS_ASSERT(!array.empty());
|
||||
array.clear();
|
||||
TS_ASSERT(array.empty());
|
||||
}
|
||||
|
||||
void test_iterator() {
|
||||
Common::Array<int> array;
|
||||
Common::Array<int>::iterator iter;
|
||||
|
||||
// Fill the array with some random data
|
||||
array.push_back(17);
|
||||
array.push_back(33);
|
||||
array.push_back(-11);
|
||||
|
||||
// Iterate over the array and verify that we encounter the elements in
|
||||
// the order we expect them to be.
|
||||
|
||||
iter = array.begin();
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 17);
|
||||
++iter;
|
||||
TS_ASSERT_DIFFERS(iter, array.end());
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 33);
|
||||
++iter;
|
||||
TS_ASSERT_DIFFERS(iter, array.end());
|
||||
|
||||
// Also test the postinc
|
||||
TS_ASSERT_EQUALS(*iter, -11);
|
||||
iter++;
|
||||
TS_ASSERT_EQUALS(iter, array.end());
|
||||
}
|
||||
|
||||
void test_erase_iterator() {
|
||||
Common::Array<int> array;
|
||||
Common::Array<int>::iterator iter;
|
||||
|
||||
// Fill the array with some random data
|
||||
array.push_back(17);
|
||||
array.push_back(33);
|
||||
array.push_back(-11);
|
||||
|
||||
iter = array.begin();
|
||||
++iter;
|
||||
|
||||
iter = array.erase(iter);
|
||||
TS_ASSERT_DIFFERS(iter, array.end());
|
||||
TS_ASSERT_EQUALS(*iter, -11);
|
||||
TS_ASSERT_EQUALS(array.size(), (unsigned int)2);
|
||||
TS_ASSERT_EQUALS(array[0], 17);
|
||||
TS_ASSERT_EQUALS(array[1], -11);
|
||||
}
|
||||
|
||||
void test_erase_iterator_range() {
|
||||
Common::Array<int> array;
|
||||
Common::Array<int>::iterator first, last;
|
||||
|
||||
// Fill the array with some random data
|
||||
array.push_back(17);
|
||||
array.push_back(33);
|
||||
array.push_back(66);
|
||||
array.push_back(99);
|
||||
array.push_back(-11);
|
||||
|
||||
first = array.begin();
|
||||
++first;
|
||||
|
||||
last = array.end();
|
||||
--last;
|
||||
|
||||
first = array.erase(first, last);
|
||||
TS_ASSERT_DIFFERS(first, array.end());
|
||||
TS_ASSERT_EQUALS(*first, -11);
|
||||
TS_ASSERT_EQUALS(array.size(), (unsigned int)2);
|
||||
TS_ASSERT_EQUALS(array[0], 17);
|
||||
TS_ASSERT_EQUALS(array[1], -11);
|
||||
}
|
||||
|
||||
void test_insert_iterator() {
|
||||
Common::Array<int> array;
|
||||
Common::Array<int>::iterator iter;
|
||||
|
||||
// Fill the array with some random data
|
||||
array.push_back(17);
|
||||
array.push_back(33);
|
||||
array.push_back(-11);
|
||||
|
||||
iter = array.begin();
|
||||
++iter;
|
||||
|
||||
array.insert(iter, 99);
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 99);
|
||||
TS_ASSERT_EQUALS(array.size(), (unsigned int)4);
|
||||
TS_ASSERT_EQUALS(array[0], 17);
|
||||
TS_ASSERT_EQUALS(array[1], 99);
|
||||
TS_ASSERT_EQUALS(array[2], 33);
|
||||
TS_ASSERT_EQUALS(array[3], -11);
|
||||
}
|
||||
|
||||
void test_direct_access() {
|
||||
Common::Array<int> array;
|
||||
|
||||
// Fill the array with some random data
|
||||
array.push_back(17);
|
||||
array.push_back(33);
|
||||
array.push_back(-11);
|
||||
|
||||
TS_ASSERT_EQUALS(array[0], 17);
|
||||
TS_ASSERT_EQUALS(array[1], 33);
|
||||
TS_ASSERT_EQUALS(array[2], -11);
|
||||
}
|
||||
|
||||
void test_insert_at() {
|
||||
Common::Array<int> array;
|
||||
|
||||
// First of all some data
|
||||
array.push_back(-12);
|
||||
array.push_back(17);
|
||||
array.push_back(25);
|
||||
array.push_back(-11);
|
||||
|
||||
// Insert some data
|
||||
array.insert_at(2, 33);
|
||||
|
||||
TS_ASSERT_EQUALS(array[0], -12);
|
||||
TS_ASSERT_EQUALS(array[1], 17);
|
||||
TS_ASSERT_EQUALS(array[2], 33);
|
||||
TS_ASSERT_EQUALS(array[3], 25);
|
||||
TS_ASSERT_EQUALS(array[4], -11);
|
||||
|
||||
TS_ASSERT_EQUALS(array.size(), (unsigned int)5);
|
||||
}
|
||||
|
||||
void test_insert_at_array() {
|
||||
Common::Array<int> array;
|
||||
Common::Array<int> array2;
|
||||
|
||||
// First of all some data
|
||||
array.push_back(-12);
|
||||
array.push_back(17);
|
||||
array.push_back(25);
|
||||
array.push_back(-11);
|
||||
|
||||
array2.push_back(42);
|
||||
array2.push_back(105);
|
||||
array2.push_back(-1);
|
||||
|
||||
// Insert some data
|
||||
array.insert_at(2, array2);
|
||||
|
||||
TS_ASSERT_EQUALS(array.size(), (unsigned int)7);
|
||||
|
||||
TS_ASSERT_EQUALS(array[0], -12);
|
||||
TS_ASSERT_EQUALS(array[1], 17);
|
||||
TS_ASSERT_EQUALS(array[2], 42);
|
||||
TS_ASSERT_EQUALS(array[3], 105);
|
||||
TS_ASSERT_EQUALS(array[4], -1);
|
||||
TS_ASSERT_EQUALS(array[5], 25);
|
||||
TS_ASSERT_EQUALS(array[6], -11);
|
||||
|
||||
}
|
||||
|
||||
void test_self_insert() {
|
||||
Common::Array<int> array;
|
||||
int i;
|
||||
|
||||
// Insert some data -- and make sure we have enough space for
|
||||
// *twice* as much data. This way, there is no need to allocate
|
||||
// new storage, so if the insert() operation is "clever", it
|
||||
// will try to reuse the existing storage.
|
||||
// This in turn may uncover bugs if the insertion code does not
|
||||
// expect self-insertions.
|
||||
array.reserve(128);
|
||||
for (i = 0; i < 64; ++i)
|
||||
array.push_back(i);
|
||||
|
||||
// Now insert the array into the middle of itself
|
||||
array.insert_at(12, array);
|
||||
|
||||
// Verify integrity
|
||||
TS_ASSERT_EQUALS(array.size(), 128UL);
|
||||
|
||||
for (i = 0; i < 12; ++i)
|
||||
TS_ASSERT_EQUALS(array[i], i);
|
||||
for (i = 0; i < 64; ++i)
|
||||
TS_ASSERT_EQUALS(array[i+12], i);
|
||||
for (i = 12; i < 64; ++i)
|
||||
TS_ASSERT_EQUALS(array[i+64], i);
|
||||
}
|
||||
|
||||
|
||||
void test_remove_at() {
|
||||
Common::Array<int> array;
|
||||
|
||||
// First of all some data
|
||||
array.push_back(-12);
|
||||
array.push_back(17);
|
||||
array.push_back(33);
|
||||
array.push_back(25);
|
||||
array.push_back(-11);
|
||||
|
||||
// Remove some data
|
||||
array.remove_at(1);
|
||||
|
||||
TS_ASSERT_EQUALS(array[0], -12);
|
||||
TS_ASSERT_EQUALS(array[1], 33);
|
||||
TS_ASSERT_EQUALS(array[2], 25);
|
||||
TS_ASSERT_EQUALS(array[3], -11);
|
||||
|
||||
TS_ASSERT_EQUALS(array.size(), (unsigned int)4);
|
||||
}
|
||||
|
||||
void test_push_back() {
|
||||
Common::Array<int> array1, array2;
|
||||
|
||||
// Some data for both
|
||||
array1.push_back(-3);
|
||||
array1.push_back(5);
|
||||
array1.push_back(9);
|
||||
|
||||
array2.push_back(3);
|
||||
array2.push_back(-2);
|
||||
array2.push_back(-131);
|
||||
|
||||
array1.push_back(array2);
|
||||
|
||||
TS_ASSERT_EQUALS(array1[0], -3);
|
||||
TS_ASSERT_EQUALS(array1[1], 5);
|
||||
TS_ASSERT_EQUALS(array1[2], 9);
|
||||
TS_ASSERT_EQUALS(array1[3], 3);
|
||||
TS_ASSERT_EQUALS(array1[4], -2);
|
||||
TS_ASSERT_EQUALS(array1[5], -131);
|
||||
|
||||
TS_ASSERT_EQUALS(array1.size(), (unsigned int)6);
|
||||
TS_ASSERT_EQUALS(array2.size(), (unsigned int)3);
|
||||
}
|
||||
|
||||
struct SafeInt {
|
||||
int val;
|
||||
SafeInt() : val(0) {}
|
||||
SafeInt(int v) : val(v) {}
|
||||
~SafeInt() { val = -1; }
|
||||
bool operator==(int v) {
|
||||
return val == v;
|
||||
}
|
||||
};
|
||||
|
||||
void test_push_back_ex() {
|
||||
// This test makes sure that inserting an element invalidates
|
||||
// references/iterators/pointers to elements in the array itself
|
||||
// only *after* their value has been copied.
|
||||
Common::Array<SafeInt> array;
|
||||
|
||||
array.push_back(42);
|
||||
for (int i = 0; i < 40; ++i) {
|
||||
array.push_back(array[0]);
|
||||
TS_ASSERT_EQUALS(array[i], 42);
|
||||
}
|
||||
}
|
||||
|
||||
void test_copy_constructor() {
|
||||
Common::Array<int> array1;
|
||||
|
||||
// Some data for both
|
||||
array1.push_back(-3);
|
||||
array1.push_back(5);
|
||||
array1.push_back(9);
|
||||
|
||||
Common::Array<int> array2(array1);
|
||||
|
||||
// Alter the original array
|
||||
array1[0] = 7;
|
||||
array1[1] = -5;
|
||||
array1[2] = 2;
|
||||
|
||||
TS_ASSERT_EQUALS(array2[0], -3);
|
||||
TS_ASSERT_EQUALS(array2[1], 5);
|
||||
TS_ASSERT_EQUALS(array2[2], 9);
|
||||
|
||||
TS_ASSERT_EQUALS(array2.size(), (unsigned int)3);
|
||||
}
|
||||
|
||||
void test_equals() {
|
||||
Common::Array<int> array1;
|
||||
|
||||
// Some data for both
|
||||
array1.push_back(-3);
|
||||
array1.push_back(5);
|
||||
array1.push_back(9);
|
||||
|
||||
Common::Array<int> array2(array1);
|
||||
|
||||
TS_ASSERT(array1 == array2);
|
||||
array1.push_back(42);
|
||||
TS_ASSERT(array1 != array2);
|
||||
array2.push_back(42);
|
||||
TS_ASSERT(array1 == array2);
|
||||
}
|
||||
|
||||
void test_array_constructor() {
|
||||
const int array1[] = { -3, 5, 9 };
|
||||
|
||||
Common::Array<int> array2(array1, 3);
|
||||
|
||||
TS_ASSERT_EQUALS(array2[0], -3);
|
||||
TS_ASSERT_EQUALS(array2[1], 5);
|
||||
TS_ASSERT_EQUALS(array2[2], 9);
|
||||
|
||||
TS_ASSERT_EQUALS(array2.size(), (unsigned int)3);
|
||||
}
|
||||
|
||||
class Copyable {
|
||||
bool _copied;
|
||||
int _value;
|
||||
Copyable &operator=(Copyable &);
|
||||
public:
|
||||
Copyable() : _copied(false), _value(1) {}
|
||||
explicit Copyable(const int v) : _copied(false), _value(v) {}
|
||||
Copyable(const Copyable &other) : _copied(true), _value(other._value) {}
|
||||
bool copied() const { return _copied; }
|
||||
int value() const { return _value; }
|
||||
};
|
||||
|
||||
void test_array_constructor_count() {
|
||||
Common::Array<int> array(10);
|
||||
TS_ASSERT_EQUALS(array.size(), 10U);
|
||||
TS_ASSERT_EQUALS(array[0], 0);
|
||||
TS_ASSERT_EQUALS(array[9], 0);
|
||||
|
||||
// This will fail at compile time if it is not possible to construct an
|
||||
// array without copy-construction
|
||||
Common::Array<Common::NonCopyable> nonCopyable(1);
|
||||
}
|
||||
|
||||
void test_array_constructor_list() {
|
||||
Common::Array<int> array = {1, 42, 255};
|
||||
TS_ASSERT_EQUALS(array.size(), 3U);
|
||||
TS_ASSERT_EQUALS(array[0], 1);
|
||||
TS_ASSERT_EQUALS(array[1], 42);
|
||||
TS_ASSERT_EQUALS(array[2], 255);
|
||||
}
|
||||
|
||||
void test_array_constructor_count_copy_value() {
|
||||
Common::Array<int> trivial(5, 1);
|
||||
TS_ASSERT_EQUALS(trivial.size(), 5U);
|
||||
TS_ASSERT_EQUALS(trivial[0], 1);
|
||||
TS_ASSERT_EQUALS(trivial[4], 1);
|
||||
|
||||
Copyable c(123);
|
||||
typedef Common::Array<Copyable> NonTrivialArray;
|
||||
|
||||
NonTrivialArray nonTrivialCopy(3, c);
|
||||
TS_ASSERT_EQUALS(nonTrivialCopy.size(), 3U);
|
||||
for (NonTrivialArray::size_type i = 0; i < nonTrivialCopy.size(); ++i) {
|
||||
TS_ASSERT_EQUALS(nonTrivialCopy[0].value(), 123);
|
||||
TS_ASSERT(nonTrivialCopy[0].copied());
|
||||
}
|
||||
|
||||
NonTrivialArray nonTrivialDefault(3);
|
||||
TS_ASSERT_EQUALS(nonTrivialDefault.size(), 3U);
|
||||
for (NonTrivialArray::size_type i = 0; i < nonTrivialDefault.size(); ++i) {
|
||||
TS_ASSERT_EQUALS(nonTrivialDefault[0].value(), 1);
|
||||
TS_ASSERT(!nonTrivialDefault[0].copied());
|
||||
}
|
||||
}
|
||||
|
||||
void test_array_constructor_str() {
|
||||
const char *array1[] = { "a", "b", "c" };
|
||||
|
||||
Common::Array<Common::String> array2(array1, 3);
|
||||
|
||||
TS_ASSERT_EQUALS(array2[0], "a");
|
||||
TS_ASSERT_EQUALS(array2[1], "b");
|
||||
TS_ASSERT_EQUALS(array2[2], "c");
|
||||
|
||||
TS_ASSERT_EQUALS(array2.size(), (unsigned int)3);
|
||||
}
|
||||
|
||||
void test_data() {
|
||||
Common::Array<int> array;
|
||||
TS_ASSERT(array.data() == nullptr);
|
||||
array.resize(2);
|
||||
TS_ASSERT(array.data() != nullptr);
|
||||
TS_ASSERT_EQUALS(array.data(), &array.front());
|
||||
TS_ASSERT_EQUALS(array.data() + array.size() - 1, &array.back());
|
||||
}
|
||||
|
||||
void test_front_back_push_pop() {
|
||||
Common::Array<int> container;
|
||||
|
||||
container.push_back( 42);
|
||||
container.push_back(-23);
|
||||
|
||||
TS_ASSERT_EQUALS(container.front(), 42);
|
||||
TS_ASSERT_EQUALS(container.back(), -23);
|
||||
|
||||
container.front() = -17;
|
||||
container.back() = 163;
|
||||
TS_ASSERT_EQUALS(container.front(), -17);
|
||||
TS_ASSERT_EQUALS(container.back(), 163);
|
||||
|
||||
container.pop_back();
|
||||
TS_ASSERT_EQUALS(container.front(), -17);
|
||||
TS_ASSERT_EQUALS(container.back(), -17);
|
||||
}
|
||||
|
||||
void test_resize() {
|
||||
Common::Array<int> array;
|
||||
|
||||
array.resize(3);
|
||||
TS_ASSERT_EQUALS(array.size(), (unsigned int)3);
|
||||
|
||||
array[0] = -3;
|
||||
array[1] = 163;
|
||||
array[2] = 17;
|
||||
|
||||
array.resize(100);
|
||||
TS_ASSERT_EQUALS(array.size(), (unsigned int)100);
|
||||
TS_ASSERT_EQUALS(array[0], -3);
|
||||
TS_ASSERT_EQUALS(array[1], 163);
|
||||
TS_ASSERT_EQUALS(array[2], 17);
|
||||
|
||||
TS_ASSERT_EQUALS(array[99], 0);
|
||||
|
||||
array.resize(2);
|
||||
TS_ASSERT_EQUALS(array.size(), (unsigned int)2);
|
||||
TS_ASSERT_EQUALS(array[0], -3);
|
||||
TS_ASSERT_EQUALS(array[1], 163);
|
||||
|
||||
array.resize(4, 42);
|
||||
TS_ASSERT_EQUALS(array.size(), (unsigned int)4);
|
||||
TS_ASSERT_EQUALS(array[0], -3);
|
||||
TS_ASSERT_EQUALS(array[1], 163);
|
||||
TS_ASSERT_EQUALS(array[2], 42);
|
||||
TS_ASSERT_EQUALS(array[3], 42);
|
||||
|
||||
array.resize(2, 42);
|
||||
TS_ASSERT_EQUALS(array.size(), (unsigned int)2);
|
||||
TS_ASSERT_EQUALS(array[0], -3);
|
||||
TS_ASSERT_EQUALS(array[1], 163);
|
||||
}
|
||||
|
||||
void test_swap() {
|
||||
Common::Array<int> array1, array2;
|
||||
|
||||
array1.push_back(-3);
|
||||
array1.push_back(163);
|
||||
array1.push_back(17);
|
||||
array2.push_back(5);
|
||||
array2.push_back(9);
|
||||
|
||||
TS_ASSERT_EQUALS(array1.size(), 3u);
|
||||
TS_ASSERT_EQUALS(array1[0], -3);
|
||||
TS_ASSERT_EQUALS(array1[1], 163);
|
||||
TS_ASSERT_EQUALS(array1[2], 17);
|
||||
TS_ASSERT_EQUALS(array2.size(), 2u);
|
||||
TS_ASSERT_EQUALS(array2[0], 5);
|
||||
TS_ASSERT_EQUALS(array2[1], 9);
|
||||
|
||||
array1.swap(array2);
|
||||
|
||||
TS_ASSERT_EQUALS(array1.size(), 2u);
|
||||
TS_ASSERT_EQUALS(array1[0], 5);
|
||||
TS_ASSERT_EQUALS(array1[1], 9);
|
||||
TS_ASSERT_EQUALS(array2.size(), 3u);
|
||||
TS_ASSERT_EQUALS(array2[0], -3);
|
||||
TS_ASSERT_EQUALS(array2[1], 163);
|
||||
TS_ASSERT_EQUALS(array2[2], 17);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct ListElement {
|
||||
int value;
|
||||
int tag;
|
||||
|
||||
ListElement(int v, int t = 0) : value(v), tag(t) {}
|
||||
};
|
||||
|
||||
static int compareInts(const void *a, const void *b) {
|
||||
return ((const ListElement *)a)->value - ((const ListElement *)b)->value;
|
||||
}
|
||||
|
||||
class SortedArrayTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_insert() {
|
||||
Common::SortedArray<ListElement *> container(compareInts);
|
||||
Common::SortedArray<ListElement *>::iterator iter;
|
||||
|
||||
// Fill the container with some random data
|
||||
container.insert(new ListElement(1));
|
||||
container.insert(new ListElement(7));
|
||||
container.insert(new ListElement(8));
|
||||
container.insert(new ListElement(3));
|
||||
container.insert(new ListElement(5));
|
||||
container.insert(new ListElement(4));
|
||||
container.insert(new ListElement(9));
|
||||
container.insert(new ListElement(2));
|
||||
container.insert(new ListElement(6));
|
||||
|
||||
// Verify contents are correct
|
||||
iter = container.begin();
|
||||
|
||||
for (int i = 1; i < 10; i++) {
|
||||
TS_ASSERT_EQUALS((*iter)->value, i);
|
||||
++iter;
|
||||
}
|
||||
|
||||
TS_ASSERT_EQUALS(iter, container.end());
|
||||
|
||||
// Cleanup
|
||||
for(iter = container.begin(); iter != container.end(); iter++) {
|
||||
delete *iter;
|
||||
}
|
||||
}
|
||||
|
||||
void test_stability() {
|
||||
Common::SortedArray<ListElement *> container(compareInts);
|
||||
Common::SortedArray<ListElement *>::iterator iter;
|
||||
|
||||
// Check stability, using duplicate keys and sequential tags.
|
||||
container.insert(new ListElement(1, 3));
|
||||
container.insert(new ListElement(0, 1));
|
||||
container.insert(new ListElement(4, 8));
|
||||
container.insert(new ListElement(1, 4));
|
||||
container.insert(new ListElement(0, 2));
|
||||
container.insert(new ListElement(2, 6));
|
||||
container.insert(new ListElement(1, 5));
|
||||
container.insert(new ListElement(3, 7));
|
||||
container.insert(new ListElement(4, 9));
|
||||
|
||||
// Verify contents are correct
|
||||
iter = container.begin();
|
||||
|
||||
for (int i = 1; i < 10; i++) {
|
||||
TS_ASSERT_EQUALS((*iter)->tag, i);
|
||||
++iter;
|
||||
}
|
||||
|
||||
TS_ASSERT_EQUALS(iter, container.end());
|
||||
|
||||
// Cleanup
|
||||
for(iter = container.begin(); iter != container.end(); iter++) {
|
||||
delete *iter;
|
||||
}
|
||||
}
|
||||
|
||||
void test_emplace() {
|
||||
Common::Array<ArrayTestMovablePair> movablePairArray;
|
||||
movablePairArray.emplace_back(ArrayTestMovable(1), ArrayTestMovable(2));
|
||||
|
||||
TS_ASSERT(movablePairArray[0].first._wasMoveConstructed);
|
||||
TS_ASSERT_EQUALS(movablePairArray[0].first._value, 1);
|
||||
TS_ASSERT(movablePairArray[0].second._wasMoveConstructed);
|
||||
TS_ASSERT_EQUALS(movablePairArray[0].second._value, 2);
|
||||
}
|
||||
|
||||
void test_push_back_move() {
|
||||
ArrayTestMovable movable(3);
|
||||
|
||||
Common::Array<ArrayTestMovable> movableArray;
|
||||
movableArray.push_back(Common::move(movable));
|
||||
|
||||
TS_ASSERT(movable._wasMovedFrom);
|
||||
TS_ASSERT_EQUALS(movableArray[0]._value, 3);
|
||||
TS_ASSERT(movableArray[0]._wasMoveConstructed);
|
||||
}
|
||||
};
|
||||
128
test/common/base64.h
Normal file
128
test/common/base64.h
Normal file
@@ -0,0 +1,128 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/base64.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
static const char *base64_test_string[] = {
|
||||
"",
|
||||
"a",
|
||||
"abc",
|
||||
"abcdefghijklmnopqrstuvwxyz",
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
("12345678901234567890123456789012345678901234567890123456789012"
|
||||
"345678901234567890")
|
||||
};
|
||||
|
||||
static const char *base64_test_encoded[] = {
|
||||
"",
|
||||
"YQ==",
|
||||
"YWJj",
|
||||
"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=",
|
||||
("QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdH"
|
||||
"V2d3h5ejAxMjM0NTY3ODk="),
|
||||
("MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Nj"
|
||||
"c4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTA=")
|
||||
};
|
||||
|
||||
static const char *base64_validate_tests[] = {
|
||||
"YQ", // missing padding
|
||||
"!@#$", // characters not in encoding table
|
||||
"YQ==YWJj", // data after padding
|
||||
};
|
||||
|
||||
#include "common/pack-start.h" // START STRUCT PACKING
|
||||
|
||||
struct Base64TestStruct {
|
||||
uint32 x;
|
||||
byte y;
|
||||
uint16 z;
|
||||
uint32 a;
|
||||
byte b;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
#include "common/pack-end.h" // END STRUCT PACKING
|
||||
|
||||
class Base64TestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_b64Validate() {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
Common::String encoded = base64_test_encoded[i];
|
||||
// All of these should return true.
|
||||
TS_ASSERT_EQUALS(Common::b64Validate(encoded), true);
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Common::String encoded = base64_validate_tests[i];
|
||||
// All of these should return false.
|
||||
TS_ASSERT_EQUALS(Common::b64Validate(encoded), false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void test_b64EncodeString() {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
Common::String string = base64_test_string[i];
|
||||
Common::String encoded = Common::b64EncodeString(string);
|
||||
TS_ASSERT_EQUALS(encoded, base64_test_encoded[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void test_b64EncodeStream() {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
Common::MemoryReadStream stream((const byte *)base64_test_string[i], strlen(base64_test_string[i]));
|
||||
Common::String encoded = Common::b64EncodeStream(stream);
|
||||
TS_ASSERT_EQUALS(encoded, base64_test_encoded[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void test_b64EncodeData() {
|
||||
Base64TestStruct *test = new Base64TestStruct();
|
||||
test->x = TO_LE_32(1);
|
||||
test->y = 2;
|
||||
test->z = TO_LE_16(3);
|
||||
test->a = TO_LE_32(4);
|
||||
test->b = 5;
|
||||
|
||||
Common::String encoded = Common::b64EncodeData(test, sizeof(Base64TestStruct));
|
||||
TS_ASSERT_EQUALS(encoded, "AQAAAAIDAAQAAAAF");
|
||||
delete test;
|
||||
}
|
||||
|
||||
void test_b64DecodeString() {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
Common::String encoded = base64_test_encoded[i];
|
||||
Common::String string = Common::b64DecodeString(encoded);
|
||||
TS_ASSERT_EQUALS(string, base64_test_string[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void test_b64DecodeStream() {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
Common::String encoded = base64_test_encoded[i];
|
||||
Common::MemoryReadStream *stream = Common::b64DecodeStream(encoded, strlen(base64_test_string[i]));
|
||||
TS_ASSERT_EQUALS(stream->size(), (int64)strlen(base64_test_string[i]));
|
||||
|
||||
char *data = (char *)malloc(stream->size());
|
||||
stream->read(data, stream->size());
|
||||
delete stream;
|
||||
|
||||
Common::String string(data, strlen(base64_test_string[i]));
|
||||
TS_ASSERT_EQUALS(string, base64_test_string[i]);
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
void test_b64DecodeData() {
|
||||
Base64TestStruct *test = new Base64TestStruct();
|
||||
|
||||
Common::String encoded = "AQAAAAIDAAQAAAAF";
|
||||
bool success = Common::b64DecodeData(encoded, test);
|
||||
TS_ASSERT_EQUALS(success, true);
|
||||
|
||||
TS_ASSERT_EQUALS(FROM_LE_32(test->x), 1u);
|
||||
TS_ASSERT_EQUALS(test->y, 2u);
|
||||
TS_ASSERT_EQUALS(FROM_LE_16(test->z), 3u);
|
||||
TS_ASSERT_EQUALS(FROM_LE_32(test->a), 4u);
|
||||
TS_ASSERT_EQUALS(test->b, 5u);
|
||||
delete test;
|
||||
}
|
||||
};
|
||||
258
test/common/bitstream.h
Normal file
258
test/common/bitstream.h
Normal file
@@ -0,0 +1,258 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/bitstream.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
class BitStreamTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
private:
|
||||
template<class MS, class BS>
|
||||
void tmpl_get_bit() {
|
||||
byte contents[] = { 'a' };
|
||||
|
||||
MS ms(contents, sizeof(contents));
|
||||
|
||||
BS bs(ms);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
TS_ASSERT_EQUALS(bs.getBit(), 0u);
|
||||
TS_ASSERT_EQUALS(bs.getBit(), 1u);
|
||||
TS_ASSERT_EQUALS(bs.getBit(), 1u);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 3u);
|
||||
TS_ASSERT(!bs.eos());
|
||||
}
|
||||
public:
|
||||
void test_get_bit() {
|
||||
tmpl_get_bit<Common::MemoryReadStream, Common::BitStream8MSB>();
|
||||
tmpl_get_bit<Common::BitStreamMemoryStream, Common::BitStreamMemory8MSB>();
|
||||
}
|
||||
|
||||
private:
|
||||
template<class MS, class BS>
|
||||
void tmpl_get_bits() {
|
||||
byte contents[] = { 'a', 'b' };
|
||||
|
||||
MS ms(contents, sizeof(contents));
|
||||
|
||||
BS bs(ms);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
TS_ASSERT_EQUALS(bs.getBits(3), 3u);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 3u);
|
||||
TS_ASSERT_EQUALS(bs.getBits(8), 11u);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 11u);
|
||||
TS_ASSERT(!bs.eos());
|
||||
}
|
||||
public:
|
||||
void test_get_bits() {
|
||||
tmpl_get_bits<Common::MemoryReadStream, Common::BitStream8MSB>();
|
||||
tmpl_get_bits<Common::BitStreamMemoryStream, Common::BitStreamMemory8MSB>();
|
||||
}
|
||||
|
||||
private:
|
||||
template<class MS, class BS>
|
||||
void tmpl_skip() {
|
||||
byte contents[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' };
|
||||
|
||||
MS ms(contents, sizeof(contents));
|
||||
|
||||
BS bs(ms);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
bs.skip(5);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 5u);
|
||||
bs.skip(4);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 9u);
|
||||
TS_ASSERT_EQUALS(bs.getBits(3), 6u);
|
||||
bs.skip(65);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 77u);
|
||||
TS_ASSERT(!bs.eos());
|
||||
}
|
||||
public:
|
||||
void test_skip() {
|
||||
tmpl_skip<Common::MemoryReadStream, Common::BitStream8MSB>();
|
||||
tmpl_skip<Common::BitStreamMemoryStream, Common::BitStreamMemory8MSB>();
|
||||
}
|
||||
|
||||
private:
|
||||
template<class MS, class BS>
|
||||
void tmpl_rewind() {
|
||||
byte contents[] = { 'a' };
|
||||
|
||||
MS ms(contents, sizeof(contents));
|
||||
|
||||
BS bs(ms);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
bs.skip(5);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 5u);
|
||||
bs.rewind();
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
TS_ASSERT_EQUALS(bs.getBits(3), 3u);
|
||||
TS_ASSERT(!bs.eos());
|
||||
|
||||
TS_ASSERT_EQUALS(bs.size(), 8u);
|
||||
}
|
||||
public:
|
||||
void test_rewind() {
|
||||
tmpl_rewind<Common::MemoryReadStream, Common::BitStream8MSB>();
|
||||
tmpl_rewind<Common::BitStreamMemoryStream, Common::BitStreamMemory8MSB>();
|
||||
}
|
||||
|
||||
private:
|
||||
template<class MS, class BS>
|
||||
void tmpl_peek_bit() {
|
||||
byte contents[] = { 'a' };
|
||||
|
||||
MS ms(contents, sizeof(contents));
|
||||
|
||||
BS bs(ms);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
TS_ASSERT_EQUALS(bs.peekBit(), 0u);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
TS_ASSERT_EQUALS(bs.getBit(), 0u);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 1u);
|
||||
TS_ASSERT_EQUALS(bs.peekBit(), 1u);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 1u);
|
||||
TS_ASSERT(!bs.eos());
|
||||
}
|
||||
public:
|
||||
void test_peek_bit() {
|
||||
tmpl_peek_bit<Common::MemoryReadStream, Common::BitStream8MSB>();
|
||||
tmpl_peek_bit<Common::BitStreamMemoryStream, Common::BitStreamMemory8MSB>();
|
||||
}
|
||||
|
||||
private:
|
||||
template<class MS, class BS>
|
||||
void tmpl_peek_bits() {
|
||||
byte contents[] = { 'a', 'b' };
|
||||
|
||||
MS ms(contents, sizeof(contents));
|
||||
|
||||
BS bs(ms);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
TS_ASSERT_EQUALS(bs.peekBits(3), 3u);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
bs.skip(3);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 3u);
|
||||
TS_ASSERT_EQUALS(bs.peekBits(8), 11u);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 3u);
|
||||
bs.skip(8);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 11u);
|
||||
TS_ASSERT_EQUALS(bs.peekBits(6), 4u);
|
||||
TS_ASSERT(!bs.eos());
|
||||
}
|
||||
public:
|
||||
void test_peek_bits() {
|
||||
tmpl_peek_bits<Common::MemoryReadStream, Common::BitStream8MSB>();
|
||||
tmpl_peek_bits<Common::BitStreamMemoryStream, Common::BitStreamMemory8MSB>();
|
||||
}
|
||||
|
||||
private:
|
||||
template<class MS, class BS>
|
||||
void tmpl_eos() {
|
||||
byte contents[] = { 'a', 'b' };
|
||||
|
||||
MS ms(contents, sizeof(contents));
|
||||
|
||||
BS bs(ms);
|
||||
bs.skip(11);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 11u);
|
||||
TS_ASSERT_EQUALS(bs.getBits(5), 2u);
|
||||
TS_ASSERT(bs.eos());
|
||||
|
||||
bs.rewind();
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
TS_ASSERT(!bs.eos());
|
||||
}
|
||||
public:
|
||||
void test_eos() {
|
||||
tmpl_eos<Common::MemoryReadStream, Common::BitStream8MSB>();
|
||||
tmpl_eos<Common::BitStreamMemoryStream, Common::BitStreamMemory8MSB>();
|
||||
}
|
||||
|
||||
private:
|
||||
template<class MS, class BS>
|
||||
void tmpl_get_bits_lsb() {
|
||||
byte contents[] = { 'a', 'b' };
|
||||
|
||||
MS ms(contents, sizeof(contents));
|
||||
|
||||
BS bs(ms);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
TS_ASSERT_EQUALS(bs.getBits(3), 1u);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 3u);
|
||||
TS_ASSERT_EQUALS(bs.getBits(8), 76u);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 11u);
|
||||
TS_ASSERT(!bs.eos());
|
||||
}
|
||||
public:
|
||||
void test_get_bits_lsb() {
|
||||
tmpl_get_bits_lsb<Common::MemoryReadStream, Common::BitStream8LSB>();
|
||||
tmpl_get_bits_lsb<Common::BitStreamMemoryStream, Common::BitStreamMemory8LSB>();
|
||||
}
|
||||
|
||||
private:
|
||||
template<class MS, class BS>
|
||||
void tmpl_peek_bits_lsb() {
|
||||
byte contents[] = { 'a', 'b' };
|
||||
|
||||
MS ms(contents, sizeof(contents));
|
||||
|
||||
BS bs(ms);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
TS_ASSERT_EQUALS(bs.peekBits(3), 1u);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
bs.skip(3);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 3u);
|
||||
TS_ASSERT_EQUALS(bs.peekBits(8), 76u);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 3u);
|
||||
bs.skip(8);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 11u);
|
||||
TS_ASSERT_EQUALS(bs.peekBits(20), 12u);
|
||||
TS_ASSERT(!bs.eos());
|
||||
}
|
||||
public:
|
||||
void test_peek_bits_lsb() {
|
||||
tmpl_peek_bits_lsb<Common::MemoryReadStream, Common::BitStream8LSB>();
|
||||
tmpl_peek_bits_lsb<Common::BitStreamMemoryStream, Common::BitStreamMemory8LSB>();
|
||||
}
|
||||
|
||||
private:
|
||||
template<class MS, class BS>
|
||||
void tmpl_align() {
|
||||
byte contents[] = { 'a', 'b' };
|
||||
|
||||
MS ms(contents, sizeof(contents));
|
||||
|
||||
BS bs(ms);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
bs.align();
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
bs.skip(3);
|
||||
bs.align();
|
||||
TS_ASSERT_EQUALS(bs.pos(), 8u);
|
||||
}
|
||||
public:
|
||||
void test_align() {
|
||||
tmpl_align<Common::MemoryReadStream, Common::BitStream8LSB>();
|
||||
tmpl_align<Common::BitStreamMemoryStream, Common::BitStreamMemory8LSB>();
|
||||
}
|
||||
|
||||
private:
|
||||
template<class MS, class BS>
|
||||
void tmpl_align_16() {
|
||||
byte contents[] = { 'a', 'b' };
|
||||
|
||||
MS ms(contents, sizeof(contents));
|
||||
|
||||
BS bs(ms);
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
bs.align();
|
||||
TS_ASSERT_EQUALS(bs.pos(), 0u);
|
||||
bs.skip(3);
|
||||
bs.align();
|
||||
TS_ASSERT_EQUALS(bs.pos(), 16u);
|
||||
}
|
||||
public:
|
||||
void test_align_16() {
|
||||
tmpl_align_16<Common::MemoryReadStream, Common::BitStream16BELSB>();
|
||||
tmpl_align_16<Common::BitStreamMemoryStream, Common::BitStreamMemory16BELSB>();
|
||||
}
|
||||
};
|
||||
60
test/common/bufferedreadstream.h
Normal file
60
test/common/bufferedreadstream.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/memstream.h"
|
||||
#include "common/bufferedstream.h"
|
||||
|
||||
class BufferedReadStreamTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_traverse() {
|
||||
byte contents[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
Common::MemoryReadStream ms(contents, 10);
|
||||
|
||||
// Use a buffer size of 4 -- note that 10 % 4 != 0,
|
||||
// so we test what happens if the cache can't be completely
|
||||
// refilled.
|
||||
Common::ReadStream &srs = *Common::wrapBufferedReadStream(&ms, 4, DisposeAfterUse::NO);
|
||||
|
||||
byte i, b;
|
||||
for (i = 0; i < 10; ++i) {
|
||||
TS_ASSERT(!srs.eos());
|
||||
|
||||
b = srs.readByte();
|
||||
TS_ASSERT_EQUALS(i, b);
|
||||
}
|
||||
|
||||
TS_ASSERT(!srs.eos());
|
||||
|
||||
b = srs.readByte();
|
||||
|
||||
TS_ASSERT(srs.eos());
|
||||
|
||||
delete &srs;
|
||||
}
|
||||
|
||||
void test_traverse2() {
|
||||
byte contents[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
Common::MemoryReadStream ms(contents, 9);
|
||||
|
||||
Common::ReadStream &brs = *Common::wrapBufferedReadStream(&ms, 4, DisposeAfterUse::NO);
|
||||
|
||||
// Traverse the stream with reads of 2 bytes. The size is not
|
||||
// a multiple of 2, so we can test the final partial read.
|
||||
|
||||
byte i, b[2];
|
||||
for (i = 0; i < 4; ++i) {
|
||||
TS_ASSERT(!brs.eos());
|
||||
|
||||
int n = brs.read(b, 2);
|
||||
TS_ASSERT_EQUALS(n, 2);
|
||||
}
|
||||
|
||||
TS_ASSERT(!brs.eos());
|
||||
|
||||
int n = brs.read(b, 2);
|
||||
TS_ASSERT_EQUALS(n, 1);
|
||||
|
||||
TS_ASSERT(brs.eos());
|
||||
|
||||
delete &brs;
|
||||
}
|
||||
};
|
||||
94
test/common/bufferedseekablereadstream.h
Normal file
94
test/common/bufferedseekablereadstream.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/memstream.h"
|
||||
#include "common/bufferedstream.h"
|
||||
|
||||
class BufferedSeekableReadStreamTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_traverse() {
|
||||
byte contents[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
Common::MemoryReadStream ms(contents, 10);
|
||||
|
||||
Common::SeekableReadStream &ssrs
|
||||
= *Common::wrapBufferedSeekableReadStream(&ms, 4, DisposeAfterUse::NO);
|
||||
|
||||
byte i, b;
|
||||
for (i = 0; i < 10; ++i) {
|
||||
TS_ASSERT(!ssrs.eos());
|
||||
|
||||
TS_ASSERT_EQUALS(i, ssrs.pos());
|
||||
|
||||
ssrs.read(&b, 1);
|
||||
TS_ASSERT_EQUALS(i, b);
|
||||
}
|
||||
|
||||
TS_ASSERT(!ssrs.eos());
|
||||
|
||||
TS_ASSERT_EQUALS((uint)0, ssrs.read(&b, 1));
|
||||
TS_ASSERT(ssrs.eos());
|
||||
|
||||
delete &ssrs;
|
||||
}
|
||||
|
||||
void test_seek() {
|
||||
byte contents[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
Common::MemoryReadStream ms(contents, 10);
|
||||
|
||||
Common::SeekableReadStream &ssrs
|
||||
= *Common::wrapBufferedSeekableReadStream(&ms, 4, DisposeAfterUse::NO);
|
||||
byte b;
|
||||
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 0);
|
||||
|
||||
ssrs.seek(1, SEEK_SET);
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 1);
|
||||
b = ssrs.readByte();
|
||||
TS_ASSERT_EQUALS(b, 1);
|
||||
|
||||
ssrs.seek(5, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 7);
|
||||
b = ssrs.readByte();
|
||||
TS_ASSERT_EQUALS(b, 7);
|
||||
|
||||
ssrs.seek(-3, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 5);
|
||||
b = ssrs.readByte();
|
||||
TS_ASSERT_EQUALS(b, 5);
|
||||
|
||||
ssrs.seek(0, SEEK_END);
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 10);
|
||||
TS_ASSERT(!ssrs.eos());
|
||||
b = ssrs.readByte();
|
||||
TS_ASSERT(ssrs.eos());
|
||||
|
||||
ssrs.seek(-3, SEEK_END);
|
||||
TS_ASSERT(!ssrs.eos());
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 7);
|
||||
b = ssrs.readByte();
|
||||
TS_ASSERT_EQUALS(b, 7);
|
||||
|
||||
ssrs.seek(-8, SEEK_END);
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 2);
|
||||
b = ssrs.readByte();
|
||||
TS_ASSERT_EQUALS(b, 2);
|
||||
|
||||
ssrs.seek(5, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 8);
|
||||
ssrs.seek(-1, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 7);
|
||||
b = ssrs.readByte();
|
||||
TS_ASSERT_EQUALS(b, 7);
|
||||
|
||||
byte readBuffer[8];
|
||||
ssrs.seek(0, SEEK_SET);
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 0);
|
||||
ssrs.readByte();
|
||||
b = ssrs.read(&readBuffer, 8);
|
||||
ssrs.seek(-1, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 8);
|
||||
b = ssrs.readByte();
|
||||
TS_ASSERT_EQUALS(b, 8);
|
||||
|
||||
delete &ssrs;
|
||||
}
|
||||
};
|
||||
97
test/common/compression/huffman.h
Normal file
97
test/common/compression/huffman.h
Normal file
@@ -0,0 +1,97 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
#include "common/compression/huffman.h"
|
||||
#include "common/bitstream.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
/**
|
||||
* A test suite for the Huffman decoder in common/compression/huffman.h
|
||||
* The encoding used comes from the example on the Wikipedia page
|
||||
* for Huffman.
|
||||
* TODO: It could be improved by generating one at runtime.
|
||||
*/
|
||||
class HuffmanTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_get_with_full_symbols() {
|
||||
|
||||
/*
|
||||
* The class can be initialized with or without providing
|
||||
* a max_length and a symbol table.
|
||||
* We test with a table.
|
||||
*
|
||||
* Encoding (arbitrary, for testing purpouses):
|
||||
* 0xA=010
|
||||
* 0xB=011
|
||||
* 0xC=11
|
||||
* 0xD=00
|
||||
* 0xE=10
|
||||
*/
|
||||
|
||||
uint32 codeCount = 5;
|
||||
uint8 maxLength = 3;
|
||||
const uint8 lengths[] = {3,3,2,2,2};
|
||||
const uint32 codes[] = {0x2, 0x3, 0x3, 0x0, 0x2};
|
||||
const uint32 symbols[] = {0xA, 0xB, 0xC, 0xD, 0xE};
|
||||
|
||||
Common::Huffman<Common::BitStream8MSB> h(maxLength, codeCount, codes, lengths, symbols);
|
||||
|
||||
byte input[] = {0x4F, 0x20};
|
||||
// Provided input...
|
||||
uint32 expected[] = {0xA, 0xB, 0xC, 0xD, 0xE, 0xD, 0xD};
|
||||
// ..and expected output.
|
||||
|
||||
/*
|
||||
* What should be going on:
|
||||
* 010 011 11 00 10 00 00 = A B C D E D D
|
||||
* = 0100 1111 0010 0000 = 0x4F20
|
||||
*/
|
||||
|
||||
Common::MemoryReadStream ms(input, sizeof(input));
|
||||
Common::BitStream8MSB bs(ms);
|
||||
|
||||
TS_ASSERT_EQUALS(h.getSymbol(bs), expected[0]);
|
||||
TS_ASSERT_EQUALS(h.getSymbol(bs), expected[1]);
|
||||
TS_ASSERT_EQUALS(h.getSymbol(bs), expected[2]);
|
||||
TS_ASSERT_EQUALS(h.getSymbol(bs), expected[3]);
|
||||
TS_ASSERT_EQUALS(h.getSymbol(bs), expected[4]);
|
||||
TS_ASSERT_EQUALS(h.getSymbol(bs), expected[5]);
|
||||
TS_ASSERT_EQUALS(h.getSymbol(bs), expected[6]);
|
||||
}
|
||||
|
||||
void test_get_without_symbols() {
|
||||
|
||||
/*
|
||||
* This is basically the same as test_get_with_full_symbols, but
|
||||
* I only pass the minimal required arguments.
|
||||
* Specifically, I avoid passing the symbols table, so that
|
||||
* array indices are used instead.
|
||||
*
|
||||
* Encoding becomes:
|
||||
*
|
||||
* 0=010
|
||||
* 1=011
|
||||
* 2=11
|
||||
* 3=00
|
||||
* 4=10
|
||||
*/
|
||||
|
||||
uint32 codeCount = 5;
|
||||
const uint8 lengths[] = {3,3,2,2,2};
|
||||
const uint32 codes[] = {0x2, 0x3, 0x3, 0x0, 0x2};
|
||||
|
||||
Common::Huffman<Common::BitStream8MSB> h(0, codeCount, codes, lengths, 0);
|
||||
|
||||
byte input[] = {0x4F, 0x20};
|
||||
uint32 expected[] = {0, 1, 2, 3, 4, 3 ,3};
|
||||
|
||||
Common::MemoryReadStream ms(input, sizeof(input));
|
||||
Common::BitStream8MSB bs(ms);
|
||||
|
||||
TS_ASSERT_EQUALS(h.getSymbol(bs), expected[0]);
|
||||
TS_ASSERT_EQUALS(h.getSymbol(bs), expected[1]);
|
||||
TS_ASSERT_EQUALS(h.getSymbol(bs), expected[2]);
|
||||
TS_ASSERT_EQUALS(h.getSymbol(bs), expected[3]);
|
||||
TS_ASSERT_EQUALS(h.getSymbol(bs), expected[4]);
|
||||
TS_ASSERT_EQUALS(h.getSymbol(bs), expected[5]);
|
||||
TS_ASSERT_EQUALS(h.getSymbol(bs), expected[6]);
|
||||
}
|
||||
};
|
||||
73
test/common/crc.h
Normal file
73
test/common/crc.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/crc.h"
|
||||
#include "common/crc_slow.h"
|
||||
|
||||
namespace {
|
||||
const byte *testStringCRC = (const byte *)"The quick brown fox jumps over the lazy dog";
|
||||
const int testLenCRC = 43;
|
||||
}
|
||||
|
||||
class CrcTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_crc32() {
|
||||
Common::CRC32 crc;
|
||||
TS_ASSERT_EQUALS(crc.crcFast(testStringCRC, testLenCRC), 0x414fa339U);
|
||||
uint32 running = crc.getInitRemainder();
|
||||
for (const byte *ptr = testStringCRC; *ptr; ptr++) {
|
||||
running = crc.processByte(*ptr, running);
|
||||
}
|
||||
TS_ASSERT_EQUALS(crc.finalize(running), 0x414fa339U);
|
||||
}
|
||||
|
||||
void test_crc16() {
|
||||
Common::CRC16 crc;
|
||||
TS_ASSERT_EQUALS(crc.crcFast(testStringCRC, testLenCRC), 0xfcdfU);
|
||||
uint16 running = crc.getInitRemainder();
|
||||
for (const byte *ptr = testStringCRC; *ptr; ptr++) {
|
||||
running = crc.processByte(*ptr, running);
|
||||
}
|
||||
TS_ASSERT_EQUALS(crc.finalize(running), 0xfcdfU);
|
||||
}
|
||||
|
||||
void test_crc_ccitt() {
|
||||
Common::CRC_CCITT crc; // aka ccitt-false
|
||||
TS_ASSERT_EQUALS(crc.crcFast(testStringCRC, testLenCRC), 0x8fddU);
|
||||
uint16 running = crc.getInitRemainder();
|
||||
for (const byte *ptr = testStringCRC; *ptr; ptr++) {
|
||||
running = crc.processByte(*ptr, running);
|
||||
}
|
||||
TS_ASSERT_EQUALS(crc.finalize(running), 0x8fddU);
|
||||
}
|
||||
|
||||
void test_crc_binhex() {
|
||||
Common::CRC_BINHEX crc; // Aka xmodem
|
||||
TS_ASSERT_EQUALS(crc.crcFast(testStringCRC, testLenCRC), 0xf0c8U);
|
||||
uint16 running = crc.getInitRemainder();
|
||||
for (const byte *ptr = testStringCRC; *ptr; ptr++) {
|
||||
running = crc.processByte(*ptr, running);
|
||||
}
|
||||
TS_ASSERT_EQUALS(crc.finalize(running), 0xf0c8U);
|
||||
}
|
||||
|
||||
void test_crc32_slow() {
|
||||
Common::CRC32_Slow crc;
|
||||
TS_ASSERT_EQUALS(crc.crcSlow(testStringCRC, testLenCRC), 0x414fa339U);
|
||||
}
|
||||
|
||||
void test_crc16_slow() {
|
||||
Common::CRC16_Slow crc;
|
||||
TS_ASSERT_EQUALS(crc.crcSlow(testStringCRC, testLenCRC), 0xfcdfU);
|
||||
}
|
||||
|
||||
void test_crc_ccitt_slow() {
|
||||
Common::CRC_CCITT_Slow crc; // aka ccitt-false
|
||||
TS_ASSERT_EQUALS(crc.crcSlow(testStringCRC, testLenCRC), 0x8fddU);
|
||||
}
|
||||
|
||||
void test_crc_binhex_slow() {
|
||||
Common::CRC_BINHEX_Slow crc; // Aka xmodem
|
||||
TS_ASSERT_EQUALS(crc.crcSlow(testStringCRC, testLenCRC), 0xf0c8U);
|
||||
}
|
||||
};
|
||||
274
test/common/encoding.h
Normal file
274
test/common/encoding.h
Normal file
@@ -0,0 +1,274 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/ustr.h"
|
||||
#include "../system/null_osystem.h"
|
||||
|
||||
// We support CJK on all the platforms but it relies on OSystem to read
|
||||
// file which *in test environments* is available only on some platforms
|
||||
#if NULL_OSYSTEM_IS_AVAILABLE
|
||||
#define TEST_CJK 1
|
||||
#else
|
||||
#define TEST_CJK 0
|
||||
#endif
|
||||
|
||||
class EncodingTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_korean() {
|
||||
#if TEST_CJK
|
||||
Common::install_null_g_system();
|
||||
const byte utf8[] = {
|
||||
0xea, 0xb2, 0x8c, 0xec, 0x9e, 0x84, 0xec, 0xa4,
|
||||
0x91, 0xec, 0xa7, 0x80, 0x20, 0xea, 0xb3, 0x84,
|
||||
0xec, 0x86, 0x8d, 0xed, 0x95, 0x98, 0xeb, 0xa0,
|
||||
0xa4, 0xeb, 0xa9, 0xb4, 0x20, 0xec, 0x8a, 0xa4,
|
||||
0xed, 0x8e, 0x98, 0xec, 0x9d, 0xb4, 0xec, 0x8a,
|
||||
0xa4, 0xed, 0x82, 0xa4, 0xeb, 0xa5, 0xbc, 0x20,
|
||||
0xec, 0xb9, 0x98, 0xec, 0x8b, 0x9c, 0xec, 0x98,
|
||||
0xa4, 0x2e, 0x00,
|
||||
};
|
||||
|
||||
const Common::u32char_type_t utf32[] = {
|
||||
0xac8c, 0xc784, 0xc911, 0xc9c0, 0x0020, 0xacc4,
|
||||
0xc18d, 0xd558, 0xb824, 0xba74, 0x0020, 0xc2a4,
|
||||
0xd398, 0xc774, 0xc2a4, 0xd0a4, 0xb97c, 0x0020,
|
||||
0xce58, 0xc2dc, 0xc624, 0x002e, 0
|
||||
};
|
||||
|
||||
const byte uhc[] = {
|
||||
0xb0, 0xd4, 0xc0, 0xd3, 0xc1, 0xdf, 0xc1, 0xf6,
|
||||
0x20, 0xb0, 0xe8, 0xbc, 0xd3, 0xc7, 0xcf, 0xb7,
|
||||
0xc1, 0xb8, 0xe9, 0x20, 0xbd, 0xba, 0xc6, 0xe4,
|
||||
0xc0, 0xcc, 0xbd, 0xba, 0xc5, 0xb0, 0xb8, 0xa6,
|
||||
0x20, 0xc4, 0xa1, 0xbd, 0xc3, 0xbf, 0xc0, 0x2e,
|
||||
0x00
|
||||
};
|
||||
Common::U32String ustr_from_utf8((const char *) utf8, Common::kUtf8);
|
||||
Common::U32String ustr_from_uhc((const char *) uhc, Common::kWindows949);
|
||||
Common::U32String ustr(utf32);
|
||||
Common::String utf8_to_uhc = ustr_from_utf8.encode(Common::kWindows949);
|
||||
Common::String uhc_to_utf8 = ustr_from_uhc.encode(Common::kUtf8);
|
||||
TS_ASSERT_EQUALS(ustr_from_utf8, ustr);
|
||||
TS_ASSERT_EQUALS(ustr_from_uhc, ustr);
|
||||
TS_ASSERT(strcmp((const char *) utf8, uhc_to_utf8.c_str()) == 0);
|
||||
TS_ASSERT(strcmp((const char *) uhc, utf8_to_uhc.c_str()) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_chinese() {
|
||||
#if TEST_CJK
|
||||
Common::install_null_g_system();
|
||||
const byte utf8[] = {
|
||||
0xe9, 0x81, 0x8a, 0xe6, 0x88, 0xb2, 0xe6, 0x9a,
|
||||
0xab, 0xe5, 0x81, 0x9c, 0xe3, 0x80, 0x82, 0xe6,
|
||||
0x8c, 0x89, 0xe4, 0xb8, 0x8b, 0xe7, 0xa9, 0xba,
|
||||
0x21, 0xe7, 0x99, 0xbd, 0xe9, 0x8d, 0xb5, 0xe7,
|
||||
0xb9, 0xbc, 0xe7, 0xba, 0x8c, 0xe9, 0x81, 0x8a,
|
||||
0xe6, 0x88, 0xb2, 0xe3, 0x80, 0x82, 0x00,
|
||||
};
|
||||
|
||||
const Common::u32char_type_t utf32[] = {
|
||||
0x904a, 0x6232, 0x66ab, 0x505c, 0x3002, 0x6309,
|
||||
0x4e0b, 0x7a7a, 0x0021, 0x767d, 0x9375, 0x7e7c,
|
||||
0x7e8c, 0x904a, 0x6232, 0x3002, 0
|
||||
};
|
||||
|
||||
const byte big5[] = {
|
||||
0xb9, 0x43, 0xc0, 0xb8, 0xbc, 0xc8, 0xb0, 0xb1,
|
||||
0xa1, 0x43, 0xab, 0xf6, 0xa4, 0x55, 0xaa, 0xc5,
|
||||
0x21, 0xa5, 0xd5, 0xc1, 0xe4, 0xc4, 0x7e, 0xc4,
|
||||
0xf2, 0xb9, 0x43, 0xc0, 0xb8, 0xa1, 0x43, 0x00
|
||||
};
|
||||
Common::U32String ustr_from_utf8((const char *) utf8, Common::kUtf8);
|
||||
Common::U32String ustr_from_big5((const char *) big5, Common::kWindows950);
|
||||
Common::U32String ustr(utf32);
|
||||
Common::String utf8_to_big5 = ustr_from_utf8.encode(Common::kWindows950);
|
||||
Common::String big5_to_utf8 = ustr_from_big5.encode(Common::kUtf8);
|
||||
TS_ASSERT_EQUALS(ustr_from_utf8, ustr);
|
||||
TS_ASSERT_EQUALS(ustr_from_big5, ustr);
|
||||
TS_ASSERT(strcmp((const char *) utf8, big5_to_utf8.c_str()) == 0);
|
||||
TS_ASSERT(strcmp((const char *) big5, utf8_to_big5.c_str()) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_japanese() {
|
||||
#if TEST_CJK
|
||||
Common::install_null_g_system();
|
||||
const byte utf8[] = {
|
||||
0xe4, 0xb8, 0x80, 0xe6, 0x99, 0x82, 0xe5, 0x81,
|
||||
0x9c, 0xe6, 0xad, 0xa2, 0xe3, 0x80, 0x82, 0xe7,
|
||||
0xb6, 0x9a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8b,
|
||||
0xe5, 0xa0, 0xb4, 0xe5, 0x90, 0x88, 0xe3, 0x81,
|
||||
0xaf, 0xe3, 0x82, 0xb9, 0xe3, 0x83, 0x9a, 0xe3,
|
||||
0x83, 0xbc, 0xe3, 0x82, 0xb9, 0xe3, 0x83, 0x90,
|
||||
0xe3, 0x83, 0xbc, 0xe3, 0x82, 0x92, 0xe6, 0x8a,
|
||||
0xbc, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xa6, 0xe3,
|
||||
0x81, 0x8f, 0xe3, 0x81, 0xa0, 0xe3, 0x81, 0x95,
|
||||
0xe3, 0x81, 0x84, 0xe3, 0x80, 0x82, 0
|
||||
};
|
||||
|
||||
const Common::u32char_type_t utf32[] = {
|
||||
0x4e00, 0x6642, 0x505c, 0x6b62, 0x3002, 0x7d9a,
|
||||
0x3051, 0x308b, 0x5834, 0x5408, 0x306f, 0x30b9,
|
||||
0x30da, 0x30fc, 0x30b9, 0x30d0, 0x30fc, 0x3092,
|
||||
0x62bc, 0x3057, 0x3066, 0x304f, 0x3060, 0x3055,
|
||||
0x3044, 0x3002, 0
|
||||
};
|
||||
|
||||
const byte cp932[] = {
|
||||
0x88, 0xea, 0x8e, 0x9e, 0x92, 0xe2, 0x8e, 0x7e,
|
||||
0x81, 0x42, 0x91, 0xb1, 0x82, 0xaf, 0x82, 0xe9,
|
||||
0x8f, 0xea, 0x8d, 0x87, 0x82, 0xcd, 0x83, 0x58,
|
||||
0x83, 0x79, 0x81, 0x5b, 0x83, 0x58, 0x83, 0x6f,
|
||||
0x81, 0x5b, 0x82, 0xf0, 0x89, 0x9f, 0x82, 0xb5,
|
||||
0x82, 0xc4, 0x82, 0xad, 0x82, 0xbe, 0x82, 0xb3,
|
||||
0x82, 0xa2, 0x81, 0x42, 0
|
||||
};
|
||||
Common::U32String ustr_from_utf8((const char *) utf8, Common::kUtf8);
|
||||
Common::U32String ustr_from_cp932((const char *) cp932, Common::kWindows932);
|
||||
Common::U32String ustr(utf32);
|
||||
Common::String utf8_to_cp932 = ustr_from_utf8.encode(Common::kWindows932);
|
||||
Common::String cp932_to_utf8 = ustr_from_cp932.encode(Common::kUtf8);
|
||||
TS_ASSERT_EQUALS(ustr_from_utf8, ustr);
|
||||
TS_ASSERT_EQUALS(ustr_from_cp932, ustr);
|
||||
TS_ASSERT(strcmp((const char *) utf8, cp932_to_utf8.c_str()) == 0);
|
||||
TS_ASSERT(strcmp((const char *) cp932, utf8_to_cp932.c_str()) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_conversion_unicode_machine_endian() {
|
||||
// |dolar| cent | euro |
|
||||
unsigned char utf8[] = {0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0};
|
||||
#ifdef SCUMM_BIG_ENDIAN
|
||||
//| dolar | cent | euro |
|
||||
unsigned char utf16be[] = {0, 0x24, 0, 0xA2, 0x20, 0xAC, 0, 0};
|
||||
//| dolar | cent | euro
|
||||
unsigned char utf32be[] = {0, 0, 0, 0x24, 0, 0, 0, 0xA2, 0, 0, 0x20, 0xAC, 0, 0, 0, 0};
|
||||
|
||||
unsigned char *utf16 = utf16be;
|
||||
unsigned char *utf32 = utf32be;
|
||||
#else
|
||||
//| dolar | cent | euro |
|
||||
unsigned char utf16le[] = {0x24, 0, 0xA2, 0, 0xAC, 0x20, 0, 0};
|
||||
//| dolar | cent | euro
|
||||
unsigned char utf32le[] = {0x24, 0, 0, 0, 0xA2, 0, 0, 0, 0xAC, 0x20, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
unsigned char *utf16 = utf16le;
|
||||
unsigned char *utf32 = utf32le;
|
||||
#endif
|
||||
|
||||
// UTF16 to UTF8
|
||||
Common::String resultstr8 = Common::U32String::decodeUTF16Native((uint16 *) utf16, 3).encode(Common::kUtf8);
|
||||
TS_ASSERT(resultstr8.c_str() != NULL);
|
||||
TS_ASSERT_EQUALS(memcmp(resultstr8.c_str(), utf8, 7), 0)
|
||||
|
||||
// UTF32 to UTF8
|
||||
|
||||
resultstr8 = Common::U32String((Common::u32char_type_t *) utf32, 3).encode(Common::kUtf8);
|
||||
TS_ASSERT(resultstr8.c_str() != NULL);
|
||||
TS_ASSERT_EQUALS(memcmp(resultstr8.c_str(), utf8, 7), 0);
|
||||
|
||||
// UTF32 to UTF16
|
||||
uint16 *result16 = Common::U32String((Common::u32char_type_t *) utf32, 3).encodeUTF16Native(NULL);
|
||||
TS_ASSERT(result16 != NULL);
|
||||
TS_ASSERT_EQUALS(memcmp(result16, utf16, 8), 0);
|
||||
delete[] result16;
|
||||
|
||||
// UTF8 to UTF16
|
||||
|
||||
result16 = Common::U32String((char *) utf8, 6, Common::kUtf8).encodeUTF16Native(NULL);
|
||||
TS_ASSERT(result16 != NULL);
|
||||
TS_ASSERT_EQUALS(memcmp(result16, utf16, 8), 0);
|
||||
delete[] result16;
|
||||
|
||||
// UTF8 to UTF32
|
||||
Common::U32String resultustr = Common::String((const char *) utf8, 6).decode(Common::kUtf8);
|
||||
TS_ASSERT_EQUALS(memcmp(resultustr.c_str(), utf32, 16), 0);
|
||||
|
||||
// UTF16 to UTF32
|
||||
resultustr = Common::U32String::decodeUTF16Native((uint16 *) utf16, 3);
|
||||
TS_ASSERT_EQUALS(memcmp(resultustr.c_str(), utf32, 16), 0);
|
||||
}
|
||||
|
||||
void test_conversion_unicode_big_endian() {
|
||||
// |dolar| cent | euro |
|
||||
unsigned char utf8[] = {0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0};
|
||||
//| dolar | cent | euro |
|
||||
unsigned char utf16be[] = {0, 0x24, 0, 0xA2, 0x20, 0xAC, 0, 0};
|
||||
|
||||
// UTF16 to UTF8
|
||||
Common::String resultstr8 = Common::U32String::decodeUTF16BE((uint16 *) utf16be, 3).encode(Common::kUtf8);
|
||||
TS_ASSERT(resultstr8.c_str() != NULL);
|
||||
TS_ASSERT_EQUALS(memcmp(resultstr8.c_str(), utf8, 7), 0);
|
||||
|
||||
|
||||
// UTF8 to UTF16
|
||||
uint16 *result16 = Common::U32String((char *) utf8, 6, Common::kUtf8).encodeUTF16BE(NULL);
|
||||
TS_ASSERT(result16 != NULL);
|
||||
TS_ASSERT_EQUALS(memcmp(result16, utf16be, 8), 0);
|
||||
delete[] result16;
|
||||
|
||||
}
|
||||
|
||||
void test_conversion_unicode_little_endian() {
|
||||
// |dolar| cent | euro |
|
||||
unsigned char utf8[] = {0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0};
|
||||
//| dolar | cent | euro |
|
||||
unsigned char utf16le[] = {0x24, 0, 0xA2, 0, 0xAC, 0x20, 0, 0};
|
||||
|
||||
// UTF16 to UTF8
|
||||
Common::String resultstr8 = Common::U32String::decodeUTF16LE((uint16 *) utf16le, 3).encode(Common::kUtf8);
|
||||
TS_ASSERT(resultstr8.c_str() != NULL);
|
||||
TS_ASSERT_EQUALS(memcmp(resultstr8.c_str(), utf8, 7), 0);
|
||||
|
||||
// UTF8 to UTF16
|
||||
uint16 *result16 = Common::U32String((char *) utf8, 6, Common::kUtf8).encodeUTF16LE(NULL);
|
||||
TS_ASSERT(result16 != NULL);
|
||||
TS_ASSERT_EQUALS(memcmp(result16, utf16le, 8), 0);
|
||||
delete[] result16;
|
||||
|
||||
}
|
||||
|
||||
void test_cyrillic_transliteration() {
|
||||
unsigned char utf8[] = {/* Z */0xD0, 0x97, /* d */ 0xD0, 0xB4, /* r */ 0xD1, 0x80, /* a */ 0xD0, 0xB0, /* v */ 0xD0, 0xB2, /* s */ 0xD1, 0x81, /* t */ 0xD1, 0x82, /* v */ 0xD0, 0xB2, /* u */ 0xD1, 0x83, /* j */ 0xD0, 0xB9, /* t */ 0xD1, 0x82, /* e */ 0xD0, 0xB5, 0};
|
||||
unsigned char iso_8859_5[] = {0xB7, 0xD4, 0xE0, 0xD0, 0xD2, 0xE1, 0xE2, 0xD2, 0xE3, 0xD9, 0xE2, 0xD5, 0};
|
||||
unsigned char ascii[] = "Zdravstvujte";
|
||||
|
||||
Common::String result = Common::U32String((const char *) utf8, 24, Common::kUtf8).encode(Common::kASCII);
|
||||
TS_ASSERT_EQUALS(memcmp(result.c_str(), ascii, 13), 0);
|
||||
|
||||
result = Common::U32String((const char *) iso_8859_5, 12, Common::kISO8859_5).encode(Common::kASCII);
|
||||
TS_ASSERT_EQUALS(memcmp(result.c_str(), ascii, 13), 0);
|
||||
|
||||
result = Common::U32String((const char *) iso_8859_5, 12, Common::kISO8859_5).encode(Common::kUtf8);
|
||||
TS_ASSERT_EQUALS(memcmp(result.c_str(), utf8, 25), 0);
|
||||
|
||||
result = Common::U32String((const char *) utf8, 24, Common::kUtf8).encode(Common::kISO8859_5);
|
||||
TS_ASSERT_EQUALS(memcmp(result.c_str(), iso_8859_5, 13), 0);
|
||||
|
||||
// this should stay the same
|
||||
result = Common::U32String((const char *) ascii, 12, Common::kASCII).encode(Common::kISO8859_5);
|
||||
TS_ASSERT_EQUALS(memcmp(result.c_str(), ascii, 13), 0);
|
||||
}
|
||||
|
||||
void test_other_conversions() {
|
||||
unsigned char cp850[] = {0x99, 0xE0, 0xEA, 0x41, 0x64, 0};
|
||||
unsigned char utf8_1[] = {0xC3, 0x96, 0xC3, 0x93, 0xC3, 0x9B, 0x41, 0x64, 0};
|
||||
|
||||
unsigned char iso_8859_2[] = {0xA9, 0xE1, 0x6C, 0x65, 0xE8, 0x65, 0x6B, 0};
|
||||
unsigned char utf8_2[] = {0xC5, 0xA0, 0xC3, 0xA1, 0x6C, 0x65, 0xC4, 0x8D, 0x65, 0x6B, 0};
|
||||
|
||||
Common::String result = Common::U32String((const char *) cp850, sizeof(cp850)-1, Common::kDos850).encode(Common::kUtf8);
|
||||
TS_ASSERT_EQUALS(memcmp(result.c_str(), utf8_1, sizeof(utf8_1)), 0);
|
||||
|
||||
result = Common::U32String((const char *) utf8_1, sizeof(utf8_1)-1, Common::kUtf8).encode(Common::kDos850);
|
||||
TS_ASSERT_EQUALS(memcmp(result.c_str(), cp850, sizeof(cp850)), 0);
|
||||
|
||||
result = Common::U32String((const char *) iso_8859_2, sizeof(iso_8859_2)-1, Common::kISO8859_2).encode(Common::kUtf8);
|
||||
TS_ASSERT_EQUALS(memcmp(result.c_str(), utf8_2, sizeof(utf8_2)), 0);
|
||||
|
||||
result = Common::U32String((const char *) utf8_2, sizeof(utf8_2)-1, Common::kUtf8).encode(Common::kISO8859_2);
|
||||
TS_ASSERT_EQUALS(memcmp(result.c_str(), iso_8859_2, sizeof(iso_8859_2)), 0);
|
||||
}
|
||||
};
|
||||
114
test/common/endian.h
Normal file
114
test/common/endian.h
Normal file
@@ -0,0 +1,114 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
#include "common/endian.h"
|
||||
|
||||
class EndianTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_MKTAG() {
|
||||
const char *str_tag = "ABCD";
|
||||
uint32 tag = READ_BE_UINT32(str_tag);
|
||||
TS_ASSERT_EQUALS(MKTAG('A','B','C','D'), tag);
|
||||
}
|
||||
|
||||
void test_READ_BE_UINT64() {
|
||||
const byte data[8] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF};
|
||||
uint64 value = READ_BE_UINT64(data);
|
||||
TS_ASSERT_EQUALS(value, 0x123456789ABCDEFFULL);
|
||||
}
|
||||
|
||||
void test_READ_LE_UINT64() {
|
||||
const byte data[8] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF};
|
||||
uint64 value = READ_LE_UINT64(data);
|
||||
TS_ASSERT_EQUALS(value, 0xFFDEBC9A78563412ULL);
|
||||
}
|
||||
|
||||
void test_READ_BE_UINT32() {
|
||||
const char data[4] = { 0x12, 0x34, 0x56, 0x78 };
|
||||
uint32 value = READ_BE_UINT32(data);
|
||||
TS_ASSERT_EQUALS(value, 0x12345678UL);
|
||||
}
|
||||
|
||||
void test_READ_LE_UINT32() {
|
||||
const char data[4] = { 0x12, 0x34, 0x56, 0x78 };
|
||||
uint32 value = READ_LE_UINT32(data);
|
||||
TS_ASSERT_EQUALS(value, 0x78563412UL);
|
||||
}
|
||||
|
||||
void test_READ_BE_UINT16() {
|
||||
const char data[4] = { 0x12, 0x34, 0x56, 0x78 };
|
||||
uint32 value = READ_BE_UINT16(data);
|
||||
TS_ASSERT_EQUALS(value, 0x1234UL);
|
||||
}
|
||||
|
||||
void test_READ_LE_UINT16() {
|
||||
const char data[4] = { 0x12, 0x34, 0x56, 0x78 };
|
||||
uint32 value = READ_LE_UINT16(data);
|
||||
TS_ASSERT_EQUALS(value, 0x3412UL);
|
||||
}
|
||||
|
||||
void test_READ_BE_FLOAT32() {
|
||||
const uint8 data[4] = { 0x40, 0x49, 0x0f, 0xdc };
|
||||
float value = READ_BE_FLOAT32(data);
|
||||
TS_ASSERT_EQUALS(value, 3.141593f);
|
||||
}
|
||||
|
||||
void test_READ_LE_FLOAT32() {
|
||||
const uint8 data[4] = { 0xdc, 0x0f, 0x49, 0x40 };
|
||||
float value = READ_LE_FLOAT32(data);
|
||||
TS_ASSERT_EQUALS(value, 3.141593f);
|
||||
}
|
||||
|
||||
void test_READ_BE_FLOAT64() {
|
||||
const uint8 data[8] = { 0x40, 0x09, 0x21, 0xfb, 0x82, 0xc2, 0xbd, 0x7f };
|
||||
double value = READ_BE_FLOAT64(data);
|
||||
TS_ASSERT_EQUALS(value, 3.141593);
|
||||
}
|
||||
|
||||
void test_READ_LE_FLOAT64() {
|
||||
const uint8 data[8] = { 0x7f, 0xbd, 0xc2, 0x82, 0xfb, 0x21, 0x09, 0x40 };
|
||||
double value = READ_LE_FLOAT64(data);
|
||||
TS_ASSERT_EQUALS(value, 3.141593);
|
||||
}
|
||||
|
||||
void test_READ_FPA_FLOAT64() {
|
||||
const uint8 data[8] = { 0xfb, 0x21, 0x09, 0x40, 0x7f, 0xbd, 0xc2, 0x82 };
|
||||
double value = READ_FPA_FLOAT64(data);
|
||||
TS_ASSERT_EQUALS(value, 3.141593);
|
||||
}
|
||||
|
||||
void test_WRITE_BE_FLOAT32() {
|
||||
const uint8 data[4] = { 0x40, 0x49, 0x0f, 0xdc };
|
||||
uint8 out[4];
|
||||
WRITE_BE_FLOAT32(out, 3.141593f);
|
||||
TS_ASSERT_EQUALS(memcmp(data, out, 4), 0);
|
||||
}
|
||||
|
||||
void test_WRITE_LE_FLOAT32() {
|
||||
const uint8 data[4] = { 0xdc, 0x0f, 0x49, 0x40 };
|
||||
uint8 out[4];
|
||||
WRITE_LE_FLOAT32(out, 3.141593f);
|
||||
TS_ASSERT_EQUALS(memcmp(data, out, 4), 0);
|
||||
}
|
||||
|
||||
void test_WRITE_BE_FLOAT64() {
|
||||
const uint8 data[8] = { 0x40, 0x09, 0x21, 0xfb, 0x82, 0xc2, 0xbd, 0x7f };
|
||||
uint8 out[8];
|
||||
WRITE_BE_FLOAT64(out, 3.141593);
|
||||
TS_ASSERT_EQUALS(memcmp(data, out, 8), 0);
|
||||
}
|
||||
|
||||
void test_WRITE_LE_FLOAT64() {
|
||||
const uint8 data[8] = { 0x7f, 0xbd, 0xc2, 0x82, 0xfb, 0x21, 0x09, 0x40 };
|
||||
uint8 out[8];
|
||||
WRITE_LE_FLOAT64(out, 3.141593);
|
||||
TS_ASSERT_EQUALS(memcmp(data, out, 8), 0);
|
||||
}
|
||||
|
||||
void test_WRITE_FPA_FLOAT64() {
|
||||
const uint8 data[8] = { 0xfb, 0x21, 0x09, 0x40, 0x7f, 0xbd, 0xc2, 0x82 };
|
||||
uint8 out[8];
|
||||
WRITE_FPA_FLOAT64(out, 3.141593);
|
||||
TS_ASSERT_EQUALS(memcmp(data, out, 8), 0);
|
||||
}
|
||||
|
||||
};
|
||||
83
test/common/fixedstack.h
Normal file
83
test/common/fixedstack.h
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/stack.h"
|
||||
|
||||
class FixedStackTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_empty_clear() {
|
||||
Common::FixedStack<int> stack;
|
||||
TS_ASSERT(stack.empty());
|
||||
|
||||
stack.push(1);
|
||||
stack.push(2);
|
||||
TS_ASSERT(!stack.empty());
|
||||
|
||||
stack.clear();
|
||||
|
||||
TS_ASSERT(stack.empty());
|
||||
}
|
||||
|
||||
void test_size() {
|
||||
typedef Common::FixedStack<int> Stack;
|
||||
|
||||
Stack stack;
|
||||
TS_ASSERT_EQUALS(stack.size(), (Stack::size_type)0);
|
||||
|
||||
stack.push(5);
|
||||
TS_ASSERT_EQUALS(stack.size(), (Stack::size_type)1);
|
||||
|
||||
stack.push(9);
|
||||
stack.push(0);
|
||||
TS_ASSERT_EQUALS(stack.size(), (Stack::size_type)3);
|
||||
|
||||
stack.pop();
|
||||
TS_ASSERT_EQUALS(stack.size(), (Stack::size_type)2);
|
||||
}
|
||||
|
||||
void test_top_pop() {
|
||||
Common::FixedStack<int> stack;
|
||||
|
||||
stack.push( 42);
|
||||
stack.push(-23);
|
||||
|
||||
TS_ASSERT_EQUALS(stack[0], 42);
|
||||
TS_ASSERT_EQUALS(stack.top(), -23);
|
||||
|
||||
stack[0] = -23;
|
||||
stack.top() = 42;
|
||||
TS_ASSERT_EQUALS(stack[0], -23);
|
||||
TS_ASSERT_EQUALS(stack.top(), 42);
|
||||
|
||||
stack.pop();
|
||||
TS_ASSERT_EQUALS(stack[0], -23);
|
||||
}
|
||||
|
||||
void test_assign() {
|
||||
Common::FixedStack<int> q1, q2;
|
||||
|
||||
for (int i = 0; i <= 4; ++i) {
|
||||
q1.push(4-i);
|
||||
q2.push(i);
|
||||
}
|
||||
|
||||
Common::FixedStack<int> q3(q1);
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
TS_ASSERT_EQUALS(q3.top(), i);
|
||||
q3.pop();
|
||||
}
|
||||
|
||||
TS_ASSERT(q3.empty());
|
||||
|
||||
q3 = q2;
|
||||
|
||||
for (int i = 4; i >= 0; --i) {
|
||||
TS_ASSERT_EQUALS(q3.top(), i);
|
||||
q3.pop();
|
||||
}
|
||||
|
||||
TS_ASSERT(q3.empty());
|
||||
TS_ASSERT(!q1.empty());
|
||||
TS_ASSERT(!q2.empty());
|
||||
}
|
||||
};
|
||||
83
test/common/formats/quicktime.h
Normal file
83
test/common/formats/quicktime.h
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
#include "common/util.h"
|
||||
#include "common/formats/quicktime.h"
|
||||
|
||||
static const byte VALID_MOOV_DATA[] = { // a minimally 'correct' quicktime file.
|
||||
// size 'moov' size 'mdat'
|
||||
0x0, 0x0, 0x0, 0x8, 0x6d, 0x6f, 0x6f, 0x76, 0x0, 0x0, 0x0, 0x8, 0x6d, 0x64, 0x61, 0x74
|
||||
};
|
||||
|
||||
static const byte VALID_MHDR_DATA[] = { // a 'correct' quicktime file with a header
|
||||
// size (incl mvhd) 'moov'
|
||||
0x0, 0x0, 0x0, 0x74, 0x6d, 0x6f, 0x6f, 0x76,
|
||||
//size (27*4) 'mvhd' vers 3bytes flags
|
||||
0x0, 0x0, 0x0, 0x6c, 0x6d, 0x76, 0x68, 0x64, 0x00, 0xff, 0xff, 0xff,
|
||||
// creation modification timescale (60?) length (999 * 60)+ 1
|
||||
0x65, 0x52, 0xef, 0x5b, 0x65, 0x52, 0xef, 0x5b, 0x0, 0x0, 0x0, 0x3c, 0x0, 0x0, 0xea, 0x25,
|
||||
// preferred scale, vol, [10 bytes reserved]
|
||||
0x0, 0x0, 0x0, 0x1, 0x0, 0x10, 0,0,0,0,0,0,0,0,0,0,
|
||||
// display matrix, mostly ignored by parser except xMod (0x8000) and yMod (0xa000)
|
||||
0x0, 0x0, 0x80, 0x0, 0,0,0,0,0,0,0,0,0,0,0,0, 0x0, 0x0, 0xa0, 0x0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
// 7 more 32-bit values
|
||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||
// size 'mdat'
|
||||
0x0, 0x0, 0x0, 0x8, 0x6d, 0x64, 0x61, 0x74
|
||||
};
|
||||
|
||||
|
||||
class QuickTimeTestParser : public Common::QuickTimeParser {
|
||||
public:
|
||||
uint32 getDuration() const { return _duration; }
|
||||
const Common::Rational &getScaleFactorX() const { return _scaleFactorX; }
|
||||
const Common::Rational &getScaleFactorY() const { return _scaleFactorY; }
|
||||
const Common::Array<Track *> &getTracks() const { return _tracks; }
|
||||
|
||||
SampleDesc *readSampleDesc(Track *track, uint32 format, uint32 descSize) override {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class QuicktimeParserTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_streamAtEOS() {
|
||||
QuickTimeTestParser parser;
|
||||
const byte data[] = "";
|
||||
Common::MemoryReadStream stream(data, sizeof(data));
|
||||
stream.readByte(); // read the null char
|
||||
bool result = parser.parseStream(&stream, DisposeAfterUse::NO);
|
||||
TS_ASSERT(!result);
|
||||
}
|
||||
|
||||
void test_streamInvalid() {
|
||||
QuickTimeTestParser parser;
|
||||
const byte data[] = "not a moov";
|
||||
Common::MemoryReadStream stream(data, sizeof(data));
|
||||
bool result = parser.parseStream(&stream, DisposeAfterUse::NO);
|
||||
TS_ASSERT(!result);
|
||||
}
|
||||
|
||||
void test_moov() {
|
||||
QuickTimeTestParser parser;
|
||||
Common::MemoryReadStream stream(VALID_MOOV_DATA, sizeof(VALID_MOOV_DATA));
|
||||
bool result = parser.parseStream(&stream, DisposeAfterUse::NO);
|
||||
TS_ASSERT(result);
|
||||
}
|
||||
|
||||
void test_mhdr() {
|
||||
QuickTimeTestParser parser;
|
||||
Common::MemoryReadStream stream(VALID_MHDR_DATA, sizeof(VALID_MHDR_DATA));
|
||||
bool result = parser.parseStream(&stream, DisposeAfterUse::NO);
|
||||
TS_ASSERT(result);
|
||||
TS_ASSERT_EQUALS(parser.getDuration(), 999*60 + 1);
|
||||
TS_ASSERT_EQUALS(parser.getScaleFactorX(), Common::Rational(0x10000, 0x8000));
|
||||
TS_ASSERT_EQUALS(parser.getScaleFactorY(), Common::Rational(0x10000, 0xa000));
|
||||
}
|
||||
|
||||
void test_mhdrEarlyEOF() {
|
||||
QuickTimeTestParser parser;
|
||||
Common::MemoryReadStream stream(VALID_MHDR_DATA, sizeof(VALID_MHDR_DATA) - 10);
|
||||
bool result = parser.parseStream(&stream, DisposeAfterUse::NO);
|
||||
TS_ASSERT(!result);
|
||||
}
|
||||
|
||||
};
|
||||
60
test/common/func.h
Normal file
60
test/common/func.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/func.h"
|
||||
|
||||
void myFunction1(int &dst, const int src) { dst = src; }
|
||||
void myFunction2(const int src, int &dst) { dst = src; }
|
||||
|
||||
class FuncTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_bind1st() {
|
||||
int dst = 0;
|
||||
Common::bind1st(Common::ptr_fun(myFunction1), dst)(1);
|
||||
TS_ASSERT_EQUALS(dst, 1);
|
||||
}
|
||||
|
||||
void test_bind2nd() {
|
||||
int dst = 0;
|
||||
Common::bind2nd(Common::ptr_fun(myFunction2), dst)(1);
|
||||
TS_ASSERT_EQUALS(dst, 1);
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
void fooAdd(int &foo) {
|
||||
++foo;
|
||||
}
|
||||
|
||||
void fooSub(int &foo) const {
|
||||
--foo;
|
||||
}
|
||||
};
|
||||
|
||||
void test_mem_fun_ref() {
|
||||
Foo myFoos[4];
|
||||
int counter = 0;
|
||||
|
||||
Common::for_each(myFoos, myFoos+4, Common::bind2nd(Common::mem_fun_ref(&Foo::fooAdd), counter));
|
||||
TS_ASSERT_EQUALS(counter, 4);
|
||||
|
||||
Common::for_each(myFoos, myFoos+4, Common::bind2nd(Common::mem_fun_ref(&Foo::fooSub), counter));
|
||||
TS_ASSERT_EQUALS(counter, 0);
|
||||
}
|
||||
|
||||
void test_mem_fun() {
|
||||
Foo *myFoos[4];
|
||||
for (int i = 0; i < 4; ++i)
|
||||
myFoos[i] = new Foo;
|
||||
|
||||
int counter = 0;
|
||||
|
||||
Common::for_each(myFoos, myFoos+4, Common::bind2nd(Common::mem_fun(&Foo::fooAdd), counter));
|
||||
TS_ASSERT_EQUALS(counter, 4);
|
||||
|
||||
Common::for_each(myFoos, myFoos+4, Common::bind2nd(Common::mem_fun(&Foo::fooSub), counter));
|
||||
TS_ASSERT_EQUALS(counter, 0);
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
delete myFoos[i];
|
||||
}
|
||||
};
|
||||
164
test/common/hash-str.h
Normal file
164
test/common/hash-str.h
Normal file
@@ -0,0 +1,164 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
#include "common/hash-str.h"
|
||||
|
||||
/**
|
||||
* Test suite for common/hash-str.h
|
||||
* We test a number of case sensitive/insensitive hash and compare functions
|
||||
* using example strings and known hashes, trying to tackle
|
||||
* as much edge cases as possible.
|
||||
*/
|
||||
class HashStrTestSuite : public CxxTest::TestSuite {
|
||||
|
||||
public:
|
||||
void test_case_sensitive_string_equal_to() {
|
||||
|
||||
// Name says it all.
|
||||
// This verifies that the function returns true
|
||||
// for exactly the same string, false for the same
|
||||
// string in mixed case and false for some edge cases
|
||||
// with various spacings plus one character replaced
|
||||
// by itself+128 (if there's some processing done after
|
||||
// conversion to 7-bit ASCII this might yield funny results).
|
||||
|
||||
const Common::String lower("test");
|
||||
const Common::String lower1("test");
|
||||
const Common::String mixed("tESt");
|
||||
const Common::String spaced("test ");
|
||||
const Common::String doublespaced("test ");
|
||||
const Common::String tabbed("test\t");
|
||||
const Common::String plus128("t\345est");
|
||||
// 'e'+128 = 0xE5 = 0o345
|
||||
|
||||
Common::CaseSensitiveString_EqualTo css_et;
|
||||
TS_ASSERT_EQUALS(css_et(lower, mixed), false);
|
||||
TS_ASSERT_EQUALS(css_et(lower, lower1), true);
|
||||
TS_ASSERT_EQUALS(css_et(lower, lower), true);
|
||||
|
||||
// Different sorts of whitespace are to be treated differently.
|
||||
TS_ASSERT_EQUALS(css_et(lower, spaced), false);
|
||||
TS_ASSERT_EQUALS(css_et(lower, tabbed), false);
|
||||
TS_ASSERT_EQUALS(css_et(spaced, tabbed), false);
|
||||
TS_ASSERT_EQUALS(css_et(spaced, doublespaced), false);
|
||||
TS_ASSERT_EQUALS(css_et(lower, plus128), false);
|
||||
}
|
||||
|
||||
void test_ignore_case_equal_to() {
|
||||
|
||||
// This should be probably called case_insensitive_string_equal_to
|
||||
// or something,but it's basically the same thing as
|
||||
// test_case_sensitive_string_equal_to, only it's case
|
||||
// insensitive.
|
||||
|
||||
const Common::String lower("test");
|
||||
const Common::String lower1("test");
|
||||
const Common::String mixed("tESt");
|
||||
const Common::String spaced("test ");
|
||||
const Common::String mixedspaced("tESt ");
|
||||
const Common::String doublespaced("test ");
|
||||
const Common::String tabbed("test\t");
|
||||
const Common::String plus128("t\345est");
|
||||
|
||||
Common::IgnoreCase_EqualTo ic_et;
|
||||
TS_ASSERT_EQUALS(ic_et(lower, mixed), true);
|
||||
TS_ASSERT_EQUALS(ic_et(lower, lower1), true);
|
||||
TS_ASSERT_EQUALS(ic_et(lower, lower), true);
|
||||
// Edge case:
|
||||
TS_ASSERT_EQUALS(ic_et(spaced, mixedspaced), true);
|
||||
|
||||
// Different sorts of whitespace are to be treated differently.
|
||||
TS_ASSERT_EQUALS(ic_et(lower, spaced), false);
|
||||
TS_ASSERT_EQUALS(ic_et(lower, tabbed), false);
|
||||
TS_ASSERT_EQUALS(ic_et(spaced, tabbed), false);
|
||||
TS_ASSERT_EQUALS(ic_et(spaced, doublespaced), false);
|
||||
TS_ASSERT_EQUALS(ic_et(lower, plus128), false);
|
||||
}
|
||||
|
||||
void test_case_sensitive_string_hash() {
|
||||
|
||||
// Here we compute string hashes for different
|
||||
// strings and see that the functor is case sensitive
|
||||
// and does not ignore spaces.
|
||||
|
||||
const Common::String lower("test");
|
||||
const Common::String lower1("test");
|
||||
const Common::String mixed("tESt");
|
||||
const Common::String spaced("test ");
|
||||
const Common::String mixedspaced("tESt ");
|
||||
const Common::String doublespaced("test ");
|
||||
const Common::String tabbed("test\t");
|
||||
|
||||
Common::CaseSensitiveString_Hash css_h;
|
||||
TS_ASSERT_EQUALS(css_h(lower), css_h(lower1));
|
||||
TS_ASSERT_DIFFERS(css_h(mixed), css_h(lower));
|
||||
TS_ASSERT_DIFFERS(css_h(spaced), css_h(lower));
|
||||
TS_ASSERT_DIFFERS(css_h(tabbed), css_h(spaced));
|
||||
TS_ASSERT_DIFFERS(css_h(spaced), css_h(doublespaced));
|
||||
}
|
||||
|
||||
void test_ignore_case_hash() {
|
||||
// Same as test_case_sensitive_string_hash, but case insensitive.
|
||||
const Common::String lower("test");
|
||||
const Common::String lower1("test");
|
||||
const Common::String mixed("tESt");
|
||||
const Common::String spaced("test ");
|
||||
const Common::String mixedspaced("tESt ");
|
||||
const Common::String doublespaced("test ");
|
||||
const Common::String tabbed("test\t");
|
||||
|
||||
Common::IgnoreCase_Hash ic_h;
|
||||
TS_ASSERT_EQUALS(ic_h(lower), ic_h(lower1));
|
||||
TS_ASSERT_EQUALS(ic_h(mixed), ic_h(lower));
|
||||
TS_ASSERT_EQUALS(ic_h(spaced), ic_h(mixedspaced));
|
||||
TS_ASSERT_DIFFERS(ic_h(tabbed), ic_h(lower));
|
||||
TS_ASSERT_DIFFERS(ic_h(spaced), ic_h(doublespaced));
|
||||
}
|
||||
|
||||
void test_cpp_string_hash()
|
||||
{
|
||||
// We run the same tests with Hash<String>,
|
||||
// a template specialization of Hash, also a functor.
|
||||
// It is supposed to be case sensitive.
|
||||
|
||||
const Common::String lower("test");
|
||||
const Common::String lower1("test");
|
||||
const Common::String mixed("tESt");
|
||||
const Common::String spaced("test ");
|
||||
const Common::String mixedspaced("tESt ");
|
||||
const Common::String doublespaced("test ");
|
||||
const Common::String tabbed("test\t");
|
||||
|
||||
Common::Hash<Common::String> h;
|
||||
TS_ASSERT_EQUALS(h(lower), h(lower1));
|
||||
TS_ASSERT_DIFFERS(h(mixed), h(lower));
|
||||
TS_ASSERT_DIFFERS(h(spaced), h(lower));
|
||||
TS_ASSERT_DIFFERS(h(tabbed), h(spaced));
|
||||
TS_ASSERT_DIFFERS(h(spaced), h(doublespaced));
|
||||
}
|
||||
|
||||
void test_c_style_string_hash()
|
||||
{
|
||||
// Same as test_cpp_string_hash but with Hash<const char*>,
|
||||
// a template specialization of Hash, also a functor,
|
||||
// that works with C-Style strings.
|
||||
// It is supposed to be case sensitive.
|
||||
|
||||
char lower[] = "test";
|
||||
char lower1[] = "test";
|
||||
char mixed[] = "tESt";
|
||||
char spaced[] = "test ";
|
||||
char mixedspaced[] = "tESt ";
|
||||
char doublespaced[] = "test ";
|
||||
char tabbed[] = "test\t";
|
||||
|
||||
Common::Hash<const char *> h;
|
||||
TS_ASSERT_EQUALS(h(lower), h(lower1));
|
||||
TS_ASSERT_DIFFERS(h(mixed), h(lower));
|
||||
TS_ASSERT_DIFFERS(h(spaced), h(lower));
|
||||
TS_ASSERT_DIFFERS(h(spaced), h(mixedspaced));
|
||||
TS_ASSERT_DIFFERS(h(tabbed), h(spaced));
|
||||
TS_ASSERT_DIFFERS(h(spaced), h(doublespaced));
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
234
test/common/hashmap.h
Normal file
234
test/common/hashmap.h
Normal file
@@ -0,0 +1,234 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/hashmap.h"
|
||||
#include "common/hash-str.h"
|
||||
|
||||
class HashMapTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_empty_clear() {
|
||||
Common::HashMap<int, int> container;
|
||||
TS_ASSERT(container.empty());
|
||||
container[0] = 17;
|
||||
container[1] = 33;
|
||||
TS_ASSERT(!container.empty());
|
||||
container.clear();
|
||||
TS_ASSERT(container.empty());
|
||||
|
||||
Common::StringMap container2;
|
||||
TS_ASSERT(container2.empty());
|
||||
container2["foo"] = "bar";
|
||||
container2["quux"] = "blub";
|
||||
TS_ASSERT(!container2.empty());
|
||||
container2.clear();
|
||||
TS_ASSERT(container2.empty());
|
||||
}
|
||||
|
||||
void test_contains() {
|
||||
Common::HashMap<int, int> container;
|
||||
container[0] = 17;
|
||||
container[1] = 33;
|
||||
TS_ASSERT(container.contains(0));
|
||||
TS_ASSERT(container.contains(1));
|
||||
TS_ASSERT(!container.contains(17));
|
||||
TS_ASSERT(!container.contains(-1));
|
||||
|
||||
Common::StringMap container2;
|
||||
container2["foo"] = "bar";
|
||||
container2["quux"] = "blub";
|
||||
TS_ASSERT(container2.contains("foo"));
|
||||
TS_ASSERT(container2.contains("quux"));
|
||||
TS_ASSERT(!container2.contains("bar"));
|
||||
TS_ASSERT(!container2.contains("asdf"));
|
||||
}
|
||||
|
||||
void test_add_remove() {
|
||||
Common::HashMap<int, int> container;
|
||||
container[0] = 17;
|
||||
container[1] = 33;
|
||||
container[2] = 45;
|
||||
container[3] = 12;
|
||||
container[4] = 96;
|
||||
TS_ASSERT(container.contains(1));
|
||||
container.erase(1);
|
||||
TS_ASSERT(!container.contains(1));
|
||||
container[1] = 42;
|
||||
TS_ASSERT(container.contains(1));
|
||||
container.erase(0);
|
||||
TS_ASSERT(!container.empty());
|
||||
container.erase(1);
|
||||
TS_ASSERT(!container.empty());
|
||||
container.erase(2);
|
||||
TS_ASSERT(!container.empty());
|
||||
container.erase(3);
|
||||
TS_ASSERT(!container.empty());
|
||||
container.erase(4);
|
||||
TS_ASSERT(container.empty());
|
||||
container[1] = 33;
|
||||
TS_ASSERT(container.contains(1));
|
||||
TS_ASSERT(!container.empty());
|
||||
container.erase(1);
|
||||
TS_ASSERT(container.empty());
|
||||
}
|
||||
|
||||
void test_add_remove_iterator() {
|
||||
Common::HashMap<int, int> container;
|
||||
container[0] = 17;
|
||||
container[1] = 33;
|
||||
container[2] = 45;
|
||||
container[3] = 12;
|
||||
container[4] = 96;
|
||||
TS_ASSERT(container.contains(1));
|
||||
container.erase(container.find(1));
|
||||
TS_ASSERT(!container.contains(1));
|
||||
container[1] = 42;
|
||||
TS_ASSERT(container.contains(1));
|
||||
container.erase(container.find(0));
|
||||
TS_ASSERT(!container.empty());
|
||||
container.erase(container.find(1));
|
||||
TS_ASSERT(!container.empty());
|
||||
container.erase(container.find(2));
|
||||
TS_ASSERT(!container.empty());
|
||||
container.erase(container.find(3));
|
||||
TS_ASSERT(!container.empty());
|
||||
container.erase(container.find(4));
|
||||
TS_ASSERT(container.empty());
|
||||
container[1] = 33;
|
||||
TS_ASSERT(container.contains(1));
|
||||
TS_ASSERT(!container.empty());
|
||||
container.erase(container.find(1));
|
||||
TS_ASSERT(container.empty());
|
||||
}
|
||||
|
||||
void test_lookup() {
|
||||
Common::HashMap<int, int> container;
|
||||
container[0] = 17;
|
||||
container[1] = -1;
|
||||
container[2] = 45;
|
||||
container[3] = 12;
|
||||
container[4] = 96;
|
||||
|
||||
TS_ASSERT_EQUALS(container[0], 17);
|
||||
TS_ASSERT_EQUALS(container[1], -1);
|
||||
TS_ASSERT_EQUALS(container[2], 45);
|
||||
TS_ASSERT_EQUALS(container[3], 12);
|
||||
TS_ASSERT_EQUALS(container[4], 96);
|
||||
}
|
||||
|
||||
void test_lookup_with_default() {
|
||||
Common::HashMap<int, int> container;
|
||||
container[0] = 17;
|
||||
container[1] = -1;
|
||||
container[2] = 45;
|
||||
container[3] = 12;
|
||||
container[4] = 96;
|
||||
|
||||
// We take a const ref now to ensure that the map
|
||||
// is not modified by getValOrDefault.
|
||||
const Common::HashMap<int, int> &containerRef = container;
|
||||
|
||||
TS_ASSERT_EQUALS(containerRef.getValOrDefault(0), 17);
|
||||
TS_ASSERT_EQUALS(containerRef.getValOrDefault(17), 0);
|
||||
TS_ASSERT_EQUALS(containerRef.getValOrDefault(0, -10), 17);
|
||||
TS_ASSERT_EQUALS(containerRef.getValOrDefault(17, -10), -10);
|
||||
}
|
||||
|
||||
void test_iterator_begin_end() {
|
||||
Common::HashMap<int, int> container;
|
||||
|
||||
// The container is initially empty ...
|
||||
TS_ASSERT_EQUALS(container.begin(), container.end());
|
||||
|
||||
// ... then non-empty ...
|
||||
container[324] = 33;
|
||||
TS_ASSERT_DIFFERS(container.begin(), container.end());
|
||||
|
||||
// ... and again empty.
|
||||
container.clear();
|
||||
TS_ASSERT_EQUALS(container.begin(), container.end());
|
||||
}
|
||||
|
||||
void test_hash_map_copy() {
|
||||
Common::HashMap<int, int> map1, container2;
|
||||
map1[323] = 32;
|
||||
container2 = map1;
|
||||
TS_ASSERT_EQUALS(container2[323], 32);
|
||||
}
|
||||
|
||||
void test_collision() {
|
||||
// NB: The usefulness of this example depends strongly on the
|
||||
// specific hashmap implementation.
|
||||
// It is constructed to insert multiple colliding elements.
|
||||
Common::HashMap<int, int> h;
|
||||
h[5] = 1;
|
||||
h[32+5] = 1;
|
||||
h[64+5] = 1;
|
||||
h[128+5] = 1;
|
||||
TS_ASSERT(h.contains(5));
|
||||
TS_ASSERT(h.contains(32+5));
|
||||
TS_ASSERT(h.contains(64+5));
|
||||
TS_ASSERT(h.contains(128+5));
|
||||
h.erase(32+5);
|
||||
TS_ASSERT(h.contains(5));
|
||||
TS_ASSERT(h.contains(64+5));
|
||||
TS_ASSERT(h.contains(128+5));
|
||||
h.erase(5);
|
||||
TS_ASSERT(h.contains(64+5));
|
||||
TS_ASSERT(h.contains(128+5));
|
||||
h[32+5] = 1;
|
||||
TS_ASSERT(h.contains(32+5));
|
||||
TS_ASSERT(h.contains(64+5));
|
||||
TS_ASSERT(h.contains(128+5));
|
||||
h[5] = 1;
|
||||
TS_ASSERT(h.contains(5));
|
||||
TS_ASSERT(h.contains(32+5));
|
||||
TS_ASSERT(h.contains(64+5));
|
||||
TS_ASSERT(h.contains(128+5));
|
||||
h.erase(5);
|
||||
TS_ASSERT(h.contains(32+5));
|
||||
TS_ASSERT(h.contains(64+5));
|
||||
TS_ASSERT(h.contains(128+5));
|
||||
h.erase(64+5);
|
||||
TS_ASSERT(h.contains(32+5));
|
||||
TS_ASSERT(h.contains(128+5));
|
||||
h.erase(128+5);
|
||||
TS_ASSERT(h.contains(32+5));
|
||||
h.erase(32+5);
|
||||
TS_ASSERT(h.empty());
|
||||
}
|
||||
|
||||
void test_iterator() {
|
||||
Common::HashMap<int, int> container;
|
||||
container[0] = 17;
|
||||
container[1] = 33;
|
||||
container[2] = 45;
|
||||
container[3] = 12;
|
||||
container[4] = 96;
|
||||
container.erase(1);
|
||||
container[1] = 42;
|
||||
container.erase(0);
|
||||
container.erase(1);
|
||||
|
||||
int found = 0;
|
||||
Common::HashMap<int, int>::iterator i;
|
||||
for (i = container.begin(); i != container.end(); ++i) {
|
||||
int key = i->_key;
|
||||
TS_ASSERT(key >= 0 && key <= 4);
|
||||
TS_ASSERT(!(found & (1 << key)));
|
||||
found |= 1 << key;
|
||||
}
|
||||
TS_ASSERT(found == 16+8+4);
|
||||
|
||||
found = 0;
|
||||
Common::HashMap<int, int>::const_iterator j;
|
||||
for (j = container.begin(); j != container.end(); ++j) {
|
||||
int key = j->_key;
|
||||
TS_ASSERT(key >= 0 && key <= 4);
|
||||
TS_ASSERT(!(found & (1 << key)));
|
||||
found |= 1 << key;
|
||||
}
|
||||
TS_ASSERT(found == 16+8+4);
|
||||
}
|
||||
|
||||
// TODO: Add test cases for iterators, find, ...
|
||||
};
|
||||
172
test/common/ini-file.h
Normal file
172
test/common/ini-file.h
Normal file
@@ -0,0 +1,172 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/formats/ini-file.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
|
||||
class IniFileTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_blank_ini_file() {
|
||||
Common::INIFile inifile;
|
||||
|
||||
TS_ASSERT(!inifile.hasSection("abc"));
|
||||
|
||||
Common::INIFile::SectionList sections = inifile.getSections();
|
||||
TS_ASSERT_EQUALS(sections.size(), 0U);
|
||||
}
|
||||
|
||||
void test_simple_ini_file() {
|
||||
static const unsigned char inistr[] = "#comment\n[s]\nabc=1\ndef=xyz";
|
||||
Common::MemoryReadStream ms(inistr, sizeof(inistr));
|
||||
Common::INIFile inifile;
|
||||
bool result = inifile.loadFromStream(ms);
|
||||
TS_ASSERT(result);
|
||||
|
||||
Common::INIFile::SectionList sections = inifile.getSections();
|
||||
TS_ASSERT_EQUALS(sections.size(), 1U);
|
||||
|
||||
TS_ASSERT(inifile.hasSection("s"));
|
||||
TS_ASSERT(inifile.hasKey("abc", "s"));
|
||||
|
||||
Common::String val;
|
||||
TS_ASSERT(inifile.getKey("abc", "s", val));
|
||||
TS_ASSERT_EQUALS(val, "1");
|
||||
TS_ASSERT(inifile.getKey("def", "s", val));
|
||||
TS_ASSERT_EQUALS(val, "xyz");
|
||||
inifile.setKey("abc", "s", "newval");
|
||||
TS_ASSERT(inifile.getKey("abc", "s", val));
|
||||
TS_ASSERT_EQUALS(val, "newval");
|
||||
}
|
||||
|
||||
void test_multisection_ini_file() {
|
||||
static const unsigned char inistr[] = "[s]\nabc=1\ndef=xyz\n#comment=no\n[empty]\n\n[s2]\n abc = 2 \n ; comment=no";
|
||||
Common::MemoryReadStream ms(inistr, sizeof(inistr));
|
||||
Common::INIFile inifile;
|
||||
bool result = inifile.loadFromStream(ms);
|
||||
TS_ASSERT(result);
|
||||
|
||||
Common::INIFile::SectionList sections = inifile.getSections();
|
||||
TS_ASSERT_EQUALS(sections.size(), 3U);
|
||||
|
||||
TS_ASSERT(inifile.hasSection("s"));
|
||||
TS_ASSERT(inifile.hasSection("empty"));
|
||||
TS_ASSERT(inifile.hasSection("s2"));
|
||||
TS_ASSERT(inifile.hasKey("abc", "s"));
|
||||
TS_ASSERT(inifile.hasKey("abc", "s2"));
|
||||
|
||||
Common::String val;
|
||||
TS_ASSERT(inifile.getKey("abc", "s", val));
|
||||
TS_ASSERT_EQUALS(val, "1");
|
||||
TS_ASSERT(inifile.getKey("abc", "s2", val));
|
||||
TS_ASSERT_EQUALS(val, "2");
|
||||
|
||||
inifile.clear();
|
||||
sections = inifile.getSections();
|
||||
TS_ASSERT_EQUALS(sections.size(), 0U);
|
||||
TS_ASSERT(!inifile.hasSection("s"));
|
||||
}
|
||||
|
||||
void test_modify_ini_file() {
|
||||
Common::INIFile inifile;
|
||||
|
||||
TS_ASSERT(!inifile.hasSection("s"));
|
||||
inifile.addSection("s");
|
||||
TS_ASSERT(inifile.hasSection("s"));
|
||||
|
||||
inifile.setKey("k", "s", "val");
|
||||
TS_ASSERT(inifile.hasKey("k", "s"));
|
||||
|
||||
inifile.setKey("k2", "s", "val2");
|
||||
TS_ASSERT(inifile.hasKey("k2", "s"));
|
||||
inifile.removeKey("k2", "s");
|
||||
TS_ASSERT(!inifile.hasKey("k2", "s"));
|
||||
|
||||
inifile.renameSection("s", "t");
|
||||
TS_ASSERT(!inifile.hasSection("s"));
|
||||
TS_ASSERT(inifile.hasSection("t"));
|
||||
TS_ASSERT(inifile.hasKey("k", "t"));
|
||||
|
||||
inifile.removeSection("t");
|
||||
TS_ASSERT(!inifile.hasSection("t"));
|
||||
}
|
||||
|
||||
void test_name_validity() {
|
||||
Common::INIFile inifile;
|
||||
|
||||
inifile.addSection("s*");
|
||||
TS_ASSERT(!inifile.hasSection("s*"));
|
||||
|
||||
inifile.addSection("");
|
||||
TS_ASSERT(!inifile.hasSection(""));
|
||||
|
||||
// Valid is alphanum plus [-_:. ]
|
||||
inifile.addSection("sEcT10N -_..Name:");
|
||||
TS_ASSERT(inifile.hasSection("sEcT10N -_..Name:"));
|
||||
|
||||
const char invalids[] = "!\"#$%&'()=~[]()+?<>\r\t\n";
|
||||
for (uint i = 0; i < sizeof(invalids) - 1; i++) {
|
||||
char c = invalids[i];
|
||||
const Common::String s(c);
|
||||
inifile.addSection(s);
|
||||
TS_ASSERT(!inifile.hasSection(s));
|
||||
}
|
||||
|
||||
inifile.clear();
|
||||
inifile.allowNonEnglishCharacters();
|
||||
for (uint i = 0; i < sizeof(invalids) - 1; i++) {
|
||||
char c = invalids[i];
|
||||
if (c == '[' || c == ']' || c == '#' || c == '=' || c == '\r' || c == '\n')
|
||||
continue;
|
||||
const Common::String s(c);
|
||||
inifile.addSection(s);
|
||||
TS_ASSERT(inifile.hasSection(s));
|
||||
}
|
||||
}
|
||||
|
||||
void test_write_simple_ini_file() {
|
||||
byte buf[1024];
|
||||
Common::INIFile inifile;
|
||||
{
|
||||
static const unsigned char inistr[] = "#comment\n[s]\nabc=1\ndef=xyz";
|
||||
Common::MemoryReadStream mrs(inistr, sizeof(inistr));
|
||||
TS_ASSERT(inifile.loadFromStream(mrs));
|
||||
}
|
||||
|
||||
// A too-small write buffer (should fail)
|
||||
{
|
||||
Common::MemoryWriteStream mws(buf, 10);
|
||||
TS_ASSERT(!inifile.saveToStream(mws));
|
||||
}
|
||||
|
||||
// A good sized write buffer (should work)
|
||||
int len;
|
||||
{
|
||||
Common::MemoryWriteStream mws(buf, 1024);
|
||||
TS_ASSERT(inifile.saveToStream(mws));
|
||||
len = mws.pos();
|
||||
}
|
||||
|
||||
{
|
||||
Common::MemoryReadStream mrs(buf, len - 1);
|
||||
Common::INIFile checkinifile;
|
||||
TS_ASSERT(checkinifile.loadFromStream(mrs));
|
||||
TS_ASSERT(checkinifile.hasSection("s"));
|
||||
|
||||
const Common::INIFile::SectionList §ions = checkinifile.getSections();
|
||||
const Common::INIFile::Section §ion = sections.front();
|
||||
TS_ASSERT_EQUALS(section.comment, "#comment\n");
|
||||
TS_ASSERT_EQUALS(section.name, "s");
|
||||
|
||||
TS_ASSERT(checkinifile.hasKey("abc", "s"));
|
||||
TS_ASSERT(checkinifile.hasKey("def", "s"));
|
||||
|
||||
Common::String val;
|
||||
TS_ASSERT(inifile.getKey("abc", "s", val));
|
||||
TS_ASSERT_EQUALS(val, "1");
|
||||
TS_ASSERT(inifile.getKey("def", "s", val));
|
||||
TS_ASSERT_EQUALS(val, "xyz");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
18
test/common/intrinsics.h
Normal file
18
test/common/intrinsics.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/intrinsics.h"
|
||||
|
||||
class IntrinsicsTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_intLog2() {
|
||||
// Test special case for 0
|
||||
TS_ASSERT_EQUALS(Common::intLog2(0), -1);
|
||||
|
||||
// intLog2 should round the result towards 0
|
||||
TS_ASSERT_EQUALS(Common::intLog2(7), 2);
|
||||
|
||||
// Some simple test for 2^10
|
||||
TS_ASSERT_EQUALS(Common::intLog2(1024), 10);
|
||||
}
|
||||
};
|
||||
285
test/common/list.h
Normal file
285
test/common/list.h
Normal file
@@ -0,0 +1,285 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/list.h"
|
||||
|
||||
class ListTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_empty_clear() {
|
||||
Common::List<int> container;
|
||||
TS_ASSERT(container.empty());
|
||||
container.push_back(17);
|
||||
container.push_back(33);
|
||||
TS_ASSERT(!container.empty());
|
||||
container.clear();
|
||||
TS_ASSERT(container.empty());
|
||||
}
|
||||
|
||||
public:
|
||||
void test_size() {
|
||||
Common::List<int> container;
|
||||
TS_ASSERT_EQUALS(container.size(), (unsigned int)0);
|
||||
container.push_back(17);
|
||||
TS_ASSERT_EQUALS(container.size(), (unsigned int)1);
|
||||
container.push_back(33);
|
||||
TS_ASSERT_EQUALS(container.size(), (unsigned int)2);
|
||||
container.clear();
|
||||
TS_ASSERT_EQUALS(container.size(), (unsigned int)0);
|
||||
}
|
||||
|
||||
void test_iterator_begin_end() {
|
||||
Common::List<int> container;
|
||||
|
||||
// The container is initially empty ...
|
||||
TS_ASSERT_EQUALS(container.begin(), container.end());
|
||||
|
||||
// ... then non-empty ...
|
||||
container.push_back(33);
|
||||
TS_ASSERT_DIFFERS(container.begin(), container.end());
|
||||
|
||||
// ... and again empty.
|
||||
container.clear();
|
||||
TS_ASSERT_EQUALS(container.begin(), container.end());
|
||||
}
|
||||
|
||||
void test_iterator() {
|
||||
Common::List<int> container;
|
||||
Common::List<int>::iterator iter;
|
||||
Common::List<int>::const_iterator cIter;
|
||||
|
||||
// Fill the container with some random data
|
||||
container.push_back(17);
|
||||
container.push_back(33);
|
||||
container.push_back(-11);
|
||||
|
||||
// Iterate over the container and verify that we encounter the elements in
|
||||
// the order we expect them to be.
|
||||
|
||||
iter = container.begin();
|
||||
cIter = container.begin();
|
||||
|
||||
TS_ASSERT_EQUALS(iter, cIter);
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 17);
|
||||
++iter;
|
||||
++cIter;
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
TS_ASSERT_DIFFERS(cIter, container.end());
|
||||
TS_ASSERT_EQUALS(iter, cIter);
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 33);
|
||||
++iter;
|
||||
++cIter;
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
TS_ASSERT_DIFFERS(cIter, container.end());
|
||||
TS_ASSERT_EQUALS(iter, cIter);
|
||||
|
||||
// Also test the postinc
|
||||
TS_ASSERT_EQUALS(*iter, -11);
|
||||
iter++;
|
||||
cIter++;
|
||||
TS_ASSERT_EQUALS(iter, container.end());
|
||||
TS_ASSERT_EQUALS(cIter, container.end());
|
||||
TS_ASSERT_EQUALS(iter, cIter);
|
||||
|
||||
cIter = iter;
|
||||
TS_ASSERT_EQUALS(iter, cIter);
|
||||
}
|
||||
|
||||
void test_insert() {
|
||||
Common::List<int> container;
|
||||
Common::List<int>::iterator iter;
|
||||
|
||||
// Fill the container with some random data
|
||||
container.push_back(17);
|
||||
container.push_back(33);
|
||||
container.push_back(-11);
|
||||
|
||||
// Iterate to after the second element
|
||||
iter = container.begin();
|
||||
++iter;
|
||||
++iter;
|
||||
|
||||
// Insert a value before the final one
|
||||
container.insert(iter, 42);
|
||||
|
||||
// Insert another value before the final one and check the return value
|
||||
iter = container.insert(iter, 43);
|
||||
TS_ASSERT_EQUALS(*iter, 43);
|
||||
|
||||
// Insert a value before the previously inserted one
|
||||
container.insert(iter, 44);
|
||||
|
||||
// Verify contents are correct
|
||||
iter = container.begin();
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 17);
|
||||
++iter;
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 33);
|
||||
++iter;
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 42);
|
||||
++iter;
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 44);
|
||||
++iter;
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 43);
|
||||
++iter;
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, -11);
|
||||
++iter;
|
||||
TS_ASSERT_EQUALS(iter, container.end());
|
||||
}
|
||||
|
||||
void test_erase() {
|
||||
Common::List<int> container;
|
||||
Common::List<int>::iterator first, last;
|
||||
|
||||
// Fill the container with some random data
|
||||
container.push_back(17);
|
||||
container.push_back(33);
|
||||
container.push_back(-11);
|
||||
container.push_back(42);
|
||||
container.push_back(43);
|
||||
|
||||
// Iterate to after the second element
|
||||
first = container.begin();
|
||||
++first;
|
||||
++first;
|
||||
|
||||
// Iterate to after the fourth element
|
||||
last = first;
|
||||
++last;
|
||||
++last;
|
||||
|
||||
// Now erase that range
|
||||
container.erase(first, last);
|
||||
|
||||
// Verify contents are correct
|
||||
Common::List<int>::iterator iter = container.begin();
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 17);
|
||||
++iter;
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 33);
|
||||
++iter;
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 43);
|
||||
++iter;
|
||||
TS_ASSERT_EQUALS(iter, container.end());
|
||||
}
|
||||
|
||||
void test_remove() {
|
||||
Common::List<int> container;
|
||||
Common::List<int>::iterator first, last;
|
||||
|
||||
// Fill the container with some random data
|
||||
container.push_back(-11);
|
||||
container.push_back(17);
|
||||
container.push_back(33);
|
||||
container.push_back(42);
|
||||
container.push_back(-11);
|
||||
container.push_back(42);
|
||||
container.push_back(43);
|
||||
|
||||
// Remove some stuff
|
||||
container.remove(42);
|
||||
container.remove(-11);
|
||||
|
||||
// Now erase that range
|
||||
container.erase(first, last);
|
||||
|
||||
// Verify contents are correct
|
||||
Common::List<int>::iterator iter = container.begin();
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 17);
|
||||
++iter;
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 33);
|
||||
++iter;
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 43);
|
||||
++iter;
|
||||
TS_ASSERT_EQUALS(iter, container.end());
|
||||
}
|
||||
|
||||
void test_reverse() {
|
||||
Common::List<int> container;
|
||||
Common::List<int>::iterator iter;
|
||||
|
||||
// Fill the container with some random data
|
||||
container.push_back(17);
|
||||
container.push_back(33);
|
||||
container.push_back(-11);
|
||||
|
||||
iter = container.reverse_begin();
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, -11);
|
||||
--iter;
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 33);
|
||||
--iter;
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, 17);
|
||||
--iter;
|
||||
TS_ASSERT_EQUALS(iter, container.end());
|
||||
|
||||
iter = container.reverse_begin();
|
||||
|
||||
iter = container.reverse_erase(iter);
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
TS_ASSERT_EQUALS(*iter, 33);
|
||||
|
||||
iter = container.reverse_erase(iter);
|
||||
TS_ASSERT_DIFFERS(iter, container.end());
|
||||
TS_ASSERT_EQUALS(*iter, 17);
|
||||
|
||||
iter = container.reverse_erase(iter);
|
||||
TS_ASSERT_EQUALS(iter, container.end());
|
||||
|
||||
TS_ASSERT_EQUALS(container.begin(), container.end());
|
||||
TS_ASSERT_EQUALS(container.reverse_begin(), container.end());
|
||||
}
|
||||
|
||||
void test_front_back_push_pop() {
|
||||
Common::List<int> container;
|
||||
|
||||
container.push_back( 42);
|
||||
container.push_back(-23);
|
||||
|
||||
TS_ASSERT_EQUALS(container.front(), 42);
|
||||
TS_ASSERT_EQUALS(container.back(), -23);
|
||||
|
||||
container.front() = -17;
|
||||
container.back() = 163;
|
||||
TS_ASSERT_EQUALS(container.front(), -17);
|
||||
TS_ASSERT_EQUALS(container.back(), 163);
|
||||
|
||||
container.pop_front();
|
||||
TS_ASSERT_EQUALS(container.front(), 163);
|
||||
TS_ASSERT_EQUALS(container.back(), 163);
|
||||
|
||||
container.push_front(99);
|
||||
TS_ASSERT_EQUALS(container.front(), 99);
|
||||
TS_ASSERT_EQUALS(container.back(), 163);
|
||||
|
||||
container.pop_back();
|
||||
TS_ASSERT_EQUALS(container.front(), 99);
|
||||
TS_ASSERT_EQUALS(container.back(), 99);
|
||||
}
|
||||
};
|
||||
50
test/common/md5.h
Normal file
50
test/common/md5.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/md5.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
/*
|
||||
* those are the standard RFC 1321 test vectors
|
||||
*/
|
||||
static const char *md5_test_string[] = {
|
||||
"",
|
||||
"a",
|
||||
"abc",
|
||||
"message digest",
|
||||
"abcdefghijklmnopqrstuvwxyz",
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
("12345678901234567890123456789012345678901234567890123456789012"
|
||||
"345678901234567890")
|
||||
};
|
||||
|
||||
static const char *md5_test_digest[] = {
|
||||
"d41d8cd98f00b204e9800998ecf8427e",
|
||||
"0cc175b9c0f1b6a831c399e269772661",
|
||||
"900150983cd24fb0d6963f7d28e17f72",
|
||||
"f96b697d7cb7938d525a2f31aaf161d0",
|
||||
"c3fcd3d76192e4007dfb496cca67e13b",
|
||||
"d174ab98d277d9f5a5611c2c9f419d9f",
|
||||
"57edf4a22be3c955ac49da2e2107b67a"
|
||||
};
|
||||
|
||||
class MD5TestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_computeStreamMD5() {
|
||||
int i, j;
|
||||
char output[33];
|
||||
unsigned char md5sum[16];
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
Common::MemoryReadStream stream((const byte *)md5_test_string[i], strlen(md5_test_string[i]));
|
||||
Common::computeStreamMD5(stream, md5sum);
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
snprintf(output + j * 2, 3, "%02x", md5sum[j]);
|
||||
}
|
||||
|
||||
Common::String tmp(output);
|
||||
TS_ASSERT_EQUALS(tmp, md5_test_digest[i]);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
63
test/common/memory.h
Normal file
63
test/common/memory.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/memory.h"
|
||||
|
||||
class MemoryTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_memset16() {
|
||||
uint16 expected[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
const uint16 step1[8] = { 0, 1, 1, 1, 1, 1, 1, 0 };
|
||||
const uint16 step2[8] = { 0, 1, 2, 2, 2, 2, 1, 0 };
|
||||
const uint16 step3[8] = { 0, 1, 2, 3, 3, 2, 1, 0 };
|
||||
|
||||
Common::memset16(expected + 1, 1, 6);
|
||||
|
||||
TS_ASSERT_EQUALS(memcmp(expected, step1, sizeof(expected)), 0);
|
||||
|
||||
Common::memset16(expected + 2, 2, 4);
|
||||
|
||||
TS_ASSERT_EQUALS(memcmp(expected, step2, sizeof(expected)), 0);
|
||||
|
||||
Common::memset16(expected + 3, 3, 2);
|
||||
|
||||
TS_ASSERT_EQUALS(memcmp(expected, step3, sizeof(expected)), 0);
|
||||
}
|
||||
|
||||
void test_memset32() {
|
||||
uint32 expected[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
const uint32 step1[8] = { 0, 1, 1, 1, 1, 1, 1, 0 };
|
||||
const uint32 step2[8] = { 0, 1, 2, 2, 2, 2, 1, 0 };
|
||||
const uint32 step3[8] = { 0, 1, 2, 3, 3, 2, 1, 0 };
|
||||
|
||||
Common::memset32(expected + 1, 1, 6);
|
||||
|
||||
TS_ASSERT_EQUALS(memcmp(expected, step1, sizeof(expected)), 0);
|
||||
|
||||
Common::memset32(expected + 2, 2, 4);
|
||||
|
||||
TS_ASSERT_EQUALS(memcmp(expected, step2, sizeof(expected)), 0);
|
||||
|
||||
Common::memset32(expected + 3, 3, 2);
|
||||
|
||||
TS_ASSERT_EQUALS(memcmp(expected, step3, sizeof(expected)), 0);
|
||||
}
|
||||
|
||||
void test_memset64() {
|
||||
uint64 expected[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
const uint64 step1[8] = { 0, 1, 1, 1, 1, 1, 1, 0 };
|
||||
const uint64 step2[8] = { 0, 1, 2, 2, 2, 2, 1, 0 };
|
||||
const uint64 step3[8] = { 0, 1, 2, 3, 3, 2, 1, 0 };
|
||||
|
||||
Common::memset64(expected + 1, 1, 6);
|
||||
|
||||
TS_ASSERT_EQUALS(memcmp(expected, step1, sizeof(expected)), 0);
|
||||
|
||||
Common::memset64(expected + 2, 2, 4);
|
||||
|
||||
TS_ASSERT_EQUALS(memcmp(expected, step2, sizeof(expected)), 0);
|
||||
|
||||
Common::memset64(expected + 3, 3, 2);
|
||||
|
||||
TS_ASSERT_EQUALS(memcmp(expected, step3, sizeof(expected)), 0);
|
||||
}
|
||||
};
|
||||
107
test/common/memoryreadstream.h
Normal file
107
test/common/memoryreadstream.h
Normal file
@@ -0,0 +1,107 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/memstream.h"
|
||||
|
||||
class MemoryReadStreamTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_seek_set() {
|
||||
byte contents[] = { 'a', 'b', '\n', '\n', 'c', '\n' };
|
||||
Common::MemoryReadStream ms(contents, sizeof(contents));
|
||||
|
||||
ms.seek(0, SEEK_SET);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 0);
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
ms.seek(1, SEEK_SET);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 1);
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
ms.seek(5, SEEK_SET);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 5);
|
||||
TS_ASSERT(!ms.eos());
|
||||
}
|
||||
|
||||
void test_seek_cur() {
|
||||
byte contents[] = { 'a', 'b', '\n', '\n', 'c' };
|
||||
Common::MemoryReadStream ms(contents, sizeof(contents));
|
||||
|
||||
ms.seek(3, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 3);
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
ms.seek(-1, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 2);
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
ms.seek(3, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 5);
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
ms.seek(-1, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 4);
|
||||
TS_ASSERT(!ms.eos());
|
||||
}
|
||||
|
||||
void test_seek_end() {
|
||||
byte contents[] = { 'a', 'b', '\n', '\n', 'c' };
|
||||
Common::MemoryReadStream ms(contents, sizeof(contents));
|
||||
|
||||
ms.seek(0, SEEK_END);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 5);
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
ms.seek(-1, SEEK_END);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 4);
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
ms.seek(-5, SEEK_END);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 0);
|
||||
TS_ASSERT(!ms.eos());
|
||||
}
|
||||
|
||||
void test_seek_read_le() {
|
||||
byte contents[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
|
||||
Common::MemoryReadStream ms(contents, sizeof(contents));
|
||||
|
||||
TS_ASSERT_EQUALS(ms.readUint16LE(), 0x0201UL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 2);
|
||||
TS_ASSERT_EQUALS(ms.readUint32LE(), 0x06050403UL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 6);
|
||||
TS_ASSERT_EQUALS(ms.readUint64LE(), 0x0E0D0C0B0A090807ULL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 14);
|
||||
TS_ASSERT_EQUALS(ms.readByte(), 0x0F);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 15);
|
||||
TS_ASSERT(!ms.eos());
|
||||
}
|
||||
|
||||
void test_seek_read_be() {
|
||||
byte contents[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
|
||||
Common::MemoryReadStream ms(contents, sizeof(contents));
|
||||
|
||||
TS_ASSERT_EQUALS(ms.readUint16BE(), 0x0102UL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 2);
|
||||
TS_ASSERT_EQUALS(ms.readUint32BE(), 0x03040506UL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 6);
|
||||
TS_ASSERT_EQUALS(ms.readUint64BE(), 0x0708090A0B0C0D0EULL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 14);
|
||||
TS_ASSERT_EQUALS(ms.readByte(), 0x0F);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 15);
|
||||
TS_ASSERT(!ms.eos());
|
||||
}
|
||||
|
||||
void test_eos() {
|
||||
byte contents[] = { 1, 2, 3, 4, 5, 6, 7 };
|
||||
Common::MemoryReadStream ms(contents, sizeof(contents));
|
||||
|
||||
// Read after the end of the stream
|
||||
for (int32 i = 0; i <= ms.size(); ++i)
|
||||
ms.readByte();
|
||||
|
||||
// The eos flag should be set here
|
||||
TS_ASSERT(ms.eos());
|
||||
|
||||
// Seeking should reset the eos flag
|
||||
ms.seek(0, SEEK_SET);
|
||||
TS_ASSERT(!ms.eos());
|
||||
}
|
||||
};
|
||||
121
test/common/memoryreadstreamendian.h
Normal file
121
test/common/memoryreadstreamendian.h
Normal file
@@ -0,0 +1,121 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/memstream.h"
|
||||
|
||||
class MemoryReadStreamEndianTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_seek_set() {
|
||||
byte contents[] = { 'a', 'b', '\n', '\n', 'c', '\n' };
|
||||
Common::MemoryReadStreamEndian ms(contents, sizeof(contents), false);
|
||||
|
||||
ms.seek(0, SEEK_SET);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 0);
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
ms.seek(1, SEEK_SET);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 1);
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
ms.seek(5, SEEK_SET);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 5);
|
||||
TS_ASSERT(!ms.eos());
|
||||
}
|
||||
|
||||
void test_seek_cur() {
|
||||
byte contents[] = { 'a', 'b', '\n', '\n', 'c' };
|
||||
Common::MemoryReadStreamEndian ms(contents, sizeof(contents), false);
|
||||
|
||||
ms.seek(3, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 3);
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
ms.seek(-1, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 2);
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
ms.seek(3, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 5);
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
ms.seek(-1, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 4);
|
||||
TS_ASSERT(!ms.eos());
|
||||
}
|
||||
|
||||
void test_seek_end() {
|
||||
byte contents[] = { 'a', 'b', '\n', '\n', 'c' };
|
||||
Common::MemoryReadStreamEndian ms(contents, sizeof(contents), false);
|
||||
|
||||
ms.seek(0, SEEK_END);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 5);
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
ms.seek(-1, SEEK_END);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 4);
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
ms.seek(-5, SEEK_END);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 0);
|
||||
TS_ASSERT(!ms.eos());
|
||||
}
|
||||
|
||||
void test_seek_read_le() {
|
||||
byte contents[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
|
||||
Common::MemoryReadStreamEndian ms(contents, sizeof(contents), false);
|
||||
|
||||
TS_ASSERT_EQUALS(ms.readUint16LE(), 0x0201UL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 2);
|
||||
TS_ASSERT_EQUALS(ms.readUint32LE(), 0x06050403UL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 6);
|
||||
TS_ASSERT_EQUALS(ms.readUint64LE(), 0x0E0D0C0B0A090807ULL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 14);
|
||||
TS_ASSERT_EQUALS(ms.readByte(), 0x0F);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 15);
|
||||
TS_ASSERT(!ms.eos());
|
||||
}
|
||||
|
||||
void test_seek_read_be() {
|
||||
byte contents[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
|
||||
Common::MemoryReadStreamEndian ms(contents, sizeof(contents), false);
|
||||
|
||||
TS_ASSERT_EQUALS(ms.readUint16BE(), 0x0102UL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 2);
|
||||
TS_ASSERT_EQUALS(ms.readUint32BE(), 0x03040506UL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 6);
|
||||
TS_ASSERT_EQUALS(ms.readUint64BE(), 0x0708090A0B0C0D0EULL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 14);
|
||||
TS_ASSERT_EQUALS(ms.readByte(), 0x0F);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 15);
|
||||
TS_ASSERT(!ms.eos());
|
||||
}
|
||||
|
||||
void test_seek_read_le2() {
|
||||
byte contents[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
|
||||
Common::MemoryReadStreamEndian ms(contents, sizeof(contents), false);
|
||||
|
||||
TS_ASSERT_EQUALS(ms.readUint16(), 0x0201UL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 2);
|
||||
TS_ASSERT_EQUALS(ms.readUint32(), 0x06050403UL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 6);
|
||||
TS_ASSERT_EQUALS(ms.readUint64(), 0x0E0D0C0B0A090807ULL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 14);
|
||||
TS_ASSERT_EQUALS(ms.readByte(), 0x0F);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 15);
|
||||
TS_ASSERT(!ms.eos());
|
||||
}
|
||||
|
||||
void test_seek_read_be2() {
|
||||
byte contents[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
|
||||
Common::MemoryReadStreamEndian ms(contents, sizeof(contents), true);
|
||||
|
||||
TS_ASSERT_EQUALS(ms.readUint16(), 0x0102UL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 2);
|
||||
TS_ASSERT_EQUALS(ms.readUint32(), 0x03040506UL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 6);
|
||||
TS_ASSERT_EQUALS(ms.readUint64(), 0x0708090A0B0C0D0EULL);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 14);
|
||||
TS_ASSERT_EQUALS(ms.readByte(), 0x0F);
|
||||
TS_ASSERT_EQUALS(ms.pos(), 15);
|
||||
TS_ASSERT(!ms.eos());
|
||||
}
|
||||
};
|
||||
31
test/common/memorywritestream.h
Normal file
31
test/common/memorywritestream.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/memstream.h"
|
||||
|
||||
class MemoryWriteStreamTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_err() {
|
||||
byte temp = 0;
|
||||
|
||||
Common::MemoryWriteStream stream(&temp, 0);
|
||||
TS_ASSERT(!stream.err());
|
||||
|
||||
// Make sure the error indicator gets set
|
||||
stream.write(&temp, 1);
|
||||
TS_ASSERT(stream.err());
|
||||
|
||||
// Test whether the error indicator can be cleared
|
||||
stream.clearErr();
|
||||
TS_ASSERT(!stream.err());
|
||||
}
|
||||
|
||||
void test_write() {
|
||||
byte buffer[7] = {};
|
||||
Common::MemoryWriteStream stream(buffer, sizeof(buffer));
|
||||
|
||||
const byte data[7] = { 7, 4, 3, 0, 10, 12, 1 };
|
||||
stream.write(data, sizeof(data));
|
||||
TS_ASSERT(memcmp(buffer, data, sizeof(data)) == 0);
|
||||
TS_ASSERT(!stream.err());
|
||||
}
|
||||
};
|
||||
34
test/common/pack.h
Normal file
34
test/common/pack.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#include "common/pack-start.h" // START STRUCT PACKING
|
||||
|
||||
struct TestStruct {
|
||||
uint32 x;
|
||||
byte y;
|
||||
uint16 z;
|
||||
uint32 a;
|
||||
byte b;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
#include "common/pack-end.h" // END STRUCT PACKING
|
||||
|
||||
#define OFFS(type,item) (((ptrdiff_t)(&((type *)42)->type::item))-42)
|
||||
|
||||
class PackTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_packing() {
|
||||
TS_ASSERT_EQUALS(sizeof(TestStruct), size_t(4+1+2+4+1));
|
||||
}
|
||||
|
||||
void test_offsets() {
|
||||
TS_ASSERT_EQUALS(OFFS(TestStruct, x), (ptrdiff_t)0);
|
||||
TS_ASSERT_EQUALS(OFFS(TestStruct, y), (ptrdiff_t)4);
|
||||
TS_ASSERT_EQUALS(OFFS(TestStruct, z), (ptrdiff_t)5);
|
||||
TS_ASSERT_EQUALS(OFFS(TestStruct, a), (ptrdiff_t)7);
|
||||
TS_ASSERT_EQUALS(OFFS(TestStruct, b), (ptrdiff_t)11);
|
||||
}
|
||||
};
|
||||
608
test/common/path.h
Normal file
608
test/common/path.h
Normal file
@@ -0,0 +1,608 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "test/common/str-helper.h"
|
||||
|
||||
#include "common/path.h"
|
||||
#include "common/hashmap.h"
|
||||
|
||||
static const char *TEST_PATH = "parent/dir/file.txt";
|
||||
static const char *TEST_ESCAPED1_PATH = "|parent/dir/file.txt";
|
||||
static const char *TEST_ESCAPED2_PATH = "par/ent\\dir\\file.txt";
|
||||
static const char *TEST_ESCAPED3_PATH = "parent\\dir\\fi|le.txt";
|
||||
static const char *TEST_BS_PATH = "parent\\dir\\file.txt";
|
||||
|
||||
class PathTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_Path() {
|
||||
Common::Path p;
|
||||
TS_ASSERT_EQUALS(p.toString(), "");
|
||||
TS_ASSERT_EQUALS(p.empty(), true);
|
||||
|
||||
Common::Path p2(TEST_PATH);
|
||||
TS_ASSERT_EQUALS(p2.toString(), TEST_PATH);
|
||||
TS_ASSERT_EQUALS(p2.toString('|'), "parent|dir|file.txt");
|
||||
TS_ASSERT_EQUALS(p2.toString('\\'), "parent\\dir\\file.txt");
|
||||
|
||||
Common::Path p3(TEST_ESCAPED1_PATH);
|
||||
TS_ASSERT_EQUALS(p3.toString(), TEST_ESCAPED1_PATH);
|
||||
TS_ASSERT_EQUALS(p3.toString('\\'), "|parent\\dir\\file.txt");
|
||||
|
||||
Common::Path p4(TEST_ESCAPED2_PATH, '\\');
|
||||
TS_ASSERT_EQUALS(p4.toString('\\'), TEST_ESCAPED2_PATH);
|
||||
|
||||
Common::Path p5(TEST_ESCAPED3_PATH, '\\');
|
||||
TS_ASSERT_EQUALS(p5.toString('\\'), TEST_ESCAPED3_PATH);
|
||||
TS_ASSERT_EQUALS(p5.baseName(), "fi|le.txt");
|
||||
|
||||
Common::Path p6(TEST_BS_PATH, '\\');
|
||||
TS_ASSERT_EQUALS(p6.toString('\\'), TEST_BS_PATH);
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
Common::Path::_shownSeparatorCollisionWarning = false;
|
||||
TS_ASSERT_EQUALS(p3.toString('|'), "|parent|dir|file.txt");
|
||||
TS_ASSERT_EQUALS(Common::Path::_shownSeparatorCollisionWarning, true);
|
||||
|
||||
Common::Path::_shownSeparatorCollisionWarning = false;
|
||||
TS_ASSERT_EQUALS(p3.toString('i'), "|parentidirifile.txt");
|
||||
TS_ASSERT_EQUALS(Common::Path::_shownSeparatorCollisionWarning, true);
|
||||
|
||||
Common::Path::_shownSeparatorCollisionWarning = false;
|
||||
TS_ASSERT_EQUALS(p4.toString('/'), "par/ent/dir/file.txt");
|
||||
TS_ASSERT_EQUALS(Common::Path::_shownSeparatorCollisionWarning, true);
|
||||
|
||||
Common::Path::_shownSeparatorCollisionWarning = false;
|
||||
TS_ASSERT_EQUALS(p6.toString('i'), "parentidirifile.txt");
|
||||
TS_ASSERT_EQUALS(Common::Path::_shownSeparatorCollisionWarning, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_clear() {
|
||||
Common::Path p(TEST_PATH);
|
||||
TS_ASSERT_EQUALS(p.empty(), false);
|
||||
|
||||
p.clear();
|
||||
TS_ASSERT_EQUALS(p.empty(), true);
|
||||
|
||||
TS_ASSERT(p.equals(Common::Path()));
|
||||
TS_ASSERT(p != Common::Path(TEST_PATH));
|
||||
}
|
||||
|
||||
void test_getLastComponent() {
|
||||
Common::Path p;
|
||||
TS_ASSERT_EQUALS(p.getLastComponent().toString(), "");
|
||||
TS_ASSERT_EQUALS(p.getLastComponent(), Common::Path());
|
||||
|
||||
Common::Path p2(TEST_PATH);
|
||||
TS_ASSERT_EQUALS(p2.getLastComponent().toString(), "file.txt");
|
||||
TS_ASSERT_EQUALS(p2.getLastComponent(), Common::Path("file.txt"));
|
||||
|
||||
Common::Path p3("parent/dir/|file.txt");
|
||||
TS_ASSERT_EQUALS(p3.getLastComponent().toString(), "|file.txt");
|
||||
TS_ASSERT_EQUALS(p3.getLastComponent(), Common::Path("|file.txt"));
|
||||
}
|
||||
|
||||
void test_baseName() {
|
||||
Common::Path p;
|
||||
TS_ASSERT_EQUALS(p.baseName(), "");
|
||||
|
||||
Common::Path p2(TEST_PATH);
|
||||
TS_ASSERT_EQUALS(p2.baseName(), "file.txt");
|
||||
|
||||
Common::Path p3("parent\\dir\\fi/le.txt", '\\');
|
||||
TS_ASSERT_EQUALS(p3.baseName(), "fi/le.txt");
|
||||
|
||||
Common::Path p4("parent/dir/file.txt/");
|
||||
TS_ASSERT_EQUALS(p4.baseName(), "file.txt");
|
||||
|
||||
Common::Path p5("File I/O", ':');
|
||||
TS_ASSERT_EQUALS(p5.baseName(), "File I/O");
|
||||
}
|
||||
|
||||
void test_getParent() {
|
||||
Common::Path p;
|
||||
TS_ASSERT_EQUALS(p.getParent().toString(), "");
|
||||
|
||||
Common::Path p2(TEST_PATH);
|
||||
TS_ASSERT_EQUALS(p2.getParent().toString(), "parent/dir/");
|
||||
// TODO: should this work?
|
||||
TS_ASSERT_EQUALS(p2.getParent().getLastComponent().toString(), "dir/");
|
||||
|
||||
Common::Path p3(TEST_ESCAPED1_PATH);
|
||||
TS_ASSERT_EQUALS(p3.getParent().toString(), "|parent/dir/");
|
||||
// TODO: should this work?
|
||||
TS_ASSERT_EQUALS(p3.getParent().getLastComponent().toString(), "dir/");
|
||||
|
||||
Common::Path p4(TEST_ESCAPED2_PATH, '\\');
|
||||
TS_ASSERT_EQUALS(p4.getParent().toString('\\'), "par/ent\\dir\\");
|
||||
// TODO: should this work?
|
||||
TS_ASSERT_EQUALS(p4.getParent().getLastComponent().toString('\\'), "dir\\");
|
||||
}
|
||||
|
||||
void test_join() {
|
||||
Common::Path p("dir");
|
||||
Common::Path p2 = p.join("file.txt");
|
||||
TS_ASSERT_EQUALS(p2.toString(), "dir/file.txt");
|
||||
p2 = p.join("");
|
||||
TS_ASSERT_EQUALS(p2.toString(), "dir");
|
||||
p2 = p.join(Common::Path());
|
||||
TS_ASSERT_EQUALS(p2.toString(), "dir");
|
||||
|
||||
Common::Path p3;
|
||||
Common::Path p4 = p3.join("file.txt");
|
||||
TS_ASSERT_EQUALS(p4.toString(), "file.txt");
|
||||
p4 = p3.join(Common::String("file.txt"));
|
||||
TS_ASSERT_EQUALS(p4.toString(), "file.txt");
|
||||
p4 = p3.join(Common::Path("file.txt"));
|
||||
TS_ASSERT_EQUALS(p4.toString(), "file.txt");
|
||||
|
||||
Common::Path p5(TEST_PATH);
|
||||
Common::Path p6 = p5.getParent().join("other.txt");
|
||||
TS_ASSERT_EQUALS(p6.toString(), "parent/dir/other.txt");
|
||||
p6 = p5.getParent().join("|child\\other.txt", '\\');
|
||||
TS_ASSERT_EQUALS(p6.toString(), "parent/dir/|child/other.txt");
|
||||
p6 = p5.getParent().join("/child\\other.txt", '\\');
|
||||
TS_ASSERT_EQUALS(p6.toString('|'), "parent|dir|/child|other.txt");
|
||||
p6 = p5.getParent().join(Common::Path("|other.txt"));
|
||||
TS_ASSERT_EQUALS(p6.toString(), "parent/dir/|other.txt");
|
||||
p6 = p5.getParent().join(Common::Path("oth/er.txt", '\\'));
|
||||
TS_ASSERT_EQUALS(p6.toString('\\'), "parent\\dir\\oth/er.txt");
|
||||
|
||||
Common::Path p7(TEST_ESCAPED1_PATH);
|
||||
Common::Path p8 = p7.getParent().join("other.txt");
|
||||
TS_ASSERT_EQUALS(p8.toString(), "|parent/dir/other.txt");
|
||||
p8 = p7.getParent().join(Common::Path("other.txt"));
|
||||
TS_ASSERT_EQUALS(p8.toString(), "|parent/dir/other.txt");
|
||||
p8 = p7.getParent().join(Common::Path("|other.txt"));
|
||||
TS_ASSERT_EQUALS(p8.toString(), "|parent/dir/|other.txt");
|
||||
}
|
||||
|
||||
// Ensure we can joinInPlace correctly with leading or trailing separators
|
||||
void test_joinInPlace() {
|
||||
Common::Path p("abc/def");
|
||||
p.joinInPlace("file.txt");
|
||||
TS_ASSERT_EQUALS(p.toString(), "abc/def/file.txt");
|
||||
|
||||
Common::Path p2("xyz/def");
|
||||
p2.joinInPlace(Common::Path("file.txt"));
|
||||
TS_ASSERT_EQUALS(p2.toString(), "xyz/def/file.txt");
|
||||
|
||||
Common::Path p3("ghi/def/");
|
||||
p3.joinInPlace(Common::Path("file.txt"));
|
||||
TS_ASSERT_EQUALS(p3.toString(), "ghi/def/file.txt");
|
||||
|
||||
Common::Path p4("123/def");
|
||||
p4.joinInPlace(Common::Path("/file4.txt"));
|
||||
TS_ASSERT_EQUALS(p4.toString(), "123/def/file4.txt");
|
||||
|
||||
Common::Path p5("abc/def");
|
||||
p5.joinInPlace(Common::String("file.txt"));
|
||||
TS_ASSERT_EQUALS(p5.toString(), "abc/def/file.txt");
|
||||
}
|
||||
|
||||
void test_append() {
|
||||
Common::Path p("abc/def");
|
||||
p.appendInPlace("");
|
||||
TS_ASSERT_EQUALS(p.toString(), "abc/def");
|
||||
|
||||
Common::Path p2;
|
||||
p2.appendInPlace("file.txt");
|
||||
TS_ASSERT_EQUALS(p2.toString(), "file.txt");
|
||||
|
||||
Common::Path p3("abc/def");
|
||||
p3.appendInPlace(Common::Path());
|
||||
TS_ASSERT_EQUALS(p3.toString(), "abc/def");
|
||||
|
||||
Common::Path p4;
|
||||
p4.appendInPlace(Common::Path("file.txt"));
|
||||
TS_ASSERT_EQUALS(p4.toString(), "file.txt");
|
||||
|
||||
TS_ASSERT_EQUALS(p4.append("a|b", '|').toString(), "file.txta/b");
|
||||
TS_ASSERT_EQUALS(p4.append(Common::String("a|b"), '|').toString('/'), "file.txta/b");
|
||||
TS_ASSERT_EQUALS(p4.append(p3).toString(), "file.txtabc/def");
|
||||
}
|
||||
|
||||
void test_appendComponent() {
|
||||
Common::Path p("abc/def");
|
||||
Common::Path p2 = p.appendComponent("");
|
||||
TS_ASSERT_EQUALS(p2.toString(), "abc/def");
|
||||
|
||||
Common::Path p3;
|
||||
Common::Path p4 = p3.appendComponent("file.txt");
|
||||
TS_ASSERT_EQUALS(p4.toString(), "file.txt");
|
||||
|
||||
p2 = p.appendComponent("file.txt");
|
||||
TS_ASSERT_EQUALS(p2.toString(), "abc/def/file.txt");
|
||||
|
||||
p2 = p.appendComponent("fi/le.txt");
|
||||
TS_ASSERT_EQUALS(p2.toString('\\'), "abc\\def\\fi/le.txt");
|
||||
|
||||
Common::Path p5("abc\\de/f", '\\');
|
||||
Common::Path p6 = p5.appendComponent(Common::String("fi/le.txt"));
|
||||
TS_ASSERT_EQUALS(p6.toString('\\'), "abc\\de/f\\fi/le.txt");
|
||||
}
|
||||
|
||||
void test_separator() {
|
||||
Common::Path p(TEST_PATH, '\\');
|
||||
TS_ASSERT_EQUALS(p.getLastComponent().toString(), TEST_PATH);
|
||||
TS_ASSERT_EQUALS(p.getParent().toString(), "");
|
||||
|
||||
Common::Path p2(TEST_PATH, 'e');
|
||||
TS_ASSERT_EQUALS(p2.getLastComponent().toString(), ".txt");
|
||||
TS_ASSERT_EQUALS(p2.getParent().toString('#'), "par#nt/dir/fil#");
|
||||
TS_ASSERT_EQUALS(p2.getParent().getParent().toString('#'), "par#");
|
||||
}
|
||||
|
||||
void test_splitComponents() {
|
||||
Common::Path p(TEST_PATH);
|
||||
Common::StringArray array = p.splitComponents();
|
||||
|
||||
TS_ASSERT_EQUALS(array.size(), 3u);
|
||||
|
||||
Common::StringArray::iterator iter = array.begin();
|
||||
|
||||
TS_ASSERT_EQUALS(*iter, "parent");
|
||||
++iter;
|
||||
TS_ASSERT_EQUALS(*iter, "dir");
|
||||
++iter;
|
||||
TS_ASSERT_EQUALS(*iter, "file.txt");
|
||||
|
||||
Common::Path p2;
|
||||
Common::StringArray array2 = p2.splitComponents();
|
||||
TS_ASSERT_EQUALS(array2.size(), 1u);
|
||||
Common::StringArray::iterator iter2 = array2.begin();
|
||||
TS_ASSERT_EQUALS(*iter2, "");
|
||||
|
||||
Common::Path p3(TEST_ESCAPED1_PATH);
|
||||
Common::StringArray array3 = p3.splitComponents();
|
||||
|
||||
TS_ASSERT_EQUALS(array3.size(), 3u);
|
||||
|
||||
Common::StringArray::iterator iter3 = array3.begin();
|
||||
|
||||
TS_ASSERT_EQUALS(*iter3, "|parent");
|
||||
++iter3;
|
||||
TS_ASSERT_EQUALS(*iter3, "dir");
|
||||
++iter3;
|
||||
TS_ASSERT_EQUALS(*iter3, "file.txt");
|
||||
|
||||
}
|
||||
|
||||
void test_joinComponents() {
|
||||
Common::StringArray array;
|
||||
Common::Path p = Common::Path::joinComponents(array);
|
||||
TS_ASSERT_EQUALS(p.toString(), "");
|
||||
|
||||
array.push_back("");
|
||||
p = Common::Path::joinComponents(array);
|
||||
TS_ASSERT_EQUALS(p.toString(), "");
|
||||
|
||||
Common::StringArray array2;
|
||||
array2.push_back("par/ent");
|
||||
array2.push_back("dir");
|
||||
array2.push_back("file.txt");
|
||||
p = Common::Path::joinComponents(array2);
|
||||
TS_ASSERT_EQUALS(p.toString('\\'), TEST_ESCAPED2_PATH);
|
||||
}
|
||||
|
||||
void test_removeTrailingSeparators() {
|
||||
Common::Path p;
|
||||
p.removeTrailingSeparators();
|
||||
TS_ASSERT_EQUALS(p.toString(), "");
|
||||
|
||||
Common::Path p2(TEST_PATH);
|
||||
p2.removeTrailingSeparators();
|
||||
TS_ASSERT_EQUALS(p2.toString(), TEST_PATH);
|
||||
|
||||
Common::Path p3("parent/dir/file.txt///");
|
||||
p3.removeTrailingSeparators();
|
||||
TS_ASSERT_EQUALS(p3.toString(), "parent/dir/file.txt");
|
||||
|
||||
Common::Path p4("//");
|
||||
p4.removeTrailingSeparators();
|
||||
TS_ASSERT_EQUALS(p4.toString(), "/");
|
||||
}
|
||||
|
||||
void test_isRelativeTo() {
|
||||
Common::Path p, p1(TEST_PATH), p2(TEST_ESCAPED1_PATH);
|
||||
|
||||
// Everything is relative to empty
|
||||
TS_ASSERT_EQUALS(p1.isRelativeTo(p), true);
|
||||
TS_ASSERT_EQUALS(p2.isRelativeTo(p), true);
|
||||
// Everything is relative to itself
|
||||
TS_ASSERT_EQUALS(p1.isRelativeTo(p1), true);
|
||||
TS_ASSERT_EQUALS(p2.isRelativeTo(p2), true);
|
||||
|
||||
// A path is not relative to empty one
|
||||
TS_ASSERT_EQUALS(p.isRelativeTo(p1), false);
|
||||
|
||||
TS_ASSERT_EQUALS(p1.isRelativeTo(Common::Path("parent/dir")), true);
|
||||
TS_ASSERT_EQUALS(p1.isRelativeTo(Common::Path("parent/dir/")), true);
|
||||
TS_ASSERT_EQUALS(p1.isRelativeTo(Common::Path("parent/dir/fi")), false);
|
||||
|
||||
TS_ASSERT_EQUALS(p1.isRelativeTo(Common::Path("|parent/dir")), false);
|
||||
|
||||
Common::Path p3("parent\\dir\\fi/le.txt", '\\');
|
||||
TS_ASSERT_EQUALS(p3.isRelativeTo(Common::Path("parent/dir")), true);
|
||||
TS_ASSERT_EQUALS(p3.isRelativeTo(Common::Path("parent/dir/")), true);
|
||||
TS_ASSERT_EQUALS(p3.isRelativeTo(Common::Path("parent/dir/fi")), false);
|
||||
TS_ASSERT_EQUALS(p3.isRelativeTo(Common::Path("parent/dir/fa")), false);
|
||||
|
||||
Common::Path p4("par|ent\\dir\\fi/le.txt", '\\');
|
||||
TS_ASSERT_EQUALS(p4.isRelativeTo(Common::Path("par|ent/dir")), true);
|
||||
}
|
||||
|
||||
void test_relativeTo() {
|
||||
Common::Path p, p1(TEST_PATH), p2(TEST_ESCAPED1_PATH);
|
||||
|
||||
// Everything is relative to empty
|
||||
TS_ASSERT_EQUALS(p1.relativeTo(p).toString(), TEST_PATH);
|
||||
TS_ASSERT_EQUALS(p2.relativeTo(p).toString(), TEST_ESCAPED1_PATH);
|
||||
// Everything is relative to itself
|
||||
TS_ASSERT_EQUALS(p1.relativeTo(p1), p);
|
||||
TS_ASSERT_EQUALS(p2.relativeTo(p2), p);
|
||||
|
||||
// A path is not relative to empty one
|
||||
TS_ASSERT_EQUALS(p.relativeTo(p1), p);
|
||||
|
||||
TS_ASSERT_EQUALS(p1.relativeTo(Common::Path("parent/dir")).toString(), "file.txt");
|
||||
TS_ASSERT_EQUALS(p1.relativeTo(Common::Path("parent/dir/")).toString(), "file.txt");
|
||||
TS_ASSERT_EQUALS(p1.relativeTo(Common::Path("parent/dir/fi")), p1);
|
||||
|
||||
TS_ASSERT_EQUALS(p1.relativeTo(Common::Path("|parent/dir")), p1);
|
||||
|
||||
Common::Path p3("parent\\dir\\fi/le.txt", '\\');
|
||||
TS_ASSERT_EQUALS(p3.relativeTo(Common::Path("parent/dir")).toString('\\'), "fi/le.txt");
|
||||
TS_ASSERT_EQUALS(p3.relativeTo(Common::Path("parent/dir/")).toString('\\'), "fi/le.txt");
|
||||
TS_ASSERT_EQUALS(p3.relativeTo(Common::Path("parent/dir/fi")), p3);
|
||||
TS_ASSERT_EQUALS(p3.relativeTo(Common::Path("parent/dir/fa")), p3);
|
||||
|
||||
Common::Path p4("par|ent\\dir\\fi/le.txt", '\\');
|
||||
TS_ASSERT_EQUALS(p4.relativeTo(Common::Path("par|ent/dir")).toString('\\'), "fi/le.txt");
|
||||
|
||||
Common::Path p5("par|ent\\dir\\\\\\fi/le.txt", '\\');
|
||||
TS_ASSERT_EQUALS(p5.relativeTo(Common::Path("par|ent/dir")).toString('\\'), "fi/le.txt");
|
||||
}
|
||||
|
||||
void test_normalize() {
|
||||
TS_ASSERT_EQUALS(Common::Path("/", '/').normalize().toString(), "/");
|
||||
TS_ASSERT_EQUALS(Common::Path("///", '/').normalize().toString(), "/");
|
||||
TS_ASSERT_EQUALS(Common::Path("/foo/bar", '/').normalize().toString(), "/foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("/foo//bar/", '/').normalize().toString(), "/foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("/foo/./bar", '/').normalize().toString(), "/foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("/foo//./bar//", '/').normalize().toString(), "/foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("/foo//.bar//", '/').normalize().toString(), "/foo/.bar");
|
||||
|
||||
TS_ASSERT_EQUALS(Common::Path("", '/').normalize().toString(), "");
|
||||
TS_ASSERT_EQUALS(Common::Path("foo/bar", '/').normalize().toString(), "foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("foo//bar/", '/').normalize().toString(), "foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("foo/./bar", '/').normalize().toString(), "foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("foo//./bar//", '/').normalize().toString(), "foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("foo//.bar//", '/').normalize().toString(), "foo/.bar");
|
||||
|
||||
TS_ASSERT_EQUALS(Common::Path("..", '/').normalize().toString(), "..");
|
||||
TS_ASSERT_EQUALS(Common::Path("../", '/').normalize().toString(), "..");
|
||||
TS_ASSERT_EQUALS(Common::Path("/..", '/').normalize().toString(), "/..");
|
||||
TS_ASSERT_EQUALS(Common::Path("../bar", '/').normalize().toString(), "../bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("foo//../", '/').normalize().toString(), "");
|
||||
TS_ASSERT_EQUALS(Common::Path("foo/../bar", '/').normalize().toString(), "bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("foo//../bar//", '/').normalize().toString(), "bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("foo//..bar//", '/').normalize().toString(), "foo/..bar");
|
||||
|
||||
TS_ASSERT_EQUALS(Common::Path("foo/../../bar//", '/').normalize().toString(), "../bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("../foo/../bar", '/').normalize().toString(), "../bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("../../foo/bar/", '/').normalize().toString(), "../../foo/bar");
|
||||
|
||||
TS_ASSERT_EQUALS(Common::Path("foo/../|bar", '/').normalize().toString(), "|bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("foo/^..^bar", '^').normalize().toString('^'), "bar");
|
||||
TS_ASSERT_EQUALS(Common::Path("foo^..^bar/", '^').normalize().toString('^'), "bar/");
|
||||
}
|
||||
|
||||
void test_punycode() {
|
||||
Common::Path p;
|
||||
Common::Path p2 = p.punycodeDecode();
|
||||
TS_ASSERT_EQUALS(p.toString(), "");
|
||||
|
||||
Common::Path p3("parent/dir/xn--Sound Manager 3.1 SoundLib-lba84k/Sound");
|
||||
Common::Path p4 = p3.punycodeDecode();
|
||||
|
||||
TS_ASSERT_EQUALS(p4.toString(':'), "parent:dir:Sound Manager 3.1 / SoundLib:Sound");
|
||||
Common::Path p5 = p4.punycodeEncode();
|
||||
TS_ASSERT_EQUALS(p5.toString('/'), "parent/dir/xn--Sound Manager 3.1 SoundLib-lba84k/Sound");
|
||||
|
||||
Common::Path p6 = p3.punycodeEncode();
|
||||
TS_ASSERT_EQUALS(p6.toString('/'), "parent/dir/xn--xn--Sound Manager 3.1 SoundLib-lba84k-/Sound");
|
||||
|
||||
Common::Path p7 = p6.punycodeDecode();
|
||||
TS_ASSERT_EQUALS(p7.toString('/'), "parent/dir/xn--Sound Manager 3.1 SoundLib-lba84k/Sound");
|
||||
|
||||
typedef Common::HashMap<Common::Path, bool,
|
||||
Common::Path::IgnoreCaseAndMac_Hash, Common::Path::IgnoreCaseAndMac_EqualTo> TestPathMap;
|
||||
TestPathMap map;
|
||||
|
||||
map.setVal(p3, false);
|
||||
TS_ASSERT_EQUALS(map.size(), 1u);
|
||||
map.setVal(p4, false);
|
||||
TS_ASSERT_EQUALS(map.size(), 1u);
|
||||
map.setVal(p5, false);
|
||||
TS_ASSERT_EQUALS(map.size(), 1u);
|
||||
|
||||
map.setVal(p, false);
|
||||
TS_ASSERT_EQUALS(map.size(), 2u);
|
||||
}
|
||||
|
||||
void test_lowerupper() {
|
||||
Common::Path p2(TEST_PATH);
|
||||
p2.toUppercase();
|
||||
TS_ASSERT_EQUALS(p2.toString('/'), "PARENT/DIR/FILE.TXT");
|
||||
|
||||
p2 = TEST_PATH;
|
||||
p2.toLowercase();
|
||||
TS_ASSERT_EQUALS(p2.toString('/'), TEST_PATH);
|
||||
|
||||
Common::Path p3(TEST_ESCAPED1_PATH);
|
||||
p3.toUppercase();
|
||||
TS_ASSERT_EQUALS(p3.toString('/'), "|PARENT/DIR/FILE.TXT");
|
||||
|
||||
Common::String s3(TEST_ESCAPED1_PATH);
|
||||
s3.toUppercase();
|
||||
p3 = s3;
|
||||
p3.toLowercase();
|
||||
TS_ASSERT_EQUALS(p3.toString('/'), TEST_ESCAPED1_PATH);
|
||||
}
|
||||
|
||||
void test_caseinsensitive() {
|
||||
Common::Path p;
|
||||
Common::Path p2("parent:dir:Sound Manager 3.1 / SoundLib:Sound", ':');
|
||||
Common::Path p3("parent:dir:sound manager 3.1 / soundlib:sound", ':');
|
||||
Common::Path p4("parent/dir/xn--Sound Manager 3.1 SoundLib-lba84k/Sound");
|
||||
|
||||
typedef Common::HashMap<Common::Path, bool,
|
||||
Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> TestPathMap;
|
||||
TestPathMap map;
|
||||
|
||||
map.setVal(p2, false);
|
||||
TS_ASSERT_EQUALS(map.size(), 1u);
|
||||
map.setVal(p3, false);
|
||||
TS_ASSERT_EQUALS(map.size(), 1u);
|
||||
map.setVal(p4, false);
|
||||
TS_ASSERT_EQUALS(map.size(), 2u);
|
||||
|
||||
map.setVal(p, false);
|
||||
TS_ASSERT_EQUALS(map.size(), 3u);
|
||||
}
|
||||
|
||||
void test_casesensitive() {
|
||||
Common::Path p2("parent:dir:Sound Manager 3.1 / SoundLib:Sound", ':');
|
||||
Common::Path p3("parent:dir:sound manager 3.1 / soundlib:sound", ':');
|
||||
Common::Path p4("parent/dir/xn--Sound Manager 3.1 SoundLib-lba84k/Sound");
|
||||
|
||||
TS_ASSERT_DIFFERS(p2.hash(), p3.hash());
|
||||
TS_ASSERT_DIFFERS(p2.hash(), p4.hash());
|
||||
TS_ASSERT_DIFFERS(p3.hash(), p4.hash());
|
||||
}
|
||||
|
||||
void test_matchString() {
|
||||
TS_ASSERT(Common::Path("").matchPattern(""));
|
||||
TS_ASSERT(Common::Path("a").matchPattern("*"));
|
||||
TS_ASSERT(Common::Path("monkey.s01").matchPattern("*"));
|
||||
|
||||
TS_ASSERT(!Common::Path("").matchPattern("?"));
|
||||
TS_ASSERT(Common::Path("a").matchPattern("?"));
|
||||
TS_ASSERT(!Common::Path("monkey.s01").matchPattern("?"));
|
||||
|
||||
TS_ASSERT(Common::Path("monkey.s01").matchPattern("monkey.s??"));
|
||||
TS_ASSERT(Common::Path("monkey.s99").matchPattern("monkey.s??"));
|
||||
TS_ASSERT(!Common::Path("monkey.s101").matchPattern("monkey.s??"));
|
||||
|
||||
TS_ASSERT(Common::Path("monkey.s01").matchPattern("monkey.s?1"));
|
||||
TS_ASSERT(!Common::Path("monkey.s99").matchPattern("monkey.s?1"));
|
||||
TS_ASSERT(!Common::Path("monkey.s101").matchPattern("monkey.s?1"));
|
||||
|
||||
TS_ASSERT(Common::Path("monkey.s01").matchPattern("monkey.s*"));
|
||||
TS_ASSERT(Common::Path("monkey.s99").matchPattern("monkey.s*"));
|
||||
TS_ASSERT(Common::Path("monkey.s101").matchPattern("monkey.s*"));
|
||||
|
||||
TS_ASSERT(Common::Path("monkey.s01").matchPattern("monkey.s*1"));
|
||||
TS_ASSERT(!Common::Path("monkey.s99").matchPattern("monkey.s*1"));
|
||||
TS_ASSERT(Common::Path("monkey.s101").matchPattern("monkey.s*1"));
|
||||
|
||||
TS_ASSERT(Common::Path("monkey.s01").matchPattern("monkey.s##"));
|
||||
TS_ASSERT(!Common::Path("monkey.s01").matchPattern("monkey.###"));
|
||||
|
||||
TS_ASSERT(Common::Path("monkey.s0#").matchPattern("monkey.s0\\#"));
|
||||
TS_ASSERT(!Common::Path("monkey.s0#").matchPattern("monkey.s0#"));
|
||||
TS_ASSERT(!Common::Path("monkey.s01").matchPattern("monkey.s0\\#"));
|
||||
|
||||
TS_ASSERT(Common::Path("test/monkey.s01").matchPattern("*/*"));
|
||||
TS_ASSERT(!Common::Path("test/monkey.s01").matchPattern("|test/*"));
|
||||
TS_ASSERT(Common::Path("|test/monkey.s01").matchPattern("*/*"));
|
||||
TS_ASSERT(!Common::Path("test/monkey.s01").matchPattern("*"));
|
||||
TS_ASSERT(!Common::Path("test/monkey.s01").matchPattern(Common::Path("test\\fi/le.txt", '\\')));
|
||||
}
|
||||
|
||||
// These tests are here to exercise cases currently not used
|
||||
// This allow to reach 100% code coverage (except unescape error)
|
||||
void test_findLastSeparator() {
|
||||
Common::Path p(TEST_PATH);
|
||||
TS_ASSERT_EQUALS(p.findLastSeparator(), 10u);
|
||||
|
||||
Common::Path p2("file.txt");
|
||||
TS_ASSERT_EQUALS(p2.findLastSeparator(), Common::String::npos);
|
||||
}
|
||||
|
||||
void test_extract() {
|
||||
Common::Path p(TEST_PATH);
|
||||
Common::Path p2 = p.extract(p._str.c_str(), p._str.c_str());
|
||||
TS_ASSERT_EQUALS(p2, Common::Path());
|
||||
|
||||
Common::Path p3("file.txt");
|
||||
TS_ASSERT_EQUALS(p3.extract(p3._str.c_str()), p3);
|
||||
}
|
||||
|
||||
void test_canUnescape() {
|
||||
TS_ASSERT(Common::Path::canUnescape(true, true, ""));
|
||||
}
|
||||
|
||||
void test_removeExtension() {
|
||||
Common::Path p(TEST_PATH);
|
||||
p.removeExtension();
|
||||
TS_ASSERT_EQUALS(p.toString(), "parent/dir/file");
|
||||
|
||||
Common::Path p2("parent/dir/file.txt.gz");
|
||||
p2.removeExtension();
|
||||
TS_ASSERT_EQUALS(p2.toString(), "parent/dir/file.txt");
|
||||
|
||||
Common::Path p3("parent/dir/file.");
|
||||
p3.removeExtension();
|
||||
TS_ASSERT_EQUALS(p3.toString(), "parent/dir/file");
|
||||
|
||||
Common::Path p4("parent/dir/file.txt.txt");
|
||||
p4.removeExtension(".txt");
|
||||
TS_ASSERT_EQUALS(p4.toString(), "parent/dir/file.txt");
|
||||
|
||||
Common::Path p5("parent/dir/file.txt");
|
||||
p5.removeExtension(".txt");
|
||||
TS_ASSERT_EQUALS(p5.toString(), "parent/dir/file");
|
||||
|
||||
Common::Path p6("parent/dir.txt/file.gz");
|
||||
p6.removeExtension(".txt");
|
||||
TS_ASSERT_EQUALS(p6.toString(), "parent/dir.txt/file.gz");
|
||||
|
||||
Common::Path p7("parent/dir/xn--Sound Manager 3.1 SoundLib-lba84k/Sound.txt");
|
||||
p7.removeExtension(".txt");
|
||||
TS_ASSERT_EQUALS(p7.toString(), "parent/dir/xn--Sound Manager 3.1 SoundLib-lba84k/Sound");
|
||||
|
||||
Common::Path p8("parent/dir/Sound/xn--dialred.dir-qa21d");
|
||||
p8.removeExtension(".dir");
|
||||
TS_ASSERT_EQUALS(p8.toString(), "parent/dir/Sound/xn--dialred.dir-qa21d");
|
||||
|
||||
Common::Path p9("parent/dir/.ab");
|
||||
p9.removeExtension();
|
||||
TS_ASSERT_EQUALS(p9.toString(), "parent/dir/");
|
||||
|
||||
Common::Path p10("parent/dir/.ab");
|
||||
p10.removeExtension(".abc");
|
||||
TS_ASSERT_EQUALS(p10.toString(), "parent/dir/.ab");
|
||||
|
||||
Common::Path p11(".ab");
|
||||
p11.removeExtension(".abc");
|
||||
TS_ASSERT_EQUALS(p11.toString(), ".ab");
|
||||
|
||||
Common::Path p12("test.dir");
|
||||
p12.removeExtension(".dir");
|
||||
TS_ASSERT_EQUALS(p12.toString(), "test");
|
||||
|
||||
Common::Path p13("test.dir");
|
||||
p13.removeExtension(".txt");
|
||||
TS_ASSERT_EQUALS(p13.toString(), "test.dir");
|
||||
|
||||
Common::Path p14("test.dir.txt");
|
||||
p14.removeExtension(".dir");
|
||||
TS_ASSERT_EQUALS(p14.toString(), "test.dir.txt");
|
||||
|
||||
Common::Path p15(".dir");
|
||||
p15.removeExtension(".dir");
|
||||
TS_ASSERT_EQUALS(p15.toString(), "");
|
||||
}
|
||||
};
|
||||
172
test/common/ptr.h
Normal file
172
test/common/ptr.h
Normal file
@@ -0,0 +1,172 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/ptr.h"
|
||||
|
||||
class PtrTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
|
||||
struct A {
|
||||
int a;
|
||||
};
|
||||
|
||||
struct B : public A {
|
||||
int b;
|
||||
};
|
||||
|
||||
// A simple class which keeps track of all its instances
|
||||
class InstanceCountingClass {
|
||||
public:
|
||||
static int count;
|
||||
InstanceCountingClass() { count++; }
|
||||
InstanceCountingClass(const InstanceCountingClass&) { count++; }
|
||||
~InstanceCountingClass() { count--; }
|
||||
};
|
||||
|
||||
void test_deletion() {
|
||||
TS_ASSERT_EQUALS(InstanceCountingClass::count, 0);
|
||||
{
|
||||
Common::SharedPtr<InstanceCountingClass> p1(new InstanceCountingClass());
|
||||
TS_ASSERT_EQUALS(InstanceCountingClass::count, 1);
|
||||
|
||||
Common::ScopedPtr<InstanceCountingClass> p2(new InstanceCountingClass());
|
||||
TS_ASSERT_EQUALS(InstanceCountingClass::count, 2);
|
||||
}
|
||||
TS_ASSERT_EQUALS(InstanceCountingClass::count, 0);
|
||||
}
|
||||
|
||||
struct CustomDeleter {
|
||||
static bool invoked;
|
||||
void operator()(int *object) {
|
||||
invoked = true;
|
||||
delete object;
|
||||
}
|
||||
};
|
||||
|
||||
void test_scoped_deleter() {
|
||||
CustomDeleter::invoked = false;
|
||||
|
||||
{
|
||||
Common::ScopedPtr<int, CustomDeleter> a(new int(0));
|
||||
TS_ASSERT(!CustomDeleter::invoked);
|
||||
}
|
||||
|
||||
TS_ASSERT(CustomDeleter::invoked);
|
||||
}
|
||||
|
||||
void test_disposable_deleter() {
|
||||
CustomDeleter::invoked = false;
|
||||
|
||||
{
|
||||
Common::DisposablePtr<int, CustomDeleter> a1(new int, DisposeAfterUse::YES);
|
||||
TS_ASSERT(!CustomDeleter::invoked);
|
||||
}
|
||||
|
||||
TS_ASSERT(CustomDeleter::invoked);
|
||||
CustomDeleter::invoked = false;
|
||||
|
||||
int *a = new int;
|
||||
{
|
||||
Common::DisposablePtr<int, CustomDeleter> a2(a, DisposeAfterUse::NO);
|
||||
}
|
||||
|
||||
TS_ASSERT(!CustomDeleter::invoked);
|
||||
delete a;
|
||||
}
|
||||
|
||||
void test_scoped_deref() {
|
||||
A *raw = new A();
|
||||
raw->a = 123;
|
||||
Common::ScopedPtr<A> a(raw);
|
||||
TS_ASSERT_EQUALS(&*a, &*raw);
|
||||
TS_ASSERT_EQUALS(a->a, raw->a);
|
||||
}
|
||||
|
||||
void test_disposable_deref() {
|
||||
A *raw = new A();
|
||||
raw->a = 123;
|
||||
Common::DisposablePtr<A> a(raw, DisposeAfterUse::YES);
|
||||
TS_ASSERT_EQUALS(&*a, &*raw);
|
||||
TS_ASSERT_EQUALS(a->a, raw->a);
|
||||
}
|
||||
|
||||
void test_assign() {
|
||||
Common::SharedPtr<int> p1(new int(1));
|
||||
TS_ASSERT(p1.unique());
|
||||
TS_ASSERT_EQUALS(*p1, 1);
|
||||
|
||||
{
|
||||
Common::SharedPtr<int> p2 = p1;
|
||||
TS_ASSERT(!p1.unique());
|
||||
TS_ASSERT_EQUALS(p1.refCount(), p2.refCount());
|
||||
TS_ASSERT_EQUALS(p1.refCount(), 2);
|
||||
TS_ASSERT_EQUALS(p1, p2);
|
||||
TS_ASSERT_EQUALS(*p2, 1);
|
||||
{
|
||||
Common::SharedPtr<int> p3;
|
||||
p3 = p2;
|
||||
TS_ASSERT_EQUALS(p3, p2);
|
||||
TS_ASSERT_EQUALS(p3, p1);
|
||||
TS_ASSERT_EQUALS(p1.refCount(), 3);
|
||||
TS_ASSERT_EQUALS(*p3, 1);
|
||||
*p3 = 0;
|
||||
TS_ASSERT_EQUALS(*p3, 0);
|
||||
}
|
||||
TS_ASSERT_EQUALS(*p2, 0);
|
||||
TS_ASSERT_EQUALS(p1.refCount(), 2);
|
||||
}
|
||||
|
||||
TS_ASSERT_EQUALS(*p1, 0);
|
||||
TS_ASSERT(p1.unique());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
struct Deleter {
|
||||
bool *test;
|
||||
void operator()(T *ptr) { *test = true; delete ptr; }
|
||||
};
|
||||
|
||||
void test_deleter() {
|
||||
Deleter<int> myDeleter;
|
||||
bool test = false;
|
||||
myDeleter.test = &test;
|
||||
|
||||
{
|
||||
Common::SharedPtr<int> p(new int(1), myDeleter);
|
||||
}
|
||||
|
||||
TS_ASSERT_EQUALS(test, true);
|
||||
}
|
||||
|
||||
void test_compare() {
|
||||
Common::SharedPtr<int> p1(new int(1));
|
||||
Common::SharedPtr<int> p2;
|
||||
|
||||
TS_ASSERT(p1);
|
||||
TS_ASSERT(!p2);
|
||||
|
||||
TS_ASSERT(p1 != 0);
|
||||
TS_ASSERT(p2 == 0);
|
||||
|
||||
p1.reset();
|
||||
TS_ASSERT(!p1);
|
||||
}
|
||||
|
||||
void test_cast() {
|
||||
Common::SharedPtr<B> b(new B);
|
||||
Common::SharedPtr<A> a(b);
|
||||
a = b;
|
||||
}
|
||||
|
||||
void test_weak_ptr() {
|
||||
Common::SharedPtr<B> b(new B);
|
||||
Common::WeakPtr<A> a(b);
|
||||
TS_ASSERT(a.lock() == b);
|
||||
TS_ASSERT(!a.expired());
|
||||
b.reset();
|
||||
TS_ASSERT(a.expired());
|
||||
TS_ASSERT(!a.lock());
|
||||
}
|
||||
};
|
||||
|
||||
int PtrTestSuite::InstanceCountingClass::count = 0;
|
||||
bool PtrTestSuite::CustomDeleter::invoked = false;
|
||||
42
test/common/punycode.h
Normal file
42
test/common/punycode.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
#include "common/punycode.h"
|
||||
|
||||
/**
|
||||
* Test suite for the functions in common/util.h
|
||||
*/
|
||||
static const char *strings[] = {
|
||||
"Icon\r", "xn--Icon-ja6e", "1",
|
||||
"ascii", "ascii", "0",
|
||||
"ends with dot .", "xn--ends with dot .-", "1",
|
||||
"ends with space ", "xn--ends with space -", "1",
|
||||
"バッドデイ(Power PC)", "xn--(Power PC)-jx4ilmwb1a7h", "1",
|
||||
"Hello*", "xn--Hello-la10a", "1",
|
||||
"File I/O", "xn--File IO-oa82b", "1",
|
||||
"HDにコピーして下さい。G3", "xn--HDG3-rw3c5o2dpa9kzb2170dd4tzyda5j4k", "1",
|
||||
"Buried in Time™ Demo", "xn--Buried in Time Demo-eo0l", "1",
|
||||
"•Main Menu", "xn--Main Menu-zd0e", "1",
|
||||
"Spaceship Warlock™", "xn--Spaceship Warlock-306j", "1",
|
||||
"ワロビージャックの大冒険<デモ>", "xn--baa0pja0512dela6bueub9gshf1k1a1rt742c060a2x4u", "1",
|
||||
"Jönssonligan går på djupet.exe", "xn--Jnssonligan gr p djupet.exe-glcd70c", "1",
|
||||
"Jönssonligan.exe", "xn--Jnssonligan.exe-8sb", "1",
|
||||
"G3フォルダ", "xn--G3-3g4axdtexf", "1",
|
||||
"Big[test]", "Big[test]", "0",
|
||||
"Where \\ Do <you> Want / To: G* ? ;Unless=nowhere,or|\"(everything)/\":*|\\?%<>,;=", "xn--Where Do you Want To G ;Unless=nowhere,or(everything),;=-5baedgdcbtamaaaaaaaaa99woa3wnnmb82aqb71ekb9g3c1f1cyb7bx6rfcv2pxa", "1",
|
||||
"Buried in Timeェ Demo", "xn--Buried in Time Demo-yp97h", "1",
|
||||
0
|
||||
};
|
||||
class PunycodeTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
|
||||
void test_punycode() {
|
||||
for (const char **a = strings; *a; a += 3) {
|
||||
Common::U32String string_in(a[0]);
|
||||
Common::String string_out(a[1]);
|
||||
bool need = (a[2][0] == '1');
|
||||
|
||||
TS_ASSERT_EQUALS(punycode_decodefilename(string_out), string_in);
|
||||
TS_ASSERT_EQUALS(punycode_encodefilename(string_in), string_out);
|
||||
TS_ASSERT_EQUALS(punycode_needEncode(string_in), need);
|
||||
}
|
||||
}
|
||||
};
|
||||
82
test/common/queue.h
Normal file
82
test/common/queue.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/queue.h"
|
||||
|
||||
class QueueTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_empty_clear() {
|
||||
Common::Queue<int> queue;
|
||||
TS_ASSERT(queue.empty());
|
||||
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
TS_ASSERT(!queue.empty());
|
||||
|
||||
queue.clear();
|
||||
|
||||
TS_ASSERT(queue.empty());
|
||||
}
|
||||
|
||||
void test_size() {
|
||||
Common::Queue<int> queue;
|
||||
TS_ASSERT_EQUALS(queue.size(), 0);
|
||||
|
||||
queue.push(5);
|
||||
TS_ASSERT_EQUALS(queue.size(), 1);
|
||||
|
||||
queue.push(9);
|
||||
queue.push(0);
|
||||
TS_ASSERT_EQUALS(queue.size(), 3);
|
||||
|
||||
queue.pop();
|
||||
TS_ASSERT_EQUALS(queue.size(), 2);
|
||||
}
|
||||
|
||||
void test_front_back_push_pop() {
|
||||
Common::Queue<int> container;
|
||||
|
||||
container.push( 42);
|
||||
container.push(-23);
|
||||
|
||||
TS_ASSERT_EQUALS(container.front(), 42);
|
||||
TS_ASSERT_EQUALS(container.back(), -23);
|
||||
|
||||
container.front() = -17;
|
||||
container.back() = 163;
|
||||
TS_ASSERT_EQUALS(container.front(), -17);
|
||||
TS_ASSERT_EQUALS(container.back(), 163);
|
||||
|
||||
container.pop();
|
||||
TS_ASSERT_EQUALS(container.front(), 163);
|
||||
TS_ASSERT_EQUALS(container.back(), 163);
|
||||
}
|
||||
|
||||
void test_assign() {
|
||||
Common::Queue<int> q1, q2;
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
q1.push(i);
|
||||
q2.push(4-i);
|
||||
}
|
||||
|
||||
Common::Queue<int> q3(q1);
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
TS_ASSERT_EQUALS(q3.front(), i);
|
||||
q3.pop();
|
||||
}
|
||||
|
||||
TS_ASSERT(q3.empty());
|
||||
|
||||
q3 = q2;
|
||||
|
||||
for (int i = 4; i >= 0; --i) {
|
||||
TS_ASSERT_EQUALS(q3.front(), i);
|
||||
q3.pop();
|
||||
}
|
||||
|
||||
TS_ASSERT(q3.empty());
|
||||
TS_ASSERT(!q1.empty());
|
||||
TS_ASSERT(!q2.empty());
|
||||
}
|
||||
};
|
||||
144
test/common/rational.h
Normal file
144
test/common/rational.h
Normal file
@@ -0,0 +1,144 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/rational.h"
|
||||
|
||||
class RationalTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_operators() {
|
||||
Common::Rational r0(6, 3);
|
||||
Common::Rational r1(1, 2);
|
||||
|
||||
Common::Rational r2(62, 2);
|
||||
Common::Rational r3(34, 4);
|
||||
|
||||
Common::Rational r4 = (r0 + r1) * 3;
|
||||
Common::Rational r5 = (r2 - r3) / 3;
|
||||
|
||||
Common::Rational r6 = r5 - 1;
|
||||
|
||||
TS_ASSERT(r4 == r5);
|
||||
TS_ASSERT(!(r4 != r5));
|
||||
|
||||
TS_ASSERT(r4 != r6);
|
||||
TS_ASSERT(!(r4 == r6));
|
||||
|
||||
TS_ASSERT(-r4 == -r5);
|
||||
|
||||
TS_ASSERT(r0 == 2);
|
||||
TS_ASSERT(!(r0 != 2));
|
||||
TS_ASSERT(!(r3 == 2));
|
||||
TS_ASSERT(r3 != 2);
|
||||
|
||||
TS_ASSERT( r4 > r6);
|
||||
TS_ASSERT( r4 >= r6);
|
||||
TS_ASSERT(!(r4 < r6));
|
||||
TS_ASSERT(!(r4 <= r6));
|
||||
|
||||
TS_ASSERT( r4 > 7);
|
||||
TS_ASSERT( r4 >= 7);
|
||||
TS_ASSERT(!(r4 < 7));
|
||||
TS_ASSERT(!(r4 <= 7));
|
||||
|
||||
TS_ASSERT( 7 < r4);
|
||||
TS_ASSERT( 7 <= r4);
|
||||
TS_ASSERT(!(7 > r4));
|
||||
TS_ASSERT(!(7 >= r4));
|
||||
}
|
||||
|
||||
void test_assign() {
|
||||
Common::Rational r0(6, 3);
|
||||
Common::Rational r1(1, 2);
|
||||
|
||||
TS_ASSERT_EQUALS(r0, 2);
|
||||
TS_ASSERT_EQUALS(r1, Common::Rational(1, 2));
|
||||
|
||||
r0 = r1;
|
||||
TS_ASSERT_EQUALS(r0, r1);
|
||||
TS_ASSERT_EQUALS(r0, Common::Rational(1, 2));
|
||||
}
|
||||
|
||||
void test_negative() {
|
||||
Common::Rational r0(6, 3);
|
||||
Common::Rational r1(1, 2);
|
||||
|
||||
r0 = -r0;
|
||||
r1 = -r1;
|
||||
TS_ASSERT_EQUALS(r0, -2);
|
||||
TS_ASSERT_EQUALS(r1, Common::Rational(-1, 2));
|
||||
TS_ASSERT_EQUALS(r1, Common::Rational(1, -2));
|
||||
|
||||
TS_ASSERT_EQUALS(r1, Common::Rational(-25, 50));
|
||||
TS_ASSERT_EQUALS(r1, Common::Rational(25, -50));
|
||||
}
|
||||
|
||||
void test_add_sub() {
|
||||
const Common::Rational r0(6, 3);
|
||||
const Common::Rational r1(1, 2);
|
||||
|
||||
TS_ASSERT_EQUALS(r0 + r1, Common::Rational(5, 2));
|
||||
TS_ASSERT_EQUALS(r1 + r0, Common::Rational(5, 2));
|
||||
TS_ASSERT_EQUALS(r0 - r1, Common::Rational(3, 2));
|
||||
TS_ASSERT_EQUALS(r1 - r0, Common::Rational(-3, 2));
|
||||
|
||||
TS_ASSERT_EQUALS(1 + r1, Common::Rational(3, 2));
|
||||
TS_ASSERT_EQUALS(r1 + 1, Common::Rational(3, 2));
|
||||
TS_ASSERT_EQUALS(1 - r1, Common::Rational(1, 2));
|
||||
TS_ASSERT_EQUALS(r1 - 1, Common::Rational(-1, 2));
|
||||
}
|
||||
|
||||
void test_add_sub2() {
|
||||
// Make sure cancelation works correctly
|
||||
const Common::Rational r0(4, 15); // = 8 / 30
|
||||
const Common::Rational r1(1, 6); // = 5 / 30
|
||||
|
||||
TS_ASSERT_EQUALS(r0 + r1, Common::Rational(13, 30));
|
||||
TS_ASSERT_EQUALS(r1 + r0, Common::Rational(13, 30));
|
||||
TS_ASSERT_EQUALS(r0 - r1, Common::Rational(1, 10));
|
||||
TS_ASSERT_EQUALS(r1 - r0, Common::Rational(-1, 10));
|
||||
|
||||
TS_ASSERT_EQUALS(1 + r1, Common::Rational(7, 6));
|
||||
TS_ASSERT_EQUALS(r1 + 1, Common::Rational(7, 6));
|
||||
TS_ASSERT_EQUALS(1 - r1, Common::Rational(5, 6));
|
||||
TS_ASSERT_EQUALS(r1 - 1, Common::Rational(-5, 6));
|
||||
}
|
||||
|
||||
void test_mul() {
|
||||
const Common::Rational r0(6, 3);
|
||||
const Common::Rational r1(1, 2);
|
||||
|
||||
const Common::Rational r2(15, 14);
|
||||
const Common::Rational r3(7,3);
|
||||
const Common::Rational r4(5,2);
|
||||
|
||||
TS_ASSERT_EQUALS(r0 * r1, 1);
|
||||
|
||||
TS_ASSERT_EQUALS(r2 * r3, r4);
|
||||
TS_ASSERT_EQUALS((-r2) * r3, -r4);
|
||||
TS_ASSERT_EQUALS(r2 * (-r3), -r4);
|
||||
TS_ASSERT_EQUALS((-r2) * (-r3), r4);
|
||||
|
||||
TS_ASSERT_EQUALS(r1 * 2, 1);
|
||||
TS_ASSERT_EQUALS(2 * r1, 1);
|
||||
}
|
||||
|
||||
void test_div() {
|
||||
Common::Rational r0(6, 3);
|
||||
Common::Rational r1(1, 2);
|
||||
|
||||
TS_ASSERT_EQUALS(r0 / r1, 4);
|
||||
|
||||
TS_ASSERT_EQUALS(r1 / 2, Common::Rational(1, 4));
|
||||
TS_ASSERT_EQUALS(2 / r1, Common::Rational(4, 1));
|
||||
}
|
||||
|
||||
void test_isOne() {
|
||||
Common::Rational r0(5, 5);
|
||||
Common::Rational r1(1, 2);
|
||||
Common::Rational r2(2, 1);
|
||||
Common::Rational r3(1, 1);
|
||||
TS_ASSERT(r0.isOne());
|
||||
TS_ASSERT(!r1.isOne());
|
||||
TS_ASSERT(!r2.isOne());
|
||||
TS_ASSERT(r3.isOne());
|
||||
}
|
||||
};
|
||||
62
test/common/rect.h
Normal file
62
test/common/rect.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
class RectTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_point_sqrDist() {
|
||||
Common::Point p0;
|
||||
Common::Point p11(1, 1);
|
||||
Common::Point p21(2, 1);
|
||||
Common::Point p23(2, 3);
|
||||
Common::Point p32(3, 2);
|
||||
TS_ASSERT_EQUALS(p0.sqrDist(p11), (uint) 2);
|
||||
TS_ASSERT_EQUALS(p0.sqrDist(p21), (uint) 5);
|
||||
TS_ASSERT_EQUALS(p0.sqrDist(p23), p0.sqrDist(p32));
|
||||
TS_ASSERT_EQUALS(p11.sqrDist(p11), (uint) 0);
|
||||
TS_ASSERT_EQUALS(p11.sqrDist(p23), (uint) 5);
|
||||
}
|
||||
|
||||
void test_intersects() {
|
||||
TS_ASSERT(Common::Rect(0, 0, 2, 2).intersects(Common::Rect(0, 0, 1, 1)));
|
||||
TS_ASSERT(Common::Rect(0, 0, 2, 2).intersects(Common::Rect(1, 1, 2, 2)));
|
||||
TS_ASSERT(!Common::Rect(0, 0, 1, 1).intersects(Common::Rect(1, 1, 2, 2)));
|
||||
}
|
||||
|
||||
void test_contains() {
|
||||
Common::Rect r0;
|
||||
Common::Rect r1(0, 0, 1, 1);
|
||||
Common::Rect r2(0, 0, 2, 2);
|
||||
TS_ASSERT(!r0.contains(r1));
|
||||
TS_ASSERT(!r0.contains(r2));
|
||||
TS_ASSERT(!r1.contains(r2));
|
||||
TS_ASSERT(r0.contains(r0));
|
||||
|
||||
TS_ASSERT(r1.contains(r0));
|
||||
TS_ASSERT(r1.contains(r1));
|
||||
|
||||
TS_ASSERT(r2.contains(r0));
|
||||
TS_ASSERT(r2.contains(r1));
|
||||
TS_ASSERT(r2.contains(r2));
|
||||
}
|
||||
|
||||
void test_extend() {
|
||||
Common::Rect r0;
|
||||
Common::Rect r1(0, 0, 1, 1);
|
||||
Common::Rect r2(0, 0, 2, 2);
|
||||
TS_ASSERT(!r0.contains(r1));
|
||||
r0.extend(r1);
|
||||
TS_ASSERT(r0.contains(r1));
|
||||
TS_ASSERT_EQUALS(r0.top, 0);
|
||||
TS_ASSERT_EQUALS(r0.left, 0);
|
||||
TS_ASSERT_EQUALS(r0.bottom, 1);
|
||||
TS_ASSERT_EQUALS(r0.right, 1);
|
||||
r2.extend(r1);
|
||||
TS_ASSERT_EQUALS(r2.top, 0);
|
||||
TS_ASSERT_EQUALS(r2.left, 0);
|
||||
TS_ASSERT_EQUALS(r2.bottom, 2);
|
||||
TS_ASSERT_EQUALS(r2.right, 2);
|
||||
}
|
||||
|
||||
};
|
||||
83
test/common/rendermode.h
Normal file
83
test/common/rendermode.h
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
#include "common/rendermode.h"
|
||||
#include "common/gui_options.h"
|
||||
#include "common/str.h"
|
||||
|
||||
class RenderModeTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_parse_render_mode_good() {
|
||||
/*
|
||||
* Tests for parseRenderMode.
|
||||
* It takes a code (case-insensitive) and spits a RenderMode back at you.
|
||||
* These cases should work - the inputs are standard, there's just some
|
||||
* fun with caps being had in here.
|
||||
*/
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("fMTOwNs"), Common::kRenderFMTowns);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("hercGrEen"), Common::kRenderHercG);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("hercAmbeR"), Common::kRenderHercA);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("CgA"), Common::kRenderCGA);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("ega"), Common::kRenderEGA);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("Vga"), Common::kRenderVGA);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("AmigA"), Common::kRenderAmiga);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("pc98-256c"), Common::kRenderPC98_256c);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("PC98-16c"), Common::kRenderPC98_16c);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("0"), Common::kRenderDefault);
|
||||
}
|
||||
|
||||
|
||||
void test_parse_render_mode_bad() {
|
||||
/*
|
||||
* These cases, according to the specification, should return the default.
|
||||
* It is only mentioned that the function must be case insensitive.
|
||||
* Whitespaces, in particular, should not be automatically trimmed.
|
||||
*/
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("fmtowns "), Common::kRenderDefault);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("FM-TOWNS "), Common::kRenderDefault);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode(" cga"), Common::kRenderDefault);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("\tC g A"), Common::kRenderDefault);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("\t"), Common::kRenderDefault);
|
||||
// This is the only interesting bit: if the function was really, really
|
||||
// broken it could be tempted to test for +-0x20.
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("pc Y8 -256c "), Common::kRenderDefault);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode(" PC\t98-16c "), Common::kRenderDefault);
|
||||
TS_ASSERT_EQUALS(Common::parseRenderMode("0"), Common::kRenderDefault);
|
||||
}
|
||||
|
||||
void test_get_render_mode_code_back_and_forth() {
|
||||
/*
|
||||
* What does getRenderModeCode return?
|
||||
* Notably, the output should not be in mixed case.
|
||||
*/
|
||||
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("FMTOWNS")), "fmtowns", 7);
|
||||
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("CGA")), "cga", 3);
|
||||
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("vga")), "vga", 3);
|
||||
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("Ega")), "ega", 3);
|
||||
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("AmiGa")), "amiga", 5);
|
||||
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("PC98-256C")), "pc98-256c", 9);
|
||||
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("PC98-16C")), "pc98-16c", 8);
|
||||
// Slightly more interesting:
|
||||
// Make sure that we get a null pointer for 0 (and not the "0" string or stuff)
|
||||
char *null_p = 0;
|
||||
TS_ASSERT_EQUALS(Common::getRenderModeCode(Common::kRenderDefault), null_p);
|
||||
}
|
||||
|
||||
void test_render_2_guio() {
|
||||
/*
|
||||
* Verify that a rendermode is taken and the corresponding
|
||||
* GUIO_xxxxx is returned.
|
||||
*/
|
||||
TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderHercG), GUIO_RENDERHERCGREEN);
|
||||
TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderHercA), GUIO_RENDERHERCAMBER);
|
||||
TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderCGA), GUIO_RENDERCGA);
|
||||
TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderEGA), GUIO_RENDEREGA);
|
||||
TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderVGA), GUIO_RENDERVGA);
|
||||
TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderAmiga), GUIO_RENDERAMIGA);
|
||||
TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderFMTowns), GUIO_RENDERFMTOWNS);
|
||||
TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderPC98_256c), GUIO_RENDERPC98_256C);
|
||||
TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderPC98_16c), GUIO_RENDERPC98_16C);
|
||||
// renderMode2GUIO is supposed to return an empty string
|
||||
// if given kRenderDefault as an argument
|
||||
Common::String empty;
|
||||
TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderDefault), empty);
|
||||
}
|
||||
};
|
||||
73
test/common/seekablesubreadstream.h
Normal file
73
test/common/seekablesubreadstream.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/memstream.h"
|
||||
#include "common/substream.h"
|
||||
|
||||
class SeekableSubReadStreamTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_traverse() {
|
||||
byte contents[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
Common::MemoryReadStream ms(contents, 10);
|
||||
|
||||
int start = 2, end = 8;
|
||||
|
||||
Common::SeekableSubReadStream ssrs(&ms, start, end);
|
||||
|
||||
int i;
|
||||
byte b;
|
||||
for (i = start; i < end; ++i) {
|
||||
TS_ASSERT(!ssrs.eos());
|
||||
|
||||
TS_ASSERT_EQUALS(i - start, ssrs.pos());
|
||||
|
||||
ssrs.read(&b, 1);
|
||||
TS_ASSERT_EQUALS(i, b);
|
||||
}
|
||||
|
||||
TS_ASSERT(!ssrs.eos());
|
||||
TS_ASSERT_EQUALS((uint)0, ssrs.read(&b, 1));
|
||||
TS_ASSERT(ssrs.eos());
|
||||
}
|
||||
|
||||
void test_seek() {
|
||||
byte contents[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
Common::MemoryReadStream ms(contents, 10);
|
||||
|
||||
Common::SeekableSubReadStream ssrs(&ms, 1, 9);
|
||||
byte b;
|
||||
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 0);
|
||||
|
||||
ssrs.seek(1, SEEK_SET);
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 1);
|
||||
b = ssrs.readByte();
|
||||
TS_ASSERT_EQUALS(b, 2);
|
||||
|
||||
ssrs.seek(5, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 7);
|
||||
b = ssrs.readByte();
|
||||
TS_ASSERT_EQUALS(b, 8);
|
||||
|
||||
ssrs.seek(-3, SEEK_CUR);
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 5);
|
||||
b = ssrs.readByte();
|
||||
TS_ASSERT_EQUALS(b, 6);
|
||||
|
||||
ssrs.seek(0, SEEK_END);
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 8);
|
||||
TS_ASSERT(!ssrs.eos());
|
||||
b = ssrs.readByte();
|
||||
TS_ASSERT(ssrs.eos());
|
||||
|
||||
ssrs.seek(-3, SEEK_END);
|
||||
TS_ASSERT(!ssrs.eos());
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 5);
|
||||
b = ssrs.readByte();
|
||||
TS_ASSERT_EQUALS(b, 6);
|
||||
|
||||
ssrs.seek(-8, SEEK_END);
|
||||
TS_ASSERT_EQUALS(ssrs.pos(), 0);
|
||||
b = ssrs.readByte();
|
||||
TS_ASSERT_EQUALS(b, 1);
|
||||
}
|
||||
};
|
||||
111
test/common/serializer.h
Normal file
111
test/common/serializer.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
class SerializerTestSuite : public CxxTest::TestSuite {
|
||||
Common::SeekableReadStream *_inStreamV1;
|
||||
Common::SeekableReadStream *_inStreamV2;
|
||||
public:
|
||||
void setUp() {
|
||||
// Our pseudo data format is as follows:
|
||||
// * magic id - string "MAGI"
|
||||
// * Version - uint32, LE
|
||||
// * uint32, LE (available in v2 onward)
|
||||
// * uint16, BE (available in v1 onward)
|
||||
// * sint16, LE (available only in v1)
|
||||
// * byte (always available)
|
||||
static const byte contents_v1[] = {
|
||||
'M', 'A', 'G', 'I', // magic id
|
||||
0x01, 0x00, 0x00, 0x00, // Version
|
||||
0x06, 0x07, // uint16, BE (available in v1 onward)
|
||||
0xfe, 0xff, // sint16, LE (available only in v1)
|
||||
0x0a // byte (always available)
|
||||
};
|
||||
static const byte contents_v2[] = {
|
||||
'M', 'A', 'G', 'I', // magic id
|
||||
0x02, 0x00, 0x00, 0x00, // Version
|
||||
0x02, 0x03, 0x04, 0x05, // uint32, LE (available in v2 onward)
|
||||
0x06, 0x07, // uint16, BE (available in v1 onward)
|
||||
0x0a // byte (always available)
|
||||
};
|
||||
|
||||
_inStreamV1 = new Common::MemoryReadStream(contents_v1, sizeof(contents_v1));
|
||||
_inStreamV2 = new Common::MemoryReadStream(contents_v2, sizeof(contents_v2));
|
||||
}
|
||||
|
||||
void tearDown() {
|
||||
delete _inStreamV1;
|
||||
delete _inStreamV2;
|
||||
}
|
||||
|
||||
// A method which reads a v1 file
|
||||
void readVersioned_v1(Common::SeekableReadStream *stream, Common::Serializer::Version version) {
|
||||
Common::Serializer ser(stream, 0);
|
||||
|
||||
TS_ASSERT(ser.matchBytes("MAGI", 4));
|
||||
|
||||
TS_ASSERT(ser.syncVersion(1));
|
||||
TS_ASSERT_EQUALS(ser.getVersion(), version);
|
||||
|
||||
uint32 tmp = 0;
|
||||
|
||||
ser.syncAsUint16BE(tmp, Common::Serializer::Version(1));
|
||||
TS_ASSERT_EQUALS(tmp, (uint16)0x0607);
|
||||
|
||||
ser.syncAsSint16LE(tmp, Common::Serializer::Version(1));
|
||||
TS_ASSERT_EQUALS((int16)tmp, -2);
|
||||
|
||||
ser.syncAsByte(tmp);
|
||||
TS_ASSERT_EQUALS(tmp, (uint8)0x0a);
|
||||
}
|
||||
|
||||
// A method which reads a v2 file
|
||||
void readVersioned_v2(Common::SeekableReadStream *stream, Common::Serializer::Version version) {
|
||||
Common::Serializer ser(stream, 0);
|
||||
|
||||
TS_ASSERT(ser.matchBytes("MAGI", 4));
|
||||
|
||||
TS_ASSERT(ser.syncVersion(2));
|
||||
TS_ASSERT_EQUALS(ser.getVersion(), version);
|
||||
|
||||
uint32 tmp;
|
||||
|
||||
// Read a value only available starting with v2.
|
||||
// Thus if we load an old save, it must be
|
||||
// manually set. To simplify that, no sync method should
|
||||
// modify the value passed to it if nothing was read!
|
||||
tmp = 0x12345678;
|
||||
ser.syncAsUint32LE(tmp, Common::Serializer::Version(2));
|
||||
if (ser.getVersion() < 2) {
|
||||
TS_ASSERT_EQUALS(tmp, (uint32)0x12345678);
|
||||
} else {
|
||||
TS_ASSERT_EQUALS(tmp, (uint32)0x05040302);
|
||||
}
|
||||
|
||||
ser.syncAsUint16BE(tmp, Common::Serializer::Version(1));
|
||||
TS_ASSERT_EQUALS(tmp, (uint32)0x0607);
|
||||
|
||||
// Skip over obsolete data
|
||||
ser.skip(2, Common::Serializer::Version(1), Common::Serializer::Version(1));
|
||||
|
||||
ser.syncAsByte(tmp);
|
||||
TS_ASSERT_EQUALS(tmp, (uint8)0x0a);
|
||||
}
|
||||
|
||||
void test_read_v1_as_v1() {
|
||||
readVersioned_v1(_inStreamV1, 1);
|
||||
}
|
||||
|
||||
// There is no test_read_v2_as_v1() because a v1 parser cannot possibly
|
||||
// read v2 data correctly. It should instead error out if it
|
||||
// detects a version newer than its current version.
|
||||
|
||||
void test_read_v1_as_v2() {
|
||||
readVersioned_v2(_inStreamV1, 1);
|
||||
}
|
||||
|
||||
void test_read_v2_as_v2() {
|
||||
readVersioned_v2(_inStreamV2, 2);
|
||||
}
|
||||
};
|
||||
810
test/common/span.h
Normal file
810
test/common/span.h
Normal file
@@ -0,0 +1,810 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
class SpanTestSuite;
|
||||
|
||||
#include "common/span.h"
|
||||
#include "common/str.h"
|
||||
|
||||
class SpanTestSuite : public CxxTest::TestSuite {
|
||||
struct Foo {
|
||||
int a;
|
||||
};
|
||||
|
||||
template <typename ValueType, template <typename> class Derived>
|
||||
class SiblingSpanImpl : public Common::SpanImpl<ValueType, Derived> {
|
||||
typedef Common::SpanImpl<ValueType, Derived> super_type;
|
||||
public:
|
||||
COMMON_SPAN_TYPEDEFS;
|
||||
SiblingSpanImpl() = default;
|
||||
SiblingSpanImpl(pointer data_, size_type size_) : super_type(data_, size_) {}
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
class SiblingSpan : public SiblingSpanImpl<ValueType, SiblingSpan> {
|
||||
typedef SiblingSpanImpl<ValueType, ::SpanTestSuite::SiblingSpan> super_type;
|
||||
public:
|
||||
COMMON_SPAN_TYPEDEFS;
|
||||
SiblingSpan() = default;
|
||||
SiblingSpan(pointer data_, size_type size_) : super_type(data_, size_) {}
|
||||
};
|
||||
|
||||
template <typename ValueType, template <typename> class Derived>
|
||||
class SubSpanImpl : public Common::NamedSpanImpl<ValueType, Derived> {
|
||||
typedef Common::NamedSpanImpl<ValueType, Derived> super_type;
|
||||
public:
|
||||
COMMON_SPAN_TYPEDEFS;
|
||||
SubSpanImpl() = default;
|
||||
SubSpanImpl(pointer data_,
|
||||
size_type size_,
|
||||
const Common::String &name_ = Common::String(),
|
||||
const size_type sourceByteOffset_ = 0) :
|
||||
super_type(data_, size_, name_, sourceByteOffset_) {}
|
||||
|
||||
template <typename Other>
|
||||
SubSpanImpl(const Other &other) : super_type(other) {}
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
class SubSpan : public SubSpanImpl<ValueType, SubSpan> {
|
||||
typedef SubSpanImpl<ValueType, ::SpanTestSuite::SubSpan> super_type;
|
||||
public:
|
||||
COMMON_SPAN_TYPEDEFS;
|
||||
SubSpan() = default;
|
||||
SubSpan(pointer data_,
|
||||
size_type size_,
|
||||
const Common::String &name_ = Common::String(),
|
||||
const size_type sourceByteOffset_ = 0) :
|
||||
super_type(data_, size_, name_, sourceByteOffset_) {}
|
||||
|
||||
template <typename Other>
|
||||
SubSpan(const Other &other) : super_type(other) {}
|
||||
};
|
||||
|
||||
public:
|
||||
void test_sibling_span() {
|
||||
byte data[] = { 'h', 'e', 'l', 'l', 'o' };
|
||||
SiblingSpan<byte> ss(data, sizeof(data));
|
||||
Common::Span<byte> superInstance = ss;
|
||||
TS_ASSERT_EQUALS(ss.data(), data);
|
||||
TS_ASSERT_EQUALS(superInstance.data(), data);
|
||||
}
|
||||
|
||||
void test_sub_span() {
|
||||
byte data[] = { 'h', 'e', 'l', 'l', 'o' };
|
||||
SubSpan<byte> ss(data, sizeof(data), "custom subspan");
|
||||
Common::NamedSpan<byte> namedSuper = ss;
|
||||
Common::Span<byte> unnamedSuper = ss;
|
||||
TS_ASSERT(ss.name() == "custom subspan");
|
||||
TS_ASSERT(namedSuper.name() == ss.name());
|
||||
TS_ASSERT(unnamedSuper.name() == Common::String::format("%p", (void *)data));
|
||||
}
|
||||
|
||||
void test_span_iterator_const() {
|
||||
byte data[] = { 'h', 'e', 'l', 'l', 'o' };
|
||||
const Common::Span<byte> span(data, sizeof(data));
|
||||
|
||||
Common::Span<byte>::const_iterator it = span.cbegin();
|
||||
|
||||
Common::Span<byte>::const_iterator sameIt(it);
|
||||
|
||||
TS_ASSERT_EQUALS(sameIt, it);
|
||||
|
||||
uint i;
|
||||
for (i = 0; it != span.cend(); ++i, ++it) {
|
||||
TS_ASSERT_EQUALS(*it, data[i]);
|
||||
TS_ASSERT_LESS_THAN(i, sizeof(data));
|
||||
}
|
||||
TS_ASSERT_EQUALS(i, sizeof(data));
|
||||
|
||||
it = span.cend() - 1;
|
||||
for (i = sizeof(data) - 1; it != span.cbegin(); --i, --it) {
|
||||
TS_ASSERT_EQUALS(data[i], *it);
|
||||
}
|
||||
TS_ASSERT_EQUALS(i, 0U);
|
||||
|
||||
it = span.cbegin();
|
||||
|
||||
it += 4;
|
||||
TS_ASSERT_EQUALS(data[4], *it);
|
||||
|
||||
it -= 4;
|
||||
TS_ASSERT_EQUALS(data[0], *it);
|
||||
|
||||
TS_ASSERT_EQUALS(data[0], *it++);
|
||||
|
||||
TS_ASSERT_EQUALS(data[1], *it--);
|
||||
|
||||
TS_ASSERT_EQUALS(span.cend() - span.cbegin(), 5);
|
||||
|
||||
TS_ASSERT_EQUALS(*(span.cbegin() + 4), data[4]);
|
||||
|
||||
TS_ASSERT_EQUALS(*(span.cend() - 4), data[1]);
|
||||
|
||||
TS_ASSERT(span.cbegin() < span.cend());
|
||||
|
||||
TS_ASSERT(span.cbegin() <= span.cend());
|
||||
TS_ASSERT(span.cbegin() <= span.cbegin());
|
||||
|
||||
TS_ASSERT(span.cend() > span.cbegin());
|
||||
|
||||
TS_ASSERT(span.cend() >= span.cbegin());
|
||||
TS_ASSERT(span.cend() >= span.cend());
|
||||
}
|
||||
|
||||
void test_span_iterator() {
|
||||
byte data[] = { 'h', 'e', 'l', 'l', 'o' };
|
||||
Common::Span<byte> span(data, sizeof(data));
|
||||
|
||||
// empty iterator should default construct OK
|
||||
Common::Span<byte>::iterator defaultIt;
|
||||
|
||||
Common::Span<byte>::iterator it = span.begin();
|
||||
|
||||
Common::Span<byte>::iterator sameIt(it);
|
||||
|
||||
TS_ASSERT_EQUALS(sameIt, it);
|
||||
|
||||
uint i;
|
||||
for (i = 0; it != span.end(); ++i, ++it) {
|
||||
TS_ASSERT_EQUALS(*it, data[i]);
|
||||
TS_ASSERT_LESS_THAN(i, sizeof(data));
|
||||
}
|
||||
TS_ASSERT_EQUALS(i, sizeof(data));
|
||||
|
||||
it = span.end() - 1;
|
||||
for (i = sizeof(data) - 1; it != span.begin(); --i, --it) {
|
||||
TS_ASSERT_EQUALS(data[i], *it);
|
||||
}
|
||||
TS_ASSERT_EQUALS(i, 0U);
|
||||
|
||||
it = span.begin();
|
||||
|
||||
it += 4;
|
||||
TS_ASSERT_EQUALS(data[4], *it);
|
||||
|
||||
it -= 4;
|
||||
TS_ASSERT_EQUALS(data[0], *it);
|
||||
|
||||
TS_ASSERT_EQUALS(data[0], *it++);
|
||||
|
||||
TS_ASSERT_EQUALS(data[1], *it--);
|
||||
|
||||
TS_ASSERT_EQUALS(span.end() - span.begin(), 5);
|
||||
|
||||
TS_ASSERT_EQUALS(*(span.begin() + 4), data[4]);
|
||||
|
||||
TS_ASSERT_EQUALS(*(span.end() - 4), data[1]);
|
||||
|
||||
TS_ASSERT(span.begin() < span.end());
|
||||
|
||||
TS_ASSERT(span.begin() <= span.end());
|
||||
TS_ASSERT(span.begin() <= span.begin());
|
||||
|
||||
TS_ASSERT(span.end() > span.begin());
|
||||
|
||||
TS_ASSERT(span.end() >= span.begin());
|
||||
TS_ASSERT(span.end() >= span.end());
|
||||
|
||||
it = span.begin();
|
||||
for (i = 0; it != span.end(); ++i, ++it) {
|
||||
*it = 'a' + i;
|
||||
}
|
||||
|
||||
it = span.begin();
|
||||
for (i = 0; it != span.end(); ++i, ++it) {
|
||||
TS_ASSERT_EQUALS(*it, 'a' + i);
|
||||
TS_ASSERT_EQUALS(data[i], 'a' + i);
|
||||
}
|
||||
}
|
||||
|
||||
void test_span_iterator_integers() {
|
||||
const byte data[] = { 0xFF, 1, 2, 3, 2, 1, 0xFF };
|
||||
Common::Span<const byte> span(data, sizeof(data));
|
||||
Common::Span<const byte>::const_iterator it = span.cbegin();
|
||||
|
||||
TS_ASSERT_EQUALS(it.getInt8(), -1);
|
||||
TS_ASSERT_EQUALS(it.getUint8(), 255);
|
||||
TS_ASSERT_EQUALS(it.getInt16BE(), -255);
|
||||
TS_ASSERT_EQUALS(it.getUint16BE(), 65281U);
|
||||
TS_ASSERT_EQUALS((it + 5).getInt16LE(), -255);
|
||||
TS_ASSERT_EQUALS((it + 5).getUint16LE(), 65281U);
|
||||
TS_ASSERT_EQUALS(it.getUint24LE(), 131583U);
|
||||
#if defined(SCUMM_LITTLE_ENDIAN)
|
||||
TS_ASSERT_EQUALS((it + 3).getUint32(), 4278256131U);
|
||||
#elif defined(SCUMM_BIG_ENDIAN)
|
||||
TS_ASSERT_EQUALS(it.getUint32(), 4278256131U);
|
||||
#else
|
||||
#error No endianness detected
|
||||
#endif
|
||||
TS_ASSERT_EQUALS(it.getInt32BE(), -16711165);
|
||||
TS_ASSERT_EQUALS(it.getUint32BE(), 4278256131U);
|
||||
TS_ASSERT_EQUALS((it + 3).getInt32LE(), -16711165);
|
||||
TS_ASSERT_EQUALS((it + 3).getUint32LE(), 4278256131U);
|
||||
}
|
||||
|
||||
void test_span_iterator_ptr() {
|
||||
Foo foo[2];
|
||||
foo[0].a = 1;
|
||||
foo[1].a = 2;
|
||||
|
||||
const Common::Span<Foo> span(foo, 2);
|
||||
Common::Span<Foo>::const_iterator it = span.cbegin();
|
||||
TS_ASSERT_EQUALS(it->a, 1);
|
||||
++it;
|
||||
TS_ASSERT_EQUALS(it->a, 2);
|
||||
|
||||
TS_ASSERT_EQUALS(it[0].a, 2);
|
||||
TS_ASSERT_EQUALS(it[-1].a, 1);
|
||||
--it;
|
||||
TS_ASSERT_EQUALS(it[1].a, 2);
|
||||
}
|
||||
|
||||
void test_span_owner() {
|
||||
Common::SpanOwner<Common::Span<byte> > owner;
|
||||
owner->allocate(3);
|
||||
owner[0] = 'a';
|
||||
owner[1] = 'b';
|
||||
owner[2] = 'c';
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
TS_ASSERT_EQUALS(owner->getUint8At(i), 'a' + i);
|
||||
TS_ASSERT_EQUALS((*owner)[i], 'a' + i);
|
||||
}
|
||||
|
||||
{
|
||||
Common::SpanOwner<Common::NamedSpan<byte> > owner2;
|
||||
TS_ASSERT(owner2->data() == nullptr);
|
||||
owner2->allocateFromSpan(*owner);
|
||||
TS_ASSERT(owner2->data() != nullptr);
|
||||
TS_ASSERT_DIFFERS(owner->data(), owner2->data());
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
TS_ASSERT_EQUALS(owner2->getUint8At(i), 'a' + i);
|
||||
TS_ASSERT_EQUALS((*owner2)[i], 'a' + i);
|
||||
}
|
||||
|
||||
TS_ASSERT_EQUALS((bool)owner2, true);
|
||||
owner2.clear();
|
||||
TS_ASSERT_EQUALS((bool)owner2, false);
|
||||
}
|
||||
|
||||
{
|
||||
Common::SpanOwner<Common::Span<byte> > owner2;
|
||||
TS_ASSERT(owner2->data() == nullptr);
|
||||
owner2 = owner;
|
||||
TS_ASSERT(owner2->data() != nullptr);
|
||||
TS_ASSERT_DIFFERS(owner->data(), owner2->data());
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
TS_ASSERT_EQUALS(owner2->getUint8At(i), 'a' + i);
|
||||
TS_ASSERT_EQUALS((*owner2)[i], 'a' + i);
|
||||
}
|
||||
|
||||
TS_ASSERT_EQUALS((bool)owner2, true);
|
||||
owner2.clear();
|
||||
TS_ASSERT_EQUALS((bool)owner2, false);
|
||||
}
|
||||
|
||||
{
|
||||
Common::SpanOwner<Common::Span<byte> > owner2;
|
||||
TS_ASSERT_EQUALS((bool)owner, true);
|
||||
void *dataPtr = owner->data();
|
||||
owner2.moveFrom(owner);
|
||||
TS_ASSERT_EQUALS((bool)owner, false);
|
||||
TS_ASSERT(owner->data() == nullptr);
|
||||
TS_ASSERT_EQUALS(owner2->data(), dataPtr);
|
||||
|
||||
// tests destruction of held pointer by reassignment
|
||||
owner2 = owner;
|
||||
|
||||
// tests nullipotence of assignment to self
|
||||
dataPtr = owner2->data();
|
||||
owner2 = owner2;
|
||||
TS_ASSERT(owner2->data() == dataPtr);
|
||||
}
|
||||
|
||||
{
|
||||
char *data = new char[6];
|
||||
Common::strlcpy(data, "hello", 6);
|
||||
const Common::SpanOwner<Common::Span<const char> > constOwner(Common::Span<const char>(data, 6));
|
||||
TS_ASSERT_EQUALS((*constOwner)[0], 'h');
|
||||
TS_ASSERT_EQUALS(constOwner->getUint8At(1), 'e');
|
||||
TS_ASSERT_EQUALS(constOwner[2], 'l');
|
||||
}
|
||||
|
||||
{
|
||||
TS_ASSERT_EQUALS((bool)owner, false);
|
||||
Common::SpanOwner<Common::Span<byte> > owner2(owner);
|
||||
TS_ASSERT_EQUALS((bool)owner2, false);
|
||||
}
|
||||
|
||||
{
|
||||
owner->allocate(1);
|
||||
TS_ASSERT_EQUALS((bool)owner, true);
|
||||
Common::SpanOwner<Common::Span<byte> > owner2(owner);
|
||||
TS_ASSERT_EQUALS((bool)owner2, true);
|
||||
TS_ASSERT_DIFFERS(owner->data(), owner2->data());
|
||||
}
|
||||
|
||||
{
|
||||
TS_ASSERT_EQUALS((bool)owner, true);
|
||||
byte *dataPtr = owner->data();
|
||||
TS_ASSERT_EQUALS(owner.release(), dataPtr);
|
||||
TS_ASSERT_EQUALS((bool)owner, false);
|
||||
delete[] dataPtr;
|
||||
}
|
||||
}
|
||||
|
||||
void test_span_owner_named_span() {
|
||||
Common::SpanOwner<Common::NamedSpan<byte> > owner;
|
||||
owner->allocate(3, "foo");
|
||||
owner[0] = 'a';
|
||||
owner[1] = 'b';
|
||||
owner[2] = 'c';
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
TS_ASSERT_EQUALS(owner->getUint8At(i), 'a' + i);
|
||||
TS_ASSERT_EQUALS((*owner)[i], 'a' + i);
|
||||
}
|
||||
TS_ASSERT(owner->name() == "foo");
|
||||
|
||||
{
|
||||
Common::SpanOwner<Common::NamedSpan<byte> > owner2;
|
||||
TS_ASSERT(owner2->data() == nullptr);
|
||||
owner2->allocateFromSpan(*owner);
|
||||
TS_ASSERT(owner2->data() != nullptr);
|
||||
TS_ASSERT_DIFFERS(owner->data(), owner2->data());
|
||||
TS_ASSERT(owner2->name() == "foo");
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
TS_ASSERT_EQUALS(owner2->getUint8At(i), 'a' + i);
|
||||
TS_ASSERT_EQUALS((*owner2)[i], 'a' + i);
|
||||
}
|
||||
|
||||
TS_ASSERT_EQUALS((bool)owner2, true);
|
||||
owner2.clear();
|
||||
TS_ASSERT_EQUALS((bool)owner2, false);
|
||||
}
|
||||
|
||||
{
|
||||
Common::SpanOwner<Common::NamedSpan<byte> > owner2;
|
||||
TS_ASSERT_EQUALS((bool)owner, true);
|
||||
void *dataPtr = owner->data();
|
||||
owner2.moveFrom(owner);
|
||||
TS_ASSERT_EQUALS((bool)owner, false);
|
||||
TS_ASSERT(owner->data() == nullptr);
|
||||
TS_ASSERT_EQUALS(owner2->data(), dataPtr);
|
||||
|
||||
// tests destruction of held pointer by reassignment
|
||||
owner2 = owner;
|
||||
}
|
||||
|
||||
{
|
||||
char *data = new char[6];
|
||||
Common::strlcpy(data, "hello", 6);
|
||||
const Common::SpanOwner<Common::NamedSpan<const char> > constOwner(Common::NamedSpan<const char>(data, 6));
|
||||
TS_ASSERT_EQUALS((*constOwner)[0], 'h');
|
||||
TS_ASSERT_EQUALS(constOwner->getUint8At(1), 'e');
|
||||
TS_ASSERT_EQUALS(constOwner[2], 'l');
|
||||
}
|
||||
|
||||
{
|
||||
TS_ASSERT_EQUALS((bool)owner, false);
|
||||
Common::SpanOwner<Common::NamedSpan<byte> > owner2(owner);
|
||||
TS_ASSERT_EQUALS((bool)owner2, false);
|
||||
}
|
||||
|
||||
{
|
||||
owner->allocate(1);
|
||||
TS_ASSERT_EQUALS((bool)owner, true);
|
||||
Common::SpanOwner<Common::NamedSpan<byte> > owner2(owner);
|
||||
TS_ASSERT_EQUALS((bool)owner2, true);
|
||||
TS_ASSERT_DIFFERS(owner->data(), owner2->data());
|
||||
}
|
||||
|
||||
{
|
||||
TS_ASSERT_EQUALS((bool)owner, true);
|
||||
byte *dataPtr = owner->data();
|
||||
TS_ASSERT_EQUALS(owner.release(), dataPtr);
|
||||
TS_ASSERT_EQUALS((bool)owner, false);
|
||||
delete[] dataPtr;
|
||||
}
|
||||
}
|
||||
|
||||
void test_span_allocate_from_stream() {
|
||||
byte data[] = "hello";
|
||||
Common::MemoryReadStream stream(data, sizeof(data));
|
||||
Common::SpanOwner<Common::Span<byte> > owner;
|
||||
owner->allocateFromStream(stream, 2);
|
||||
TS_ASSERT(owner->data() != data);
|
||||
TS_ASSERT_EQUALS(owner->size(), 2U);
|
||||
TS_ASSERT_EQUALS(owner[0], 'h');
|
||||
TS_ASSERT_EQUALS(owner[1], 'e');
|
||||
owner.clear();
|
||||
TS_ASSERT(owner->data() == nullptr);
|
||||
stream.seek(0, SEEK_SET);
|
||||
|
||||
owner->allocateFromStream(stream);
|
||||
TS_ASSERT(owner->data() != data);
|
||||
TS_ASSERT_EQUALS(owner->size(), sizeof(data));
|
||||
TS_ASSERT_EQUALS(owner[0], 'h');
|
||||
TS_ASSERT_EQUALS(owner[1], 'e');
|
||||
TS_ASSERT_EQUALS(owner[2], 'l');
|
||||
TS_ASSERT_EQUALS(owner[3], 'l');
|
||||
TS_ASSERT_EQUALS(owner[4], 'o');
|
||||
|
||||
Common::SpanOwner<Common::NamedSpan<const byte> > owner2;
|
||||
stream.seek(0, SEEK_SET);
|
||||
owner2->allocateFromStream(stream, Common::kSpanMaxSize, "streamname");
|
||||
TS_ASSERT(owner2->data() != data);
|
||||
TS_ASSERT_EQUALS(owner2->size(), sizeof(data));
|
||||
TS_ASSERT_EQUALS(owner2[0], 'h');
|
||||
TS_ASSERT_EQUALS(owner2[1], 'e');
|
||||
TS_ASSERT_EQUALS(owner2[2], 'l');
|
||||
TS_ASSERT_EQUALS(owner2[3], 'l');
|
||||
TS_ASSERT_EQUALS(owner2[4], 'o');
|
||||
TS_ASSERT_EQUALS(owner2->name(), "streamname");
|
||||
}
|
||||
|
||||
void test_span_byte() {
|
||||
{
|
||||
byte data[] = { 'h', 'e', 'l', 'l', 'o' };
|
||||
Common::Span<byte> span(data, sizeof(data));
|
||||
|
||||
TS_ASSERT_EQUALS(span.size(), sizeof(data));
|
||||
TS_ASSERT_EQUALS(span.byteSize(), sizeof(data));
|
||||
|
||||
Common::Span<byte> other(span);
|
||||
TS_ASSERT_EQUALS(span, other);
|
||||
other.clear();
|
||||
TS_ASSERT(span != other);
|
||||
|
||||
TS_ASSERT_EQUALS(span[0], 'h');
|
||||
TS_ASSERT_EQUALS(span[1], 'e');
|
||||
span[1] = 'o';
|
||||
TS_ASSERT_EQUALS(span[1], 'o');
|
||||
|
||||
TS_ASSERT((bool)span);
|
||||
span.clear();
|
||||
TS_ASSERT(!(bool)span);
|
||||
}
|
||||
|
||||
{
|
||||
byte data[] = { 'h', 'e', 'l', 'l', 'o' };
|
||||
const Common::Span<const byte> span(data, sizeof(data));
|
||||
|
||||
TS_ASSERT_EQUALS(span.size(), sizeof(data));
|
||||
TS_ASSERT_EQUALS(span.byteSize(), sizeof(data));
|
||||
|
||||
const Common::Span<const byte> other(span);
|
||||
TS_ASSERT_EQUALS(span, other);
|
||||
|
||||
TS_ASSERT_EQUALS(span[0], 'h');
|
||||
TS_ASSERT_EQUALS(span[1], 'e');
|
||||
}
|
||||
}
|
||||
|
||||
void test_span_integers() {
|
||||
const byte data[] = { 0xFF, 1, 2, 3, 2, 1, 0xFF };
|
||||
Common::Span<const byte> span(data, sizeof(data));
|
||||
|
||||
TS_ASSERT_EQUALS(span[0], 255);
|
||||
TS_ASSERT_EQUALS(span.getInt8At(0), -1);
|
||||
TS_ASSERT_EQUALS(span.getUint8At(0), 255U);
|
||||
TS_ASSERT_EQUALS(span.getInt16BEAt(0), -255);
|
||||
TS_ASSERT_EQUALS(span.getUint16BEAt(0), 65281U);
|
||||
TS_ASSERT_EQUALS(span.getInt16LEAt(5), -255);
|
||||
TS_ASSERT_EQUALS(span.getUint16LEAt(5), 65281U);
|
||||
TS_ASSERT_EQUALS(span.getUint24LEAt(0), 131583U);
|
||||
TS_ASSERT_EQUALS(span.getInt32BEAt(0), -16711165);
|
||||
TS_ASSERT_EQUALS(span.getUint32BEAt(0), 4278256131U);
|
||||
TS_ASSERT_EQUALS(span.getInt32LEAt(3), -16711165);
|
||||
TS_ASSERT_EQUALS(span.getUint32LEAt(3), 4278256131U);
|
||||
|
||||
#if defined(SCUMM_LITTLE_ENDIAN)
|
||||
TS_ASSERT_EQUALS(span.getUint32At(3), 4278256131U);
|
||||
#elif defined(SCUMM_BIG_ENDIAN)
|
||||
TS_ASSERT_EQUALS(span.getUint32At(0), 4278256131U);
|
||||
#else
|
||||
#error No endianness detected
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_span_string() {
|
||||
char data[] = "hello";
|
||||
Common::Span<char> span(data, sizeof(data));
|
||||
TS_ASSERT_EQUALS(span[sizeof(data) - 1], '\0');
|
||||
|
||||
TS_ASSERT(span.getStringAt(0) == data);
|
||||
TS_ASSERT(span.getStringAt(0, 2) == "he");
|
||||
TS_ASSERT(span.getStringAt(2) == "llo");
|
||||
TS_ASSERT(span.getStringAt(2, 3) == "llo");
|
||||
span[3] = '\0';
|
||||
TS_ASSERT(span.getStringAt(0) == "hel");
|
||||
}
|
||||
|
||||
void test_span_unsafe_data() {
|
||||
char data[] = "hello";
|
||||
Common::Span<char> span(data, sizeof(data));
|
||||
|
||||
char *ptr = span.getUnsafeDataAt(0, 6);
|
||||
TS_ASSERT_EQUALS(ptr, data);
|
||||
ptr = span.getUnsafeDataAt(0);
|
||||
TS_ASSERT_EQUALS(ptr, data);
|
||||
|
||||
const Common::Span<const char> span2(data, sizeof(data));
|
||||
const char *ptr2 = span2.getUnsafeDataAt(0, 6);
|
||||
TS_ASSERT_EQUALS(ptr2, data);
|
||||
ptr2 = span2.getUnsafeDataAt(0);
|
||||
TS_ASSERT_EQUALS(ptr2, data);
|
||||
}
|
||||
|
||||
void test_span_subspan() {
|
||||
{
|
||||
byte data[] = { 1, 2, 3, 4, 5, 6 };
|
||||
Common::Span<byte> span(data, sizeof(data));
|
||||
|
||||
TS_ASSERT_EQUALS(span.subspan(0).size(), sizeof(data) - 0);
|
||||
TS_ASSERT_EQUALS(span.subspan(2).size(), sizeof(data) - 2);
|
||||
TS_ASSERT_EQUALS(span.subspan(2, 2).size(), 2U);
|
||||
TS_ASSERT_EQUALS(span.subspan<uint16>(0).size(), sizeof(data) / 2);
|
||||
TS_ASSERT_EQUALS(span.subspan<uint16>(0).byteSize(), sizeof(data));
|
||||
TS_ASSERT_EQUALS(span.subspan<uint16>(0, 2).size(), 1U);
|
||||
TS_ASSERT_EQUALS(span.subspan<uint16>(0, 2).byteSize(), 2U);
|
||||
|
||||
#if defined(SCUMM_LITTLE_ENDIAN)
|
||||
TS_ASSERT_EQUALS(span.subspan<uint16>(0)[1], 4 << 8 | 3);
|
||||
#elif defined(SCUMM_BIG_ENDIAN)
|
||||
TS_ASSERT_EQUALS(span.subspan<uint16>(0)[1], 3 << 8 | 4);
|
||||
#else
|
||||
#error No endianness detected
|
||||
#endif
|
||||
|
||||
Common::Span<uint16> shortSpan = span.subspan<uint16>(0);
|
||||
TS_ASSERT_EQUALS(shortSpan.byteSize(), span.byteSize());
|
||||
TS_ASSERT(shortSpan.size() != span.size());
|
||||
shortSpan[1] = 0xFFFF;
|
||||
Common::Span<byte> byteSpan = shortSpan.subspan<byte>(1);
|
||||
TS_ASSERT_EQUALS(byteSpan.size(), sizeof(data) - 1 * sizeof(uint16));
|
||||
TS_ASSERT_EQUALS(byteSpan[0], 0xFF);
|
||||
TS_ASSERT_EQUALS(byteSpan[1], 0xFF);
|
||||
}
|
||||
|
||||
{
|
||||
byte data[] = { 1, 2, 3, 4, 5, 6 };
|
||||
const Common::Span<const byte> span(data, sizeof(data));
|
||||
|
||||
TS_ASSERT_EQUALS(span.subspan(0).size(), sizeof(data) - 0);
|
||||
TS_ASSERT_EQUALS(span.subspan(2).size(), sizeof(data) - 2);
|
||||
TS_ASSERT_EQUALS(span.subspan(2, 2).size(), 2U);
|
||||
TS_ASSERT_EQUALS(span.subspan<uint16>(0).size(), sizeof(data) / 2);
|
||||
TS_ASSERT_EQUALS(span.subspan<uint16>(0).byteSize(), sizeof(data));
|
||||
TS_ASSERT_EQUALS(span.subspan<uint16>(0, 2).size(), 1U);
|
||||
TS_ASSERT_EQUALS(span.subspan<uint16>(0, 2).byteSize(), 2U);
|
||||
|
||||
#if defined(SCUMM_LITTLE_ENDIAN)
|
||||
TS_ASSERT_EQUALS(span.subspan<uint16>(0)[1], 4 << 8 | 3);
|
||||
#elif defined(SCUMM_BIG_ENDIAN)
|
||||
TS_ASSERT_EQUALS(span.subspan<uint16>(0)[1], 3 << 8 | 4);
|
||||
#else
|
||||
#error No endianness detected
|
||||
#endif
|
||||
|
||||
const Common::Span<uint16> shortSpan = span.subspan<uint16>(0);
|
||||
TS_ASSERT_EQUALS(shortSpan.byteSize(), span.byteSize());
|
||||
TS_ASSERT(shortSpan.size() != span.size());
|
||||
Common::Span<byte> byteSpan = shortSpan.subspan<byte>(1);
|
||||
TS_ASSERT_EQUALS(byteSpan.size(), sizeof(data) - 1 * sizeof(uint16));
|
||||
TS_ASSERT_EQUALS(byteSpan[0], 3);
|
||||
TS_ASSERT_EQUALS(byteSpan[1], 4);
|
||||
}
|
||||
}
|
||||
|
||||
void test_span_to_stream() {
|
||||
const byte data[] = { 0, 1, 2, 3 };
|
||||
Common::Span<const byte> span(data, sizeof(data));
|
||||
|
||||
{
|
||||
Common::MemoryReadStream stream(span.toStream(1, 2));
|
||||
byte out;
|
||||
TS_ASSERT_EQUALS(stream.read(&out, 1), 1U);
|
||||
TS_ASSERT_EQUALS(out, 1);
|
||||
TS_ASSERT_EQUALS(stream.read(&out, 1), 1U);
|
||||
TS_ASSERT_EQUALS(out, 2);
|
||||
TS_ASSERT_EQUALS(stream.read(&out, 1), 0U);
|
||||
}
|
||||
|
||||
{
|
||||
Common::MemoryReadStream stream = span.toStream();
|
||||
byte out;
|
||||
TS_ASSERT_EQUALS(stream.read(&out, 1), 1U);
|
||||
TS_ASSERT_EQUALS(out, 0);
|
||||
TS_ASSERT_EQUALS(stream.read(&out, 1), 1U);
|
||||
TS_ASSERT_EQUALS(out, 1);
|
||||
TS_ASSERT_EQUALS(stream.read(&out, 1), 1U);
|
||||
TS_ASSERT_EQUALS(out, 2);
|
||||
TS_ASSERT_EQUALS(stream.read(&out, 1), 1U);
|
||||
TS_ASSERT_EQUALS(out, 3);
|
||||
TS_ASSERT_EQUALS(stream.read(&out, 1), 0U);
|
||||
}
|
||||
}
|
||||
|
||||
void test_span_copying() {
|
||||
const byte data[] = { 0, 1, 2, 3, 4, 5 };
|
||||
Common::Span<const byte> span(data, sizeof(data));
|
||||
|
||||
byte targetData[sizeof(data)] = {};
|
||||
Common::Span<byte> target(targetData, sizeof(targetData));
|
||||
span.copyDataTo(target);
|
||||
for (uint i = 0; i < sizeof(data); ++i) {
|
||||
TS_ASSERT_EQUALS(target[i], i);
|
||||
}
|
||||
|
||||
byte out[sizeof(data)];
|
||||
span.unsafeCopyDataTo(out);
|
||||
for (uint i = 0; i < sizeof(data); ++i) {
|
||||
TS_ASSERT_EQUALS(out[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
void test_span_validation() {
|
||||
byte data[6];
|
||||
Common::Span<byte> span(data, sizeof(data));
|
||||
TS_ASSERT(!span.checkInvalidBounds(0, 0));
|
||||
TS_ASSERT(!span.checkInvalidBounds(0, 6));
|
||||
TS_ASSERT(!span.checkInvalidBounds(2, 4));
|
||||
TS_ASSERT(!span.checkInvalidBounds(4, 2));
|
||||
TS_ASSERT(!span.checkInvalidBounds(6, 0));
|
||||
TS_ASSERT(!span.checkInvalidBounds(2, -2));
|
||||
TS_ASSERT(span.checkInvalidBounds(-2, 2)); // negative index disallowed
|
||||
TS_ASSERT(span.checkInvalidBounds(6, 1)); // combined positive overflow (+7)
|
||||
TS_ASSERT(span.checkInvalidBounds(2, -4)); // negative overflow (-2)
|
||||
TS_ASSERT(span.checkInvalidBounds(0, 10)); // delta positive overflow
|
||||
|
||||
const Common::Span<byte>::difference_type big = (Common::Span<byte>::difference_type)1 << (8 * sizeof(Common::Span<byte>::difference_type) - 1);
|
||||
TS_ASSERT(span.checkInvalidBounds(big, 0));
|
||||
TS_ASSERT(span.checkInvalidBounds(0, big));
|
||||
TS_ASSERT(span.checkInvalidBounds(big, big));
|
||||
}
|
||||
|
||||
void test_span_validation_message() {
|
||||
byte data[1];
|
||||
Common::Span<byte> span(data, sizeof(data));
|
||||
|
||||
Common::String source = span.name();
|
||||
Common::String actual;
|
||||
Common::String expected;
|
||||
|
||||
actual = span.getValidationMessage(12, 34, Common::kValidateRead);
|
||||
expected = Common::String::format("Access violation reading %s: 12 + 34 > 1", source.c_str());
|
||||
TS_ASSERT_EQUALS(actual, expected);
|
||||
|
||||
actual = span.getValidationMessage(23, 45, Common::kValidateWrite);
|
||||
expected = Common::String::format("Access violation writing %s: 23 + 45 > 1", source.c_str());
|
||||
TS_ASSERT_EQUALS(actual, expected);
|
||||
|
||||
actual = span.getValidationMessage(0, -56, Common::kValidateSeek);
|
||||
expected = Common::String::format("Access violation seeking %s: 0 + -56 > 1", source.c_str());
|
||||
TS_ASSERT_EQUALS(actual, expected);
|
||||
}
|
||||
|
||||
void test_span_comparators() {
|
||||
byte data[2] = { 0 };
|
||||
Common::Span<const byte> span0(data, sizeof(data));
|
||||
Common::Span<const byte> span1(data, sizeof(data));
|
||||
Common::Span<const byte> span2(data, sizeof(data) - 1);
|
||||
Common::Span<const byte> span3(data + 1, sizeof(data) - 1);
|
||||
Common::Span<const byte> span4(data + 2, sizeof(data) - 2);
|
||||
|
||||
TS_ASSERT(span0 == span1);
|
||||
TS_ASSERT(span0 != span2);
|
||||
TS_ASSERT(span0 <= span1);
|
||||
TS_ASSERT(span0 <= span3);
|
||||
TS_ASSERT(span0 < span3);
|
||||
TS_ASSERT(span3 < span4);
|
||||
TS_ASSERT(span4 > span3);
|
||||
TS_ASSERT(span3 > span0);
|
||||
TS_ASSERT(span4 >= span4);
|
||||
TS_ASSERT(span0 >= span1);
|
||||
|
||||
TS_ASSERT_EQUALS(span1 - span0, 0);
|
||||
TS_ASSERT_EQUALS(span3 - span0, 1);
|
||||
TS_ASSERT_EQUALS(span4 - span0, 2);
|
||||
TS_ASSERT_EQUALS(span0 - span1, 0);
|
||||
TS_ASSERT_EQUALS(span0 - span3, -1);
|
||||
TS_ASSERT_EQUALS(span0 - span4, -2);
|
||||
}
|
||||
|
||||
void test_named_span() {
|
||||
byte data[6] = { 0, 1, 2, 3, 4, 5 };
|
||||
Common::NamedSpan<byte> span(data, sizeof(data), "foo.data");
|
||||
TS_ASSERT_EQUALS(span.name(), "foo.data");
|
||||
|
||||
Common::String actual;
|
||||
Common::String expected;
|
||||
|
||||
actual = span.getValidationMessage(12, 34, Common::kValidateRead);
|
||||
expected = "Access violation reading foo.data: 12 + 34 > 6 (abs: 12 + 34 > 6)";
|
||||
TS_ASSERT_EQUALS(actual, expected);
|
||||
|
||||
{
|
||||
Common::NamedSpan<byte> subspan = span.subspan(2);
|
||||
|
||||
expected = "Access violation reading foo.data: 23 + 45 > 4 (abs: 25 + 45 > 6)";
|
||||
actual = subspan.getValidationMessage(23, 45, Common::kValidateRead);
|
||||
TS_ASSERT_EQUALS(actual, expected);
|
||||
}
|
||||
|
||||
{
|
||||
Common::NamedSpan<byte> subspan = span.subspan(2, Common::kSpanMaxSize, "new.data");
|
||||
expected = "Access violation reading new.data: 0 + -56 > 4 (abs: 2 + -56 > 6)";
|
||||
actual = subspan.getValidationMessage(0, -56, Common::kValidateRead);
|
||||
TS_ASSERT_EQUALS(actual, expected);
|
||||
}
|
||||
|
||||
{
|
||||
Common::NamedSpan<byte> subspan = span.subspan(2, Common::kSpanMaxSize, "new.data", 0);
|
||||
expected = "Access violation reading new.data: 0 + -56 > 4 (abs: 0 + -56 > 4)";
|
||||
actual = subspan.getValidationMessage(0, -56, Common::kValidateRead);
|
||||
TS_ASSERT_EQUALS(actual, expected);
|
||||
}
|
||||
|
||||
Common::NamedSpan<byte> span2;
|
||||
span = span2 = span;
|
||||
TS_ASSERT_EQUALS(span2, span);
|
||||
TS_ASSERT(span2.name() == span.name());
|
||||
TS_ASSERT(span2.sourceByteOffset() == span.sourceByteOffset());
|
||||
|
||||
Common::Span<byte> superclassInstance;
|
||||
superclassInstance = span;
|
||||
TS_ASSERT_EQUALS(span, superclassInstance);
|
||||
|
||||
Common::Span<byte> subclassInstance(superclassInstance);
|
||||
TS_ASSERT_EQUALS(subclassInstance, superclassInstance);
|
||||
|
||||
const Common::NamedSpan<const byte> constSpan(span);
|
||||
|
||||
{
|
||||
Common::NamedSpan<const byte> subspan = constSpan.subspan(2);
|
||||
|
||||
expected = "Access violation reading foo.data: 23 + 45 > 4 (abs: 25 + 45 > 6)";
|
||||
actual = subspan.getValidationMessage(23, 45, Common::kValidateRead);
|
||||
TS_ASSERT_EQUALS(actual, expected);
|
||||
TS_ASSERT_EQUALS(subspan.sourceByteOffset(), 2U);
|
||||
}
|
||||
|
||||
{
|
||||
Common::NamedSpan<const byte> subspan = constSpan.subspan(2, Common::kSpanMaxSize, "new.data");
|
||||
expected = "Access violation reading new.data: 0 + -56 > 4 (abs: 2 + -56 > 6)";
|
||||
actual = subspan.getValidationMessage(0, -56, Common::kValidateRead);
|
||||
TS_ASSERT_EQUALS(actual, expected);
|
||||
}
|
||||
|
||||
{
|
||||
Common::NamedSpan<const byte> subspan = constSpan.subspan(2, Common::kSpanMaxSize, "new.data", 0);
|
||||
expected = "Access violation reading new.data: 0 + -56 > 4 (abs: 0 + -56 > 4)";
|
||||
actual = subspan.getValidationMessage(0, -56, Common::kValidateRead);
|
||||
TS_ASSERT_EQUALS(actual, expected);
|
||||
}
|
||||
|
||||
{
|
||||
Common::NamedSpan<const byte> subspan = constSpan.subspan(2, Common::kSpanMaxSize, "new.data", 0);
|
||||
subspan.sourceByteOffset() = 2;
|
||||
expected = "Access violation reading new.data: 0 + -56 > 4 (abs: 2 + -56 > 6)";
|
||||
actual = subspan.getValidationMessage(0, -56, Common::kValidateRead);
|
||||
TS_ASSERT_EQUALS(actual, expected);
|
||||
}
|
||||
|
||||
{
|
||||
Common::MemoryReadStream *stream = new Common::MemoryReadStream(data, sizeof(data));
|
||||
Common::File file;
|
||||
file.open(stream, "test.txt");
|
||||
Common::SpanOwner<Common::NamedSpan<const byte> > fileOwner;
|
||||
fileOwner->allocateFromStream(file);
|
||||
TS_ASSERT_EQUALS(fileOwner->size(), (uint)file.size());
|
||||
file.close();
|
||||
TS_ASSERT(fileOwner->name() == "test.txt");
|
||||
for (uint i = 0; i < fileOwner->size(); ++i) {
|
||||
TS_ASSERT_EQUALS(fileOwner->getInt8At(i), data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
83
test/common/stack.h
Normal file
83
test/common/stack.h
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/stack.h"
|
||||
|
||||
class StackTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_empty_clear() {
|
||||
Common::Stack<int> stack;
|
||||
TS_ASSERT(stack.empty());
|
||||
|
||||
stack.push(1);
|
||||
stack.push(2);
|
||||
TS_ASSERT(!stack.empty());
|
||||
|
||||
stack.clear();
|
||||
|
||||
TS_ASSERT(stack.empty());
|
||||
}
|
||||
|
||||
void test_size() {
|
||||
typedef Common::Stack<int> Stack;
|
||||
|
||||
Stack stack;
|
||||
TS_ASSERT_EQUALS(stack.size(), (Stack::size_type)0);
|
||||
|
||||
stack.push(5);
|
||||
TS_ASSERT_EQUALS(stack.size(), (Stack::size_type)1);
|
||||
|
||||
stack.push(9);
|
||||
stack.push(0);
|
||||
TS_ASSERT_EQUALS(stack.size(), (Stack::size_type)3);
|
||||
|
||||
stack.pop();
|
||||
TS_ASSERT_EQUALS(stack.size(), (Stack::size_type)2);
|
||||
}
|
||||
|
||||
void test_top_pop() {
|
||||
Common::Stack<int> stack;
|
||||
|
||||
stack.push( 42);
|
||||
stack.push(-23);
|
||||
|
||||
TS_ASSERT_EQUALS(stack[0], 42);
|
||||
TS_ASSERT_EQUALS(stack.top(), -23);
|
||||
|
||||
stack[0] = -23;
|
||||
stack.top() = 42;
|
||||
TS_ASSERT_EQUALS(stack[0], -23);
|
||||
TS_ASSERT_EQUALS(stack.top(), 42);
|
||||
|
||||
stack.pop();
|
||||
TS_ASSERT_EQUALS(stack[0], -23);
|
||||
}
|
||||
|
||||
void test_assign() {
|
||||
Common::Stack<int> q1, q2;
|
||||
|
||||
for (int i = 0; i <= 4; ++i) {
|
||||
q1.push(4-i);
|
||||
q2.push(i);
|
||||
}
|
||||
|
||||
Common::Stack<int> q3(q1);
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
TS_ASSERT_EQUALS(q3.top(), i);
|
||||
q3.pop();
|
||||
}
|
||||
|
||||
TS_ASSERT(q3.empty());
|
||||
|
||||
q3 = q2;
|
||||
|
||||
for (int i = 4; i >= 0; --i) {
|
||||
TS_ASSERT_EQUALS(q3.top(), i);
|
||||
q3.pop();
|
||||
}
|
||||
|
||||
TS_ASSERT(q3.empty());
|
||||
TS_ASSERT(!q1.empty());
|
||||
TS_ASSERT(!q2.empty());
|
||||
}
|
||||
};
|
||||
23
test/common/str-helper.h
Normal file
23
test/common/str-helper.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef TEST_COMMON_HELPER_H
|
||||
#define TEST_COMMON_HELPER_H
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
CXXTEST_TEMPLATE_INSTANTIATION
|
||||
class ValueTraits<const Common::String &>
|
||||
{
|
||||
ValueTraits &operator=( const ValueTraits & );
|
||||
Common::String _str;
|
||||
|
||||
public:
|
||||
ValueTraits( const Common::String &value ) : _str( value ) {}
|
||||
ValueTraits( const ValueTraits &other ) : _str( other._str ) {}
|
||||
const char *asString( void ) const { return _str.c_str(); }
|
||||
};
|
||||
CXXTEST_COPY_CONST_TRAITS( Common::String &);
|
||||
CXXTEST_COPY_TRAITS( Common::String, const Common::String &);
|
||||
}
|
||||
|
||||
#endif
|
||||
774
test/common/str.h
Normal file
774
test/common/str.h
Normal file
@@ -0,0 +1,774 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/ustr.h"
|
||||
|
||||
#include "test/common/str-helper.h"
|
||||
|
||||
class StringTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_constructors() {
|
||||
Common::String str("test-string");
|
||||
TS_ASSERT_EQUALS(str, "test-string");
|
||||
str = Common::String(str.c_str()+5, 3);
|
||||
TS_ASSERT_EQUALS(str, "str");
|
||||
str = "test-string";
|
||||
TS_ASSERT_EQUALS(str, "test-string");
|
||||
str = Common::String(str.c_str()+5, str.c_str()+8);
|
||||
TS_ASSERT_EQUALS(str, "str");
|
||||
str = Common::String(5, 'a');
|
||||
TS_ASSERT_EQUALS(str, "aaaaa");
|
||||
}
|
||||
|
||||
void test_trim() {
|
||||
Common::String str(" This is a s tring with spaces ");
|
||||
Common::String str2 = str;
|
||||
str.trim();
|
||||
TS_ASSERT_EQUALS(str, "This is a s tring with spaces");
|
||||
TS_ASSERT_EQUALS(str2, " This is a s tring with spaces ");
|
||||
}
|
||||
|
||||
void test_chop() {
|
||||
Common::String str("test-string");
|
||||
Common::String str2 = str;
|
||||
str.chop();
|
||||
TS_ASSERT_EQUALS(str, "test-strin");
|
||||
TS_ASSERT_EQUALS(str2, "test-string");
|
||||
|
||||
str = "test-string";
|
||||
str.chop(2);
|
||||
TS_ASSERT_EQUALS(str, "test-stri");
|
||||
|
||||
str = "test-string";
|
||||
str.chop(10);
|
||||
TS_ASSERT_EQUALS(str, "t");
|
||||
|
||||
str = "test-string";
|
||||
str.chop(11);
|
||||
TS_ASSERT(str.empty());
|
||||
|
||||
str = "test-string";
|
||||
str.chop(200);
|
||||
TS_ASSERT(str.empty());
|
||||
}
|
||||
|
||||
void test_empty_clear() {
|
||||
Common::String str("test");
|
||||
TS_ASSERT(!str.empty());
|
||||
str.clear();
|
||||
TS_ASSERT(str.empty());
|
||||
}
|
||||
|
||||
void test_lastChar() {
|
||||
Common::String str;
|
||||
TS_ASSERT_EQUALS(str.lastChar(), '\0');
|
||||
str = "test";
|
||||
TS_ASSERT_EQUALS(str.lastChar(), 't');
|
||||
Common::String str2("bar");
|
||||
TS_ASSERT_EQUALS(str2.lastChar(), 'r');
|
||||
}
|
||||
|
||||
void test_firstChar() {
|
||||
Common::String str;
|
||||
TS_ASSERT_EQUALS(str.firstChar(), '\0');
|
||||
str = "first_test";
|
||||
TS_ASSERT_EQUALS(str.firstChar(), 'f');
|
||||
Common::String str2("bar");
|
||||
TS_ASSERT_EQUALS(str2.firstChar(), 'b');
|
||||
}
|
||||
|
||||
void test_assign1() {
|
||||
Common::String str("foobar");
|
||||
str.assign("bar");
|
||||
TS_ASSERT_EQUALS(str, "bar");
|
||||
}
|
||||
|
||||
void test_assign2() {
|
||||
Common::String str("foobar");
|
||||
str.assign("abcdef", 3);
|
||||
TS_ASSERT_EQUALS(str, "abc");
|
||||
}
|
||||
|
||||
void test_assign3() {
|
||||
Common::String str("foobar");
|
||||
str.assign(3, '0');
|
||||
TS_ASSERT_EQUALS(str, "000");
|
||||
}
|
||||
|
||||
void test_concat1() {
|
||||
Common::String str("foo");
|
||||
Common::String str2("bar");
|
||||
str += str2;
|
||||
TS_ASSERT_EQUALS(str, "foobar");
|
||||
TS_ASSERT_EQUALS(str2, "bar");
|
||||
}
|
||||
|
||||
void test_concat2() {
|
||||
Common::String str("foo");
|
||||
str += "bar";
|
||||
TS_ASSERT_EQUALS(str, "foobar");
|
||||
}
|
||||
|
||||
void test_concat3() {
|
||||
Common::String str("foo");
|
||||
str += 'X';
|
||||
TS_ASSERT_EQUALS(str, "fooX");
|
||||
}
|
||||
|
||||
void test_concat4() {
|
||||
Common::String str("foo");
|
||||
str.append(2, '+');
|
||||
TS_ASSERT_EQUALS(str, "foo++");
|
||||
}
|
||||
|
||||
void test_refCount() {
|
||||
// using internal storage
|
||||
Common::String foo1("foo");
|
||||
Common::String foo2(foo1);
|
||||
Common::String foo3(foo2);
|
||||
foo3 += 'X';
|
||||
TS_ASSERT_EQUALS(foo1, "foo");
|
||||
TS_ASSERT_EQUALS(foo2, "foo");
|
||||
TS_ASSERT_EQUALS(foo3, "foo""X");
|
||||
foo2 = 'x';
|
||||
TS_ASSERT_EQUALS(foo1, "foo");
|
||||
TS_ASSERT_EQUALS(foo2, "x");
|
||||
TS_ASSERT_EQUALS(foo3, "foo""X");
|
||||
}
|
||||
|
||||
void test_refCount2() {
|
||||
// using external storage
|
||||
Common::String foo1("fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
|
||||
Common::String foo2(foo1);
|
||||
Common::String foo3(foo2);
|
||||
foo3 += 'X';
|
||||
TS_ASSERT_EQUALS(foo1, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
|
||||
TS_ASSERT_EQUALS(foo2, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
|
||||
TS_ASSERT_EQUALS(foo3, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd""X");
|
||||
foo2 = 'x';
|
||||
TS_ASSERT_EQUALS(foo1, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
|
||||
TS_ASSERT_EQUALS(foo2, "x");
|
||||
TS_ASSERT_EQUALS(foo3, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd""X");
|
||||
}
|
||||
|
||||
void test_refCount3() {
|
||||
Common::String foo1("0123456789abcdefghijk");
|
||||
Common::String foo2(foo1);
|
||||
Common::String foo3(foo2);
|
||||
foo3 += "0123456789abcdefghijk";
|
||||
TS_ASSERT_EQUALS(foo1, foo2);
|
||||
TS_ASSERT_EQUALS(foo2, "0123456789abcdefghijk");
|
||||
TS_ASSERT_EQUALS(foo3, "0123456789abcdefghijk""0123456789abcdefghijk");
|
||||
foo2 = 'x';
|
||||
TS_ASSERT_EQUALS(foo1, "0123456789abcdefghijk");
|
||||
TS_ASSERT_EQUALS(foo2, "x");
|
||||
TS_ASSERT_EQUALS(foo3, "0123456789abcdefghijk""0123456789abcdefghijk");
|
||||
}
|
||||
|
||||
void test_refCount4() {
|
||||
Common::String foo1("fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
|
||||
Common::String foo2(foo1);
|
||||
Common::String foo3(foo2);
|
||||
foo3 += "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd";
|
||||
TS_ASSERT_EQUALS(foo1, foo2);
|
||||
TS_ASSERT_EQUALS(foo2, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
|
||||
TS_ASSERT_EQUALS(foo3, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd""fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
|
||||
foo2 = 'x';
|
||||
TS_ASSERT_EQUALS(foo1, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
|
||||
TS_ASSERT_EQUALS(foo2, "x");
|
||||
TS_ASSERT_EQUALS(foo3, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd""fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
|
||||
}
|
||||
|
||||
void test_refCount5() {
|
||||
// using external storage
|
||||
Common::String foo1("HelloHelloHelloHelloAndHi");
|
||||
Common::String foo2(foo1);
|
||||
|
||||
for (Common::String::iterator i = foo2.begin(); i != foo2.end(); ++i)
|
||||
*i = 'h';
|
||||
|
||||
TS_ASSERT_EQUALS(foo1, "HelloHelloHelloHelloAndHi");
|
||||
TS_ASSERT_EQUALS(foo2, "hhhhhhhhhhhhhhhhhhhhhhhhh");
|
||||
}
|
||||
|
||||
void test_refCount6() {
|
||||
// using internal storage
|
||||
Common::String foo1("Hello");
|
||||
Common::String foo2(foo1);
|
||||
|
||||
for (Common::String::iterator i = foo2.begin(); i != foo2.end(); ++i)
|
||||
*i = 'h';
|
||||
|
||||
TS_ASSERT_EQUALS(foo1, "Hello");
|
||||
TS_ASSERT_EQUALS(foo2, "hhhhh");
|
||||
}
|
||||
|
||||
void test_self_asignment() {
|
||||
Common::String foo1("12345678901234567890123456789012");
|
||||
foo1 = foo1.c_str() + 2;
|
||||
TS_ASSERT_EQUALS(foo1, "345678901234567890123456789012");
|
||||
|
||||
Common::String foo2("123456789012");
|
||||
foo2 = foo2.c_str() + 2;
|
||||
TS_ASSERT_EQUALS(foo2, "3456789012");
|
||||
|
||||
// "foo3" and "foo4" will be using allocated storage from construction on.
|
||||
Common::String foo3("12345678901234567890123456789012");
|
||||
foo3 += foo3.c_str();
|
||||
TS_ASSERT_EQUALS(foo3, "12345678901234567890123456789012""12345678901234567890123456789012");
|
||||
|
||||
Common::String foo4("12345678901234567890123456789012");
|
||||
foo4 += foo4;
|
||||
TS_ASSERT_EQUALS(foo4, "12345678901234567890123456789012""12345678901234567890123456789012");
|
||||
|
||||
// Based on our current Common::String implementation "foo5" and "foo6" will first use the internal storage,
|
||||
// and on "operator +=" they will change to allocated memory.
|
||||
Common::String foo5("123456789012");
|
||||
foo5 += foo5.c_str();
|
||||
TS_ASSERT_EQUALS(foo5, "123456789012""123456789012");
|
||||
|
||||
Common::String foo6("123456789012");
|
||||
foo6 += foo6;
|
||||
TS_ASSERT_EQUALS(foo6, "123456789012""123456789012");
|
||||
|
||||
// "foo7" and "foo8" will purely operate on internal storage.
|
||||
Common::String foo7("1234");
|
||||
foo7 += foo7.c_str();
|
||||
TS_ASSERT_EQUALS(foo7, "1234""1234");
|
||||
|
||||
Common::String foo8("1234");
|
||||
foo8 += foo8;
|
||||
TS_ASSERT_EQUALS(foo8, "1234""1234");
|
||||
|
||||
Common::String foo9("123456789012345678901234567889012");
|
||||
foo9 = foo9.c_str();
|
||||
TS_ASSERT_EQUALS(foo9, "123456789012345678901234567889012");
|
||||
foo9 = foo9;
|
||||
TS_ASSERT_EQUALS(foo9, "123456789012345678901234567889012");
|
||||
|
||||
Common::String foo10("1234");
|
||||
foo10 = foo10.c_str();
|
||||
TS_ASSERT_EQUALS(foo10, "1234");
|
||||
foo10 = foo10;
|
||||
TS_ASSERT_EQUALS(foo10, "1234");
|
||||
}
|
||||
|
||||
void test_hasPrefix() {
|
||||
Common::String str("this/is/a/test, haha");
|
||||
TS_ASSERT_EQUALS(str.hasPrefix(""), true);
|
||||
TS_ASSERT_EQUALS(str.hasPrefix("this"), true);
|
||||
TS_ASSERT_EQUALS(str.hasPrefix("thit"), false);
|
||||
TS_ASSERT_EQUALS(str.hasPrefix("foo"), false);
|
||||
}
|
||||
|
||||
void test_hasSuffix() {
|
||||
Common::String str("this/is/a/test, haha");
|
||||
TS_ASSERT_EQUALS(str.hasSuffix(""), true);
|
||||
TS_ASSERT_EQUALS(str.hasSuffix("haha"), true);
|
||||
TS_ASSERT_EQUALS(str.hasSuffix("hahb"), false);
|
||||
TS_ASSERT_EQUALS(str.hasSuffix("hahah"), false);
|
||||
}
|
||||
|
||||
void test_contains() {
|
||||
Common::String str("this/is/a/test, haha");
|
||||
TS_ASSERT_EQUALS(str.contains(""), true);
|
||||
TS_ASSERT_EQUALS(str.contains("haha"), true);
|
||||
TS_ASSERT_EQUALS(str.contains("hahb"), false);
|
||||
TS_ASSERT_EQUALS(str.contains("test"), true);
|
||||
|
||||
TS_ASSERT_EQUALS(str.contains('/'), true);
|
||||
TS_ASSERT_EQUALS(str.contains('x'), false);
|
||||
}
|
||||
|
||||
void test_toLowercase() {
|
||||
Common::String str("Test it, NOW! 42");
|
||||
Common::String str2 = str;
|
||||
str.toLowercase();
|
||||
TS_ASSERT_EQUALS(str, "test it, now! 42");
|
||||
TS_ASSERT_EQUALS(str2, "Test it, NOW! 42");
|
||||
}
|
||||
|
||||
void test_toUppercase() {
|
||||
Common::String str("Test it, NOW! 42");
|
||||
Common::String str2 = str;
|
||||
str.toUppercase();
|
||||
TS_ASSERT_EQUALS(str, "TEST IT, NOW! 42");
|
||||
TS_ASSERT_EQUALS(str2, "Test it, NOW! 42");
|
||||
}
|
||||
|
||||
void test_deleteChar() {
|
||||
Common::String str("01234567890123456789012345678901");
|
||||
str.deleteChar(10);
|
||||
TS_ASSERT_EQUALS(str, "0123456789123456789012345678901");
|
||||
str.deleteChar(10);
|
||||
TS_ASSERT_EQUALS(str, "012345678923456789012345678901");
|
||||
}
|
||||
|
||||
void test_erase() {
|
||||
Common::String str("01234567890123456789012345678901");
|
||||
str.erase(18);
|
||||
TS_ASSERT_EQUALS(str, "012345678901234567");
|
||||
str.erase(7, 5);
|
||||
TS_ASSERT_EQUALS(str, "0123456234567");
|
||||
}
|
||||
|
||||
void test_sharing() {
|
||||
Common::String str("01234567890123456789012345678901");
|
||||
Common::String str2(str);
|
||||
TS_ASSERT_EQUALS(str2, "01234567890123456789012345678901");
|
||||
str.deleteLastChar();
|
||||
TS_ASSERT_EQUALS(str, "0123456789012345678901234567890");
|
||||
TS_ASSERT_EQUALS(str2, "01234567890123456789012345678901");
|
||||
}
|
||||
|
||||
void test_lastPathComponent() {
|
||||
TS_ASSERT_EQUALS(Common::lastPathComponent("/", '/'), "");
|
||||
TS_ASSERT_EQUALS(Common::lastPathComponent("/foo/bar", '/'), "bar");
|
||||
TS_ASSERT_EQUALS(Common::lastPathComponent("/foo//bar/", '/'), "bar");
|
||||
TS_ASSERT_EQUALS(Common::lastPathComponent("/foo/./bar", '/'), "bar");
|
||||
TS_ASSERT_EQUALS(Common::lastPathComponent("/foo//./bar//", '/'), "bar");
|
||||
TS_ASSERT_EQUALS(Common::lastPathComponent("/foo//.bar//", '/'), ".bar");
|
||||
|
||||
TS_ASSERT_EQUALS(Common::lastPathComponent("", '/'), "");
|
||||
TS_ASSERT_EQUALS(Common::lastPathComponent("foo/bar", '/'), "bar");
|
||||
TS_ASSERT_EQUALS(Common::lastPathComponent("foo//bar/", '/'), "bar");
|
||||
TS_ASSERT_EQUALS(Common::lastPathComponent("foo/./bar", '/'), "bar");
|
||||
TS_ASSERT_EQUALS(Common::lastPathComponent("foo//./bar//", '/'), "bar");
|
||||
TS_ASSERT_EQUALS(Common::lastPathComponent("foo//.bar//", '/'), ".bar");
|
||||
|
||||
TS_ASSERT_EQUALS(Common::lastPathComponent("foo", '/'), "foo");
|
||||
}
|
||||
|
||||
void test_normalizePath() {
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("/", '/'), "/");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("/foo/bar", '/'), "/foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("/foo//bar/", '/'), "/foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("/foo/./bar", '/'), "/foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("/foo//./bar//", '/'), "/foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("/foo//.bar//", '/'), "/foo/.bar");
|
||||
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("", '/'), "");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("foo/bar", '/'), "foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("foo//bar/", '/'), "foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("foo/./bar", '/'), "foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("foo//./bar//", '/'), "foo/bar");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("foo//.bar//", '/'), "foo/.bar");
|
||||
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("..", '/'), "..");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("../", '/'), "..");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("/..", '/'), "/..");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("../bar", '/'), "../bar");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("foo//../", '/'), "");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("foo/../bar", '/'), "bar");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("foo//../bar//", '/'), "bar");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("foo//..bar//", '/'), "foo/..bar");
|
||||
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("foo/../../bar//", '/'), "../bar");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("../foo/../bar", '/'), "../bar");
|
||||
TS_ASSERT_EQUALS(Common::normalizePath("../../foo/bar/", '/'), "../../foo/bar");
|
||||
}
|
||||
|
||||
void test_matchString() {
|
||||
TS_ASSERT(Common::matchString("", "*"));
|
||||
TS_ASSERT(Common::matchString("a", "*"));
|
||||
TS_ASSERT(Common::matchString("monkey.s01", "*"));
|
||||
|
||||
TS_ASSERT(!Common::matchString("", "?"));
|
||||
TS_ASSERT(Common::matchString("a", "?"));
|
||||
TS_ASSERT(!Common::matchString("monkey.s01", "?"));
|
||||
|
||||
TS_ASSERT(Common::matchString("monkey.s01", "monkey.s??"));
|
||||
TS_ASSERT(Common::matchString("monkey.s99", "monkey.s??"));
|
||||
TS_ASSERT(!Common::matchString("monkey.s101", "monkey.s??"));
|
||||
|
||||
TS_ASSERT(Common::matchString("monkey.s01", "monkey.s?1"));
|
||||
TS_ASSERT(!Common::matchString("monkey.s99", "monkey.s?1"));
|
||||
TS_ASSERT(!Common::matchString("monkey.s101", "monkey.s?1"));
|
||||
|
||||
TS_ASSERT(Common::matchString("monkey.s01", "monkey.s*"));
|
||||
TS_ASSERT(Common::matchString("monkey.s99", "monkey.s*"));
|
||||
TS_ASSERT(Common::matchString("monkey.s101", "monkey.s*"));
|
||||
|
||||
TS_ASSERT(Common::matchString("monkey.s01", "monkey.s*1"));
|
||||
TS_ASSERT(!Common::matchString("monkey.s99", "monkey.s*1"));
|
||||
TS_ASSERT(Common::matchString("monkey.s101", "monkey.s*1"));
|
||||
|
||||
TS_ASSERT(Common::matchString("monkey.s01", "monkey.s##"));
|
||||
TS_ASSERT(!Common::matchString("monkey.s01", "monkey.###"));
|
||||
|
||||
TS_ASSERT(Common::matchString("monkey.s0#", "monkey.s0\\#"));
|
||||
TS_ASSERT(!Common::matchString("monkey.s0#", "monkey.s0#"));
|
||||
TS_ASSERT(!Common::matchString("monkey.s01", "monkey.s0\\#"));
|
||||
|
||||
TS_ASSERT(!Common::String("").matchString("*_"));
|
||||
TS_ASSERT(Common::String("a").matchString("a***"));
|
||||
}
|
||||
|
||||
void test_string_printf() {
|
||||
TS_ASSERT_EQUALS( Common::String::format(" "), " " );
|
||||
TS_ASSERT_EQUALS( Common::String::format("%s", "test"), "test" );
|
||||
TS_ASSERT_EQUALS( Common::String::format("%s.s%.02d", "monkey", 1), "monkey.s01" );
|
||||
TS_ASSERT_EQUALS( Common::String::format("Some %s to make this string longer than the default built-in %s %d", "text", "capacity", 123456), "Some text to make this string longer than the default built-in capacity 123456" );
|
||||
|
||||
Common::String s = Common::String::format("%s%X", "test", 1234);
|
||||
TS_ASSERT_EQUALS(s, "test4D2");
|
||||
TS_ASSERT_EQUALS(s.size(), 7U);
|
||||
}
|
||||
|
||||
void test_ustring_printf() {
|
||||
//Ideally should be the same as above (make String template?)
|
||||
TS_ASSERT_EQUALS( Common::U32String::format(" ").encode(), " " );
|
||||
TS_ASSERT_EQUALS( Common::U32String::format("%s", "test").encode(), "test" );
|
||||
TS_ASSERT_EQUALS( Common::U32String::format("%s%c%s", "Press ", 'X', " to win").encode(), "Press X to win" );
|
||||
TS_ASSERT_EQUALS( Common::U32String::format("Some %s to make this string longer than the default built-in %s %d", "text", "capacity", 123456).encode(), "Some text to make this string longer than the default built-in capacity 123456" );
|
||||
|
||||
TS_ASSERT_EQUALS( Common::U32String::format("%u", 0).encode(), "0" );
|
||||
TS_ASSERT_EQUALS( Common::U32String::format("%u", 1234).encode(), "1234" );
|
||||
|
||||
TS_ASSERT_EQUALS( Common::U32String::format("%d", 0).encode(), "0" );
|
||||
TS_ASSERT_EQUALS( Common::U32String::format("%d", 1234).encode(), "1234" );
|
||||
TS_ASSERT_EQUALS( Common::U32String::format("%d", -1234).encode(), "-1234" );
|
||||
|
||||
TS_ASSERT_EQUALS( Common::U32String::format("%u %%", 100).encode(), "100 %" );
|
||||
}
|
||||
|
||||
void test_strlcpy() {
|
||||
static const char * const testString = "1234567890";
|
||||
|
||||
char test1[4];
|
||||
TS_ASSERT_EQUALS(Common::strlcpy(test1, testString, 4), strlen(testString));
|
||||
TS_ASSERT_EQUALS(strcmp(test1, "123"), 0);
|
||||
|
||||
char test2[12];
|
||||
test2[11] = 'X';
|
||||
TS_ASSERT_EQUALS(Common::strlcpy(test2, testString, 11), strlen(testString));
|
||||
TS_ASSERT_EQUALS(strcmp(test2, testString), 0);
|
||||
TS_ASSERT_EQUALS(test2[11], 'X');
|
||||
|
||||
char test3[1] = { 'X' };
|
||||
TS_ASSERT_EQUALS(Common::strlcpy(test3, testString, 0), strlen(testString));
|
||||
TS_ASSERT_EQUALS(test3[0], 'X');
|
||||
|
||||
char test4[12];
|
||||
TS_ASSERT_EQUALS(Common::strlcpy(test4, testString, 12), strlen(testString));
|
||||
TS_ASSERT_EQUALS(strcmp(test4, testString), 0);
|
||||
}
|
||||
|
||||
void test_strlcat() {
|
||||
static const char * const initialString = "123";
|
||||
static const char * const appendString = "4567890";
|
||||
static const char * const resultString = "1234567890";
|
||||
|
||||
char test1[4];
|
||||
TS_ASSERT_EQUALS(Common::strlcpy(test1, initialString, 4), strlen(initialString));
|
||||
TS_ASSERT_EQUALS(strcmp(test1, initialString), 0);
|
||||
TS_ASSERT_EQUALS(Common::strlcat(test1, appendString, 4), strlen(resultString));
|
||||
TS_ASSERT_EQUALS(strcmp(test1, initialString), 0);
|
||||
|
||||
char test2[12];
|
||||
test2[11] = 'X';
|
||||
TS_ASSERT_EQUALS(Common::strlcpy(test2, initialString, 11), strlen(initialString));
|
||||
TS_ASSERT_EQUALS(strcmp(test2, initialString), 0);
|
||||
TS_ASSERT_EQUALS(Common::strlcat(test2, appendString, 11), strlen(resultString));
|
||||
TS_ASSERT_EQUALS(strcmp(test2, resultString), 0);
|
||||
TS_ASSERT_EQUALS(test2[11], 'X');
|
||||
|
||||
char test3[1];
|
||||
test3[0] = 'X';
|
||||
TS_ASSERT_EQUALS(Common::strlcat(test3, appendString, 0), strlen(appendString));
|
||||
TS_ASSERT_EQUALS(test3[0], 'X');
|
||||
|
||||
char test4[11];
|
||||
TS_ASSERT_EQUALS(Common::strlcpy(test4, initialString, 11), strlen(initialString));
|
||||
TS_ASSERT_EQUALS(strcmp(test4, initialString), 0);
|
||||
TS_ASSERT_EQUALS(Common::strlcat(test4, appendString, 11), strlen(resultString));
|
||||
TS_ASSERT_EQUALS(strcmp(test4, resultString), 0);
|
||||
}
|
||||
|
||||
void test_strnlen() {
|
||||
static const char * const testString = "123";
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testString, 0), 0u);
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testString, 1), 1u);
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testString, 2), 2u);
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testString, 3), 3u);
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testString, 4), 3u);
|
||||
|
||||
const char testArray[4] = { '1', '2', '3', '4' };
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testArray, 0), 0u);
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testArray, 1), 1u);
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testArray, 2), 2u);
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testArray, 3), 3u);
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testArray, 4), 4u);
|
||||
|
||||
const char testArray2[4] = { '1', '\0', '3', '4' };
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testArray2, 0), 0u);
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testArray2, 1), 1u);
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testArray2, 2), 1u);
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testArray2, 3), 1u);
|
||||
TS_ASSERT_EQUALS(Common::strnlen(testArray2, 4), 1u);
|
||||
}
|
||||
|
||||
void test_scumm_stricmp() {
|
||||
TS_ASSERT_EQUALS(scumm_stricmp("abCd", "abCd"), 0);
|
||||
TS_ASSERT_EQUALS(scumm_stricmp("abCd", "ABCd"), 0);
|
||||
TS_ASSERT_LESS_THAN(scumm_stricmp("abCd", "ABCe"), 0);
|
||||
TS_ASSERT_LESS_THAN(scumm_stricmp("abCd", "ABCde"), 0);
|
||||
}
|
||||
|
||||
void test_scumm_strnicmp() {
|
||||
TS_ASSERT_EQUALS(scumm_strnicmp("abCd", "abCd", 3), 0);
|
||||
TS_ASSERT_EQUALS(scumm_strnicmp("abCd", "ABCd", 4), 0);
|
||||
TS_ASSERT_EQUALS(scumm_strnicmp("abCd", "ABCd", 5), 0);
|
||||
TS_ASSERT_EQUALS(scumm_strnicmp("abCd", "ABCe", 3), 0);
|
||||
TS_ASSERT_LESS_THAN(scumm_strnicmp("abCd", "ABCe", 4), 0);
|
||||
TS_ASSERT_EQUALS(scumm_strnicmp("abCd", "ABCde", 4), 0);
|
||||
TS_ASSERT_LESS_THAN(scumm_strnicmp("abCd", "ABCde", 5), 0);
|
||||
}
|
||||
|
||||
void test_wordWrap() {
|
||||
Common::String testString("123456");
|
||||
testString.wordWrap(10);
|
||||
TS_ASSERT(testString == "123456");
|
||||
testString.wordWrap(2);
|
||||
TS_ASSERT(testString == "12\n34\n56");
|
||||
testString = "1234 5678";
|
||||
testString.wordWrap(4);
|
||||
TS_ASSERT(testString == "1234\n5678");
|
||||
testString = "12 3 45";
|
||||
testString.wordWrap(4);
|
||||
TS_ASSERT(testString == "12 3\n45");
|
||||
testString = "\n1\n23 45\n\n";
|
||||
testString.wordWrap(3);
|
||||
TS_ASSERT(testString == "\n1\n23\n45\n\n");
|
||||
testString = "123 ";
|
||||
testString.wordWrap(4);
|
||||
TS_ASSERT(testString == "123 ");
|
||||
testString.wordWrap(3);
|
||||
TS_ASSERT(testString == "123\n");
|
||||
}
|
||||
|
||||
void test_replace() {
|
||||
// Tests created with the results of the STL std::string class
|
||||
|
||||
// --------------------------
|
||||
// Tests without displacement
|
||||
// --------------------------
|
||||
Common::String testString = Common::String("This is the original string.");
|
||||
|
||||
// Positions and sizes as parameters, string as replacement
|
||||
testString.replace(12, 8, Common::String("newnewne"));
|
||||
TS_ASSERT_EQUALS(testString, Common::String("This is the newnewne string."));
|
||||
|
||||
// The same but with char*
|
||||
testString.replace(0, 4, "That");
|
||||
TS_ASSERT_EQUALS(testString, Common::String("That is the newnewne string."));
|
||||
|
||||
// Using iterators (also a terribly useless program as a test).
|
||||
testString.replace(testString.begin(), testString.end(), "That is the supernew string.");
|
||||
TS_ASSERT_EQUALS(testString, Common::String("That is the supernew string."));
|
||||
|
||||
// With sub strings of character arrays.
|
||||
testString.replace(21, 6, "That phrase is new.", 5, 6);
|
||||
TS_ASSERT_EQUALS(testString, Common::String("That is the supernew phrase."));
|
||||
|
||||
// Now with substrings.
|
||||
testString.replace(12, 2, Common::String("That hy is new."), 5, 2);
|
||||
TS_ASSERT_EQUALS(testString, Common::String("That is the hypernew phrase."));
|
||||
|
||||
// --------------------------
|
||||
// Tests with displacement
|
||||
// --------------------------
|
||||
testString = Common::String("Hello World");
|
||||
|
||||
// Positions and sizes as parameters, string as replacement
|
||||
testString.replace(6, 5, Common::String("friends"));
|
||||
TS_ASSERT_EQUALS(testString, Common::String("Hello friends"));
|
||||
|
||||
// The same but with char*
|
||||
testString.replace(0, 5, "Good");
|
||||
TS_ASSERT_EQUALS(testString, Common::String("Good friends"));
|
||||
|
||||
// Using iterators (also a terribly useless program as a test)
|
||||
testString.replace(testString.begin() + 4, testString.begin() + 5, " coffee ");
|
||||
TS_ASSERT_EQUALS(testString, Common::String("Good coffee friends"));
|
||||
|
||||
// With sub strings of character arrays
|
||||
testString.replace(4, 0, "Lorem ipsum expresso dolor sit amet", 11, 9);
|
||||
TS_ASSERT_EQUALS(testString, Common::String("Good expresso coffee friends"));
|
||||
|
||||
// Now with substrings
|
||||
testString.replace(5, 9, Common::String("Displaced ristretto string"), 10, 10);
|
||||
TS_ASSERT_EQUALS(testString, Common::String("Good ristretto coffee friends"));
|
||||
|
||||
// -----------------------
|
||||
// Deep copy compliance
|
||||
// -----------------------
|
||||
|
||||
// Makes a deep copy without changing the length of the original
|
||||
Common::String s1 = "TestTestTestTestTestTestTestTestTestTestTest";
|
||||
Common::String s2(s1);
|
||||
TS_ASSERT_EQUALS(s1, "TestTestTestTestTestTestTestTestTestTestTest");
|
||||
TS_ASSERT_EQUALS(s2, "TestTestTestTestTestTestTestTestTestTestTest");
|
||||
s1.replace(0, 4, "TEST");
|
||||
TS_ASSERT_EQUALS(s1, "TESTTestTestTestTestTestTestTestTestTestTest");
|
||||
TS_ASSERT_EQUALS(s2, "TestTestTestTestTestTestTestTestTestTestTest");
|
||||
|
||||
// Makes a deep copy when we shorten the string
|
||||
Common::String s3 = "TestTestTestTestTestTestTestTestTestTestTest";
|
||||
Common::String s4(s3);
|
||||
s3.replace(0, 32, "");
|
||||
TS_ASSERT_EQUALS(s3, "TestTestTest");
|
||||
TS_ASSERT_EQUALS(s4, "TestTestTestTestTestTestTestTestTestTestTest");
|
||||
}
|
||||
|
||||
void test_ustring_replace() {
|
||||
// These tests are inspired from the above string tests
|
||||
|
||||
// --------------------------
|
||||
// Tests without displacement
|
||||
// --------------------------
|
||||
Common::U32String testString = Common::U32String("This is the original string.");
|
||||
|
||||
// Positions and sizes as parameters, U32String as replacement
|
||||
testString.replace(12, 8, Common::U32String("newnewne"));
|
||||
TS_ASSERT_EQUALS(testString, Common::U32String("This is the newnewne string."));
|
||||
|
||||
// Using iterators (also a terribly useless program as a test).
|
||||
testString.replace(testString.begin(), testString.end(), Common::U32String("That is the supernew string."));
|
||||
TS_ASSERT_EQUALS(testString, Common::U32String("That is the supernew string."));
|
||||
|
||||
// With substrings.
|
||||
testString.replace(12, 2, Common::U32String("That hy is new."), 5, 2);
|
||||
TS_ASSERT_EQUALS(testString, Common::U32String("That is the hypernew string."));
|
||||
|
||||
// --------------------------
|
||||
// Tests with displacement
|
||||
// --------------------------
|
||||
testString = Common::U32String("Hello World");
|
||||
|
||||
// Positions and sizes as parameters, string as replacement
|
||||
testString.replace(6, 5, Common::U32String("friends"));
|
||||
TS_ASSERT_EQUALS(testString, Common::U32String("Hello friends"));
|
||||
|
||||
// Using iterators (also a terribly useless program as a test)
|
||||
testString.replace(testString.begin() + 5, testString.begin() + 6, Common::U32String(" good "));
|
||||
TS_ASSERT_EQUALS(testString, Common::U32String("Hello good friends"));
|
||||
|
||||
// With substrings
|
||||
testString.replace(6, 0, Common::U32String("Displaced my string"), 10, 3);
|
||||
TS_ASSERT_EQUALS(testString, Common::U32String("Hello my good friends"));
|
||||
|
||||
// -----------------------
|
||||
// Deep copy compliance
|
||||
// -----------------------
|
||||
|
||||
// Makes a deep copy without changing the length of the original
|
||||
Common::U32String s1 = Common::U32String("TestTestTestTestTestTestTestTestTestTestTest");
|
||||
Common::U32String s2(s1);
|
||||
TS_ASSERT_EQUALS(s1, "TestTestTestTestTestTestTestTestTestTestTest");
|
||||
TS_ASSERT_EQUALS(s2, "TestTestTestTestTestTestTestTestTestTestTest");
|
||||
s1.replace(0, 4, Common::U32String("TEST"));
|
||||
TS_ASSERT_EQUALS(s1, "TESTTestTestTestTestTestTestTestTestTestTest");
|
||||
TS_ASSERT_EQUALS(s2, "TestTestTestTestTestTestTestTestTestTestTest");
|
||||
|
||||
// Makes a deep copy when we shorten the string
|
||||
Common::U32String s3 = Common::U32String("TestTestTestTestTestTestTestTestTestTestTest");
|
||||
Common::U32String s4(s3);
|
||||
s3.replace(0, 32, Common::U32String());
|
||||
TS_ASSERT_EQUALS(s3, "TestTestTest");
|
||||
TS_ASSERT_EQUALS(s4, "TestTestTestTestTestTestTestTestTestTestTest");
|
||||
}
|
||||
|
||||
void test_find() {
|
||||
Common::String a("0123012"), b;
|
||||
|
||||
TS_ASSERT_EQUALS(a.find('1'), 1u);
|
||||
TS_ASSERT_EQUALS(a.find('3'), 3u);
|
||||
TS_ASSERT_EQUALS(a.find('1', 3), 5u);
|
||||
TS_ASSERT_EQUALS(b.find('*'), Common::String::npos);
|
||||
TS_ASSERT_EQUALS(b.find('*', 1), Common::String::npos);
|
||||
|
||||
TS_ASSERT_EQUALS(a.rfind('1'), 5u);
|
||||
TS_ASSERT_EQUALS(a.rfind('3'), 3u);
|
||||
TS_ASSERT_EQUALS(a.rfind('1', 3), 1u);
|
||||
TS_ASSERT_EQUALS(b.rfind('*'), Common::String::npos);
|
||||
TS_ASSERT_EQUALS(b.rfind('*', 1), Common::String::npos);
|
||||
}
|
||||
|
||||
void test_setChar() {
|
||||
Common::String testString("123456");
|
||||
testString.setChar('2', 0);
|
||||
TS_ASSERT(testString == "223456");
|
||||
testString.setChar('0', 5);
|
||||
TS_ASSERT(testString == "223450");
|
||||
}
|
||||
|
||||
void test_insertChar() {
|
||||
Common::String testString("123456");
|
||||
testString.insertChar('2', 0);
|
||||
TS_ASSERT(testString == "2123456");
|
||||
testString.insertChar('0', 5);
|
||||
TS_ASSERT(testString == "21234056");
|
||||
testString.insertChar('7', 8);
|
||||
TS_ASSERT(testString == "212340567");
|
||||
}
|
||||
|
||||
void test_insertString() {
|
||||
Common::String testString("123456");
|
||||
testString.insertString("12", 0);
|
||||
TS_ASSERT(testString == "12123456");
|
||||
testString.insertString("01", 6);
|
||||
TS_ASSERT(testString == "1212340156");
|
||||
testString.insertString("78", 10);
|
||||
TS_ASSERT(testString == "121234015678");
|
||||
}
|
||||
|
||||
void test_comparison() {
|
||||
Common::String a("0123"), ax("01234"), b("0124"), e;
|
||||
TS_ASSERT_EQUALS(a, a);
|
||||
TS_ASSERT_EQUALS(ax, ax);
|
||||
TS_ASSERT_EQUALS(b, b);
|
||||
TS_ASSERT_EQUALS(e, e);
|
||||
|
||||
TS_ASSERT_DIFFERS(a, ax);
|
||||
TS_ASSERT_DIFFERS(a, b);
|
||||
TS_ASSERT_DIFFERS(a, e);
|
||||
TS_ASSERT_DIFFERS(ax, b);
|
||||
TS_ASSERT_DIFFERS(ax, e);
|
||||
TS_ASSERT_DIFFERS(b, ax);
|
||||
TS_ASSERT_DIFFERS(b, e);
|
||||
|
||||
TS_ASSERT_LESS_THAN(e, a);
|
||||
TS_ASSERT_LESS_THAN(e, ax);
|
||||
TS_ASSERT_LESS_THAN(e, b);
|
||||
TS_ASSERT_LESS_THAN(a, ax);
|
||||
TS_ASSERT_LESS_THAN(a, b);
|
||||
TS_ASSERT_LESS_THAN(ax, b);
|
||||
}
|
||||
|
||||
void test_ustr_comparison() {
|
||||
Common::U32String a("abc"), b("abd"), c, d("");
|
||||
|
||||
TS_ASSERT_EQUALS(a, a);
|
||||
TS_ASSERT_EQUALS(b, b);
|
||||
|
||||
TS_ASSERT_DIFFERS(a, b);
|
||||
|
||||
TS_ASSERT_LESS_THAN(a, b);
|
||||
|
||||
TS_ASSERT_LESS_THAN_EQUALS(a, b);
|
||||
TS_ASSERT_LESS_THAN_EQUALS(a, a);
|
||||
TS_ASSERT_LESS_THAN_EQUALS(b, b);
|
||||
|
||||
//U32String does not define compare, so test both sides
|
||||
TS_ASSERT(a >= a);
|
||||
TS_ASSERT(b > a);
|
||||
TS_ASSERT(b >= b);
|
||||
TS_ASSERT(b >= a);
|
||||
|
||||
TS_ASSERT(c == d);
|
||||
TS_ASSERT(a > c);
|
||||
TS_ASSERT(c < a);
|
||||
}
|
||||
};
|
||||
46
test/common/stream.h
Normal file
46
test/common/stream.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/memstream.h"
|
||||
|
||||
class ReadLineStreamTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_readline() {
|
||||
byte contents[] = { 'a', 'b', '\n', '\n', 'c', '\n' };
|
||||
Common::MemoryReadStream ms(contents, sizeof(contents));
|
||||
|
||||
char buffer[100];
|
||||
|
||||
TS_ASSERT_DIFFERS((char *)0, ms.readLine(buffer, sizeof(buffer)));
|
||||
TS_ASSERT_EQUALS(0, strcmp(buffer, "ab\n"));
|
||||
|
||||
TS_ASSERT_DIFFERS((char *)0, ms.readLine(buffer, sizeof(buffer)));
|
||||
TS_ASSERT_EQUALS(0, strcmp(buffer, "\n"));
|
||||
|
||||
TS_ASSERT_DIFFERS((char *)0, ms.readLine(buffer, sizeof(buffer)));
|
||||
TS_ASSERT_EQUALS(0, strcmp(buffer, "c\n"));
|
||||
|
||||
TS_ASSERT(!ms.eos());
|
||||
|
||||
TS_ASSERT_EQUALS((char *)0, ms.readLine(buffer, sizeof(buffer)));
|
||||
|
||||
TS_ASSERT(ms.eos());
|
||||
}
|
||||
|
||||
void test_readline2() {
|
||||
byte contents[] = { 'a', 'b', '\n', '\n', 'c' };
|
||||
Common::MemoryReadStream ms(contents, sizeof(contents));
|
||||
|
||||
char buffer[100];
|
||||
|
||||
TS_ASSERT_DIFFERS((char *)0, ms.readLine(buffer, sizeof(buffer)));
|
||||
TS_ASSERT_EQUALS(0, strcmp(buffer, "ab\n"));
|
||||
|
||||
TS_ASSERT_DIFFERS((char *)0, ms.readLine(buffer, sizeof(buffer)));
|
||||
TS_ASSERT_EQUALS(0, strcmp(buffer, "\n"));
|
||||
|
||||
TS_ASSERT_DIFFERS((char *)0, ms.readLine(buffer, sizeof(buffer)));
|
||||
TS_ASSERT_EQUALS(0, strcmp(buffer, "c"));
|
||||
|
||||
TS_ASSERT(ms.eos());
|
||||
}
|
||||
};
|
||||
47
test/common/subreadstream.h
Normal file
47
test/common/subreadstream.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "common/memstream.h"
|
||||
#include "common/substream.h"
|
||||
|
||||
class SubReadStreamTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_traverse() {
|
||||
byte contents[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
Common::MemoryReadStream ms(contents, 10);
|
||||
|
||||
int end = 5;
|
||||
|
||||
Common::SubReadStream srs(&ms, end);
|
||||
|
||||
int i;
|
||||
byte b;
|
||||
for (i = 0; i < end; ++i) {
|
||||
TS_ASSERT(!srs.eos());
|
||||
|
||||
b = srs.readByte();
|
||||
TS_ASSERT_EQUALS(i, b);
|
||||
}
|
||||
|
||||
TS_ASSERT(!srs.eos());
|
||||
b = srs.readByte();
|
||||
TS_ASSERT(srs.eos());
|
||||
}
|
||||
|
||||
void test_safe_eos() {
|
||||
byte contents[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
Common::MemoryReadStream ms(contents, sizeof(contents));
|
||||
|
||||
Common::SafeSeekableSubReadStream ssrs1(&ms, 0, sizeof(contents));
|
||||
Common::SafeSeekableSubReadStream ssrs2(&ms, 0, sizeof(contents));
|
||||
|
||||
// Read after the end of the stream of the first sub stream
|
||||
for (int32 i = 0; i <= ssrs1.size(); ++i)
|
||||
ssrs1.readByte();
|
||||
|
||||
// eos should be set for the first sub stream
|
||||
TS_ASSERT(ssrs1.eos());
|
||||
|
||||
// eos should not be set for the second sub stream
|
||||
TS_ASSERT(!ssrs2.eos());
|
||||
}
|
||||
};
|
||||
57
test/common/tokenizer.h
Normal file
57
test/common/tokenizer.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
#include "common/util.h"
|
||||
#include "common/tokenizer.h"
|
||||
|
||||
class TokenizerTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_nextToken() {
|
||||
|
||||
// test normal behavior
|
||||
Common::StringTokenizer strTokenizer("Now, this is a test!", " ,!");
|
||||
Common::String tokenArray[] = {"Now", "this", "is", "a", "test"};
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(tokenArray); ++i) {
|
||||
// make sure nextToken works correctly
|
||||
TS_ASSERT_EQUALS(tokenArray[i], strTokenizer.nextToken());
|
||||
}
|
||||
TS_ASSERT(strTokenizer.empty());
|
||||
|
||||
// Test edge cases:
|
||||
|
||||
// empty string
|
||||
Common::StringTokenizer s1("");
|
||||
TS_ASSERT_EQUALS("", s1.nextToken());
|
||||
TS_ASSERT(s1.empty());
|
||||
|
||||
// empty delimiter
|
||||
Common::StringTokenizer s2("test String", "");
|
||||
TS_ASSERT_EQUALS("test String", s2.nextToken());
|
||||
|
||||
// string is the delimiter
|
||||
Common::StringTokenizer s3("abc", "abc");
|
||||
TS_ASSERT_EQUALS("", s3.nextToken());
|
||||
TS_ASSERT(s3.empty());
|
||||
|
||||
// consecutive delimiters in the string
|
||||
Common::StringTokenizer s4("strstr,after all!!", "str, !");
|
||||
TS_ASSERT_EQUALS("af", s4.nextToken());
|
||||
}
|
||||
|
||||
void test_resetAndEmpty() {
|
||||
Common::StringTokenizer strTokenizer("Just, another test!", " ,!");
|
||||
|
||||
// test reset()
|
||||
Common::String token1 = strTokenizer.nextToken(); //Just
|
||||
TS_ASSERT_EQUALS(token1, "Just");
|
||||
strTokenizer.reset();
|
||||
Common::String token2 = strTokenizer.nextToken(); //Just
|
||||
TS_ASSERT_EQUALS(token2, "Just");
|
||||
|
||||
// test empty()
|
||||
TS_ASSERT(!strTokenizer.empty());
|
||||
strTokenizer.nextToken(); //another
|
||||
strTokenizer.nextToken(); //test
|
||||
TS_ASSERT(strTokenizer.empty());
|
||||
}
|
||||
|
||||
};
|
||||
253
test/common/util.h
Normal file
253
test/common/util.h
Normal file
@@ -0,0 +1,253 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
#include "common/util.h"
|
||||
|
||||
/**
|
||||
* Test suite for the functions in common/util.h
|
||||
*/
|
||||
class UtilTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_parsebool_yesno() {
|
||||
|
||||
// First test for the parseBool function.
|
||||
// These are the mixed case yes/no cases that must work
|
||||
|
||||
bool valasbool;
|
||||
bool success;
|
||||
|
||||
Common::String string_1("Yes");
|
||||
success = Common::parseBool(string_1, valasbool);
|
||||
TS_ASSERT_EQUALS(success, 1);
|
||||
TS_ASSERT_EQUALS(valasbool, 1);
|
||||
|
||||
Common::String string_2("nO");
|
||||
success = Common::parseBool(string_2, valasbool);
|
||||
TS_ASSERT_EQUALS(success, 1);
|
||||
TS_ASSERT_EQUALS(valasbool, 0);
|
||||
}
|
||||
|
||||
void test_parsebool_truefalse() {
|
||||
|
||||
// First test for the parseBool function.
|
||||
// These are the mixed case true/false cases that must work
|
||||
|
||||
bool valasbool;
|
||||
bool success;
|
||||
|
||||
Common::String string_3("tRuE");
|
||||
success = Common::parseBool(string_3, valasbool);
|
||||
TS_ASSERT_EQUALS(success, 1);
|
||||
TS_ASSERT_EQUALS(valasbool, 1);
|
||||
|
||||
Common::String string_4("fAlSe");
|
||||
success = Common::parseBool(string_4, valasbool);
|
||||
TS_ASSERT_EQUALS(success, 1);
|
||||
TS_ASSERT_EQUALS(valasbool, 0);
|
||||
}
|
||||
|
||||
void test_parsebool_onezero() {
|
||||
|
||||
// Third test for the parseBool function.
|
||||
// These are the 1/0 cases that must work.
|
||||
// Note that while 'a-z'+0x20 must work just fine,
|
||||
// '0-1'+0x20 should NOT; this is addressed in
|
||||
// parsebool_bad
|
||||
|
||||
bool valasbool;
|
||||
bool success;
|
||||
|
||||
Common::String string_5("1");
|
||||
success = Common::parseBool(string_5, valasbool);
|
||||
TS_ASSERT_EQUALS(success, 1);
|
||||
TS_ASSERT_EQUALS(valasbool, 1);
|
||||
|
||||
Common::String string_6("0");
|
||||
success = Common::parseBool(string_6, valasbool);
|
||||
TS_ASSERT_EQUALS(success, 1);
|
||||
TS_ASSERT_EQUALS(valasbool, 0);
|
||||
|
||||
}
|
||||
|
||||
void test_parsebool_bad() {
|
||||
|
||||
bool valasbool;
|
||||
bool success;
|
||||
|
||||
// Bad cases that should not return success #1:
|
||||
// Random string
|
||||
Common::String string_1("u_f1ght_l1k3_a_c0w");
|
||||
success = Common::parseBool(string_1, valasbool);
|
||||
TS_ASSERT_EQUALS(success, 0);
|
||||
|
||||
// Bad cases that should not return success #2, #3:
|
||||
// The function should NOT accept trailing whitespaces:
|
||||
Common::String string_2(" yes");
|
||||
success = Common::parseBool(string_2, valasbool);
|
||||
TS_ASSERT_EQUALS(success, 0);
|
||||
|
||||
Common::String string_3("yes ");
|
||||
success = Common::parseBool(string_3, valasbool);
|
||||
TS_ASSERT_EQUALS(success, 0);
|
||||
|
||||
// While 'a-z'+0x20 must work just fine,
|
||||
// '0-1'+0x20 should NOT. '2' is not good either.
|
||||
|
||||
Common::String string_4("\x50");
|
||||
success = Common::parseBool(string_4, valasbool);
|
||||
TS_ASSERT_EQUALS(success, 0);
|
||||
|
||||
Common::String string_5("\x51");
|
||||
success = Common::parseBool(string_5, valasbool);
|
||||
TS_ASSERT_EQUALS(success, 0);
|
||||
|
||||
Common::String string_6("2");
|
||||
success = Common::parseBool(string_6, valasbool);
|
||||
TS_ASSERT_EQUALS(success, 0);
|
||||
}
|
||||
|
||||
void test_is_al_num() {
|
||||
|
||||
// Test the isAlnum function
|
||||
// Should return true if and only if the input is an alphanumeric char
|
||||
|
||||
TS_ASSERT_EQUALS(Common::isAlnum('a'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isAlnum('A'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isAlnum('z'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isAlnum('Z'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isAlnum('1'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isAlnum('0'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isAlnum('\xA7'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isAlnum('$'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isAlnum(' '), 0);
|
||||
TS_ASSERT_EQUALS(Common::isAlnum('\n'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isAlnum('\b'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isAlnum(0), 0);
|
||||
TS_ASSERT_EQUALS(Common::isAlnum(255), 0);
|
||||
|
||||
}
|
||||
|
||||
void test_is_alpha() {
|
||||
|
||||
// Test the isAlpha function
|
||||
// Should return true if and only if the input is an alphanumeric char
|
||||
|
||||
TS_ASSERT_EQUALS(Common::isAlpha('a'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isAlpha('A'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isAlpha('z'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isAlpha('Z'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isAlpha('1'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isAlpha('0'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isAlpha('\xA7'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isAlpha('$'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isAlpha(' '), 0);
|
||||
TS_ASSERT_EQUALS(Common::isAlpha('\n'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isAlpha('\b'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isAlpha(0), 0);
|
||||
TS_ASSERT_EQUALS(Common::isAlpha(255), 0);
|
||||
|
||||
}
|
||||
|
||||
void test_is_digit() {
|
||||
|
||||
// Test the isDigit function
|
||||
// Should return true if and only if the input is a single digit
|
||||
|
||||
TS_ASSERT_EQUALS(Common::isDigit('a'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isDigit('A'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isDigit('z'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isDigit('Z'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isDigit('1'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isDigit('0'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isDigit('\xA7'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isDigit('$'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isDigit(' '), 0);
|
||||
TS_ASSERT_EQUALS(Common::isDigit('\n'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isDigit('\b'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isDigit(0), 0);
|
||||
TS_ASSERT_EQUALS(Common::isDigit(255), 0);
|
||||
|
||||
}
|
||||
|
||||
void test_is_lower() {
|
||||
|
||||
// Test the isLower function
|
||||
// Should return true if and only if the input is a lowercase char
|
||||
|
||||
TS_ASSERT_EQUALS(Common::isLower('a'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isLower('A'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isLower('z'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isLower('Z'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isLower('1'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isLower('0'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isLower('\xA7'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isLower('$'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isLower(' '), 0);
|
||||
TS_ASSERT_EQUALS(Common::isLower('\n'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isLower('\b'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isLower(0), 0);
|
||||
TS_ASSERT_EQUALS(Common::isLower(255), 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void test_is_upper() {
|
||||
|
||||
// Test the isUpper function
|
||||
// Should return true if and only if the input is an uppercase char
|
||||
|
||||
TS_ASSERT_EQUALS(Common::isUpper('a'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isUpper('A'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isUpper('z'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isUpper('Z'), 1);
|
||||
TS_ASSERT_EQUALS(Common::isUpper('1'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isUpper('0'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isUpper('\xA7'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isUpper('$'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isUpper(' '), 0);
|
||||
TS_ASSERT_EQUALS(Common::isUpper('\n'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isUpper('\b'), 0);
|
||||
TS_ASSERT_EQUALS(Common::isUpper(0), 0);
|
||||
TS_ASSERT_EQUALS(Common::isUpper(255), 0);
|
||||
|
||||
}
|
||||
void test_is_space() {
|
||||
// isSpace should return true iff the character is some kind of whitespace
|
||||
// or tab character
|
||||
for (int c = 0; c < 255; c++) {
|
||||
if (c == ' ' || c == '\t' ||
|
||||
c == '\r' || c == '\n' ||
|
||||
c == '\v' || c == '\f') {
|
||||
TS_ASSERT_EQUALS(Common::isSpace(c), 1);
|
||||
} else {
|
||||
TS_ASSERT_EQUALS(Common::isSpace(c), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_is_print() {
|
||||
// isPrint should return true iff the input is a printable ascii char.
|
||||
// That is to say, 0x20 to 0x7E.
|
||||
for (int c = 0; c < 255; c++) {
|
||||
if (c >= 0x20 && c <= 0x7E) {
|
||||
TS_ASSERT_EQUALS(Common::isPrint(c), 1);
|
||||
} else {
|
||||
TS_ASSERT_EQUALS(Common::isPrint(c), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
void test_is_punct() {
|
||||
// isPunct should return true if the input is a punctation ascii char.
|
||||
for (int c = 0; c < 255; c++) {
|
||||
if (c >= 33 && c <= 47) {
|
||||
TS_ASSERT_EQUALS(Common::isPunct(c), 1);
|
||||
} else if (c >= 58 && c <= 64) {
|
||||
TS_ASSERT_EQUALS(Common::isPunct(c), 1);
|
||||
} else if (c >= 91 && c <= 96) {
|
||||
TS_ASSERT_EQUALS(Common::isPunct(c), 1);
|
||||
} else if (c >= 123 && c <= 126) {
|
||||
TS_ASSERT_EQUALS(Common::isPunct(c), 1);
|
||||
} else {
|
||||
TS_ASSERT_EQUALS(Common::isPunct(c), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
502
test/cxxtest/COPYING
Normal file
502
test/cxxtest/COPYING
Normal file
@@ -0,0 +1,502 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
63
test/cxxtest/README
Normal file
63
test/cxxtest/README
Normal file
@@ -0,0 +1,63 @@
|
||||
Introduction
|
||||
------------
|
||||
|
||||
CxxTest is a JUnit/CppUnit/xUnit-like framework for C++.
|
||||
|
||||
Its advantages over existing alternatives are that it:
|
||||
- Doesn't require RTTI
|
||||
- Doesn't require member template functions
|
||||
- Doesn't require exception handling
|
||||
- Doesn't require any external libraries (including memory management,
|
||||
file/console I/O, graphics libraries)
|
||||
|
||||
This makes it extremely portable and usable.
|
||||
|
||||
CxxTest is available under the GNU Lesser General Public Licence (LGPL).
|
||||
See http://www.gnu.org/copyleft/lesser.html for the license.
|
||||
|
||||
Simple user's guide
|
||||
-------------------
|
||||
|
||||
1. Create a test suite header file:
|
||||
|
||||
MyTest.h:
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
class MyTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void testAddition( void )
|
||||
{
|
||||
TS_ASSERT( 1 + 1 > 1 );
|
||||
TS_ASSERT_EQUALS( 1 + 1, 2 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
2. Generate the tests file:
|
||||
|
||||
# cxxtestgen.pl -o tests.cpp MyTestSuite.h
|
||||
|
||||
|
||||
3. Create a main function that runs the tests
|
||||
|
||||
main.cpp:
|
||||
#include <cxxtest/ErrorPrinter.h>
|
||||
|
||||
int main( void )
|
||||
{
|
||||
CxxText::ErrorPrinter::runAllTests();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
4. Compile and run!
|
||||
|
||||
# g++ -o main main.cpp tests.cpp
|
||||
# ./main
|
||||
Running 1 test(s).OK!
|
||||
|
||||
|
||||
Advanced User's Guide
|
||||
---------------------
|
||||
See docs/guide.html.
|
||||
33
test/cxxtest/TODO
Normal file
33
test/cxxtest/TODO
Normal file
@@ -0,0 +1,33 @@
|
||||
This is an -*- Outline -*- of ideas for future versions of CxxTest.
|
||||
It is not meant to be "human readable".
|
||||
|
||||
* CxxTest To Do list
|
||||
|
||||
** Mock framework
|
||||
|
||||
Write some mocks
|
||||
|
||||
*** Distribution
|
||||
Separate packages (w/ binaries)? How would that be used?
|
||||
For Windows: .lib for "Real" and "Mock" parts.
|
||||
For Linux: Maybe. Different compilers etc.
|
||||
So probably only source release with Makefiles and .ds[pw]? Or just Win32 binary.
|
||||
|
||||
**** Installation?
|
||||
extract cxxtest-x.y.z.tar.gz
|
||||
(extract cxxtest-mock-x.y.z.tar.gz) ?
|
||||
make -C cxxtest/Real
|
||||
make -C cxxtest/Mock
|
||||
|
||||
or maybe make -C cxxtest -f Makefile.mock
|
||||
but then Makefile.mock.bcc32, Makefile.mock.msvc, Makefile.mock.gcc, and heaven knows what else.
|
||||
|
||||
Could put the Makefile.mock.* in cxxtest/Real and cxxtest/Mock or in cxxtest/T
|
||||
|
||||
Maybe this should be a different package altogether?
|
||||
Seems logical, since they evolve separately. But then you'd want to download both.
|
||||
|
||||
** Thoughts
|
||||
-fomit-frame-pointer
|
||||
|
||||
** TS_HEX
|
||||
152
test/cxxtest/Versions
Normal file
152
test/cxxtest/Versions
Normal file
@@ -0,0 +1,152 @@
|
||||
CxxTest Releases
|
||||
================
|
||||
|
||||
Version 3.10.1 (2004-12-01):
|
||||
----------------------------
|
||||
- Improved support for VC7
|
||||
- Fixed clash with some versions of STL
|
||||
|
||||
Version 3.10.0 (2004-11-20):
|
||||
----------------------------
|
||||
- Added mock framework for global functions
|
||||
- Added TS_ASSERT_THROWS_ASSERT and TS_ASSERT_THROWS_EQUALS
|
||||
- Added CXXTEST_ENUM_TRAITS
|
||||
- Improved support for STL classes (vector, map etc.)
|
||||
- Added support for Digital Mars compiler
|
||||
- Reduced root/part compilation time and binary size
|
||||
- Support C++-style commenting of tests
|
||||
|
||||
Version 3.9.1 (2004-01-19):
|
||||
---------------------------
|
||||
- Fixed small bug with runner exit code
|
||||
- Embedded test suites are now deprecated
|
||||
|
||||
Version 3.9.0 (2004-01-17):
|
||||
---------------------------
|
||||
- Added TS_TRACE
|
||||
- Added --no-static-init
|
||||
- CxxTest::setAbortTestOnFail() works even without --abort-on-fail
|
||||
|
||||
Version 3.8.5 (2004-01-08):
|
||||
---------------------------
|
||||
- Added --no-eh
|
||||
- Added CxxTest::setAbortTestOnFail() and CXXTEST_DEFAULT_ABORT
|
||||
- Added CxxTest::setMaxDumpSize()
|
||||
- Added StdioFilePrinter
|
||||
|
||||
Version 3.8.4 (2003-12-31):
|
||||
---------------------------
|
||||
- Split distribution into cxxtest and cxxtest-selftest
|
||||
- Added `sample/msvc/FixFiles.bat'
|
||||
|
||||
Version 3.8.3 (2003-12-24):
|
||||
---------------------------
|
||||
- Added TS_ASSERT_PREDICATE
|
||||
- Template files can now specify where to insert the preamble
|
||||
- Added a sample Visual Studio workspace in `sample/msvc'
|
||||
- Can compile in MSVC with warning level 4
|
||||
- Changed output format slightly
|
||||
|
||||
Version 3.8.1 (2003-12-21):
|
||||
---------------------------
|
||||
- Fixed small bug when using multiple --part files.
|
||||
- Fixed X11 GUI crash when there's no X server.
|
||||
- Added GlobalFixture::setUpWorld()/tearDownWorld()
|
||||
- Added leaveOnly(), activateAllTests() and `sample/only.tpl'
|
||||
- Should now run without warnings on Sun compiler.
|
||||
|
||||
Version 3.8.0 (2003-12-13):
|
||||
---------------------------
|
||||
- Fixed bug where `Root.cpp' needed exception handling
|
||||
- Added TS_ASSERT_RELATION
|
||||
- TSM_ macros now also tell you what went wrong
|
||||
- Renamed Win32Gui::free() to avoid clashes
|
||||
- Now compatible with more versions of Borland compiler
|
||||
- Improved the documentation
|
||||
|
||||
Version 3.7.1 (2003-09-29):
|
||||
---------------------------
|
||||
- Added --version
|
||||
- Compiles with even more exotic g++ warnings
|
||||
- Win32 Gui compiles with UNICODE
|
||||
- Should compile on some more platforms (Sun Forte, HP aCC)
|
||||
|
||||
Version 3.7.0 (2003-09-20):
|
||||
---------------------------
|
||||
- Added TS_ASSERT_LESS_THAN_EQUALS
|
||||
- Minor cleanups
|
||||
|
||||
Version 3.6.1 (2003-09-15):
|
||||
---------------------------
|
||||
- Improved QT GUI
|
||||
- Improved portability some more
|
||||
|
||||
Version 3.6.0 (2003-09-04):
|
||||
---------------------------
|
||||
- Added --longlong
|
||||
- Some portability improvements
|
||||
|
||||
Version 3.5.1 (2003-09-03):
|
||||
---------------------------
|
||||
- Major internal rewrite of macros
|
||||
- Added TS_ASSERT_SAME_DATA
|
||||
- Added --include option
|
||||
- Added --part and --root to enable splitting the test runner
|
||||
- Added global fixtures
|
||||
- Enhanced Win32 GUI with timers, -keep and -title
|
||||
- Now compiles with strict warnings
|
||||
|
||||
Version 3.1.1 (2003-08-27):
|
||||
---------------------------
|
||||
- Fixed small bug in TS_ASSERT_THROWS_*()
|
||||
|
||||
Version 3.1.0 (2003-08-23):
|
||||
---------------------------
|
||||
- Default ValueTraits now dumps value as hex bytes
|
||||
- Fixed double invocation bug (e.g. TS_FAIL(functionWithSideEffects()))
|
||||
- TS_ASSERT_THROWS*() are now "abort on fail"-friendly
|
||||
- Win32 GUI now supports Windows 98 and doesn't need comctl32.lib
|
||||
|
||||
Version 3.0.1 (2003-08-07):
|
||||
---------------------------
|
||||
- Added simple GUI for X11, Win32 and Qt
|
||||
- Added TS_WARN() macro
|
||||
- Removed --exit-code
|
||||
- Improved samples
|
||||
- Improved support for older (pre-std::) compilers
|
||||
- Made a PDF version of the User's Guide
|
||||
|
||||
Version 2.8.4 (2003-07-21):
|
||||
---------------------------
|
||||
- Now supports g++-3.3
|
||||
- Added --have-eh
|
||||
- Fixed bug in numberToString()
|
||||
|
||||
Version 2.8.3 (2003-06-30):
|
||||
---------------------------
|
||||
- Fixed bugs in cxxtestgen.pl
|
||||
- Fixed warning for some compilers in ErrorPrinter/StdioPrinter
|
||||
- Thanks Martin Jost for pointing out these problems!
|
||||
|
||||
Version 2.8.2 (2003-06-10):
|
||||
---------------------------
|
||||
- Fixed bug when using CXXTEST_ABORT_TEST_ON_FAIL without standard library
|
||||
- Added CXXTEST_USER_TRAITS
|
||||
- Added --abort-on-fail
|
||||
|
||||
Version 2.8.1 (2003-01-16):
|
||||
---------------------------
|
||||
- Fixed charToString() for negative chars
|
||||
|
||||
Version 2.8.0 (2003-01-13):
|
||||
---------------------------
|
||||
- Added CXXTEST_ABORT_TEST_ON_FAIL for xUnit-like behaviour
|
||||
- Added `sample/winddk'
|
||||
- Improved ValueTraits
|
||||
- Improved output formatter
|
||||
- Started version history
|
||||
|
||||
Version 2.7.0 (2002-09-29):
|
||||
---------------------------
|
||||
- Added embedded test suites
|
||||
- Major internal improvements
|
||||
39
test/cxxtest/cxxtest.spec
Normal file
39
test/cxxtest/cxxtest.spec
Normal file
@@ -0,0 +1,39 @@
|
||||
Name: cxxtest
|
||||
Summary: CxxTest Testing Framework for C++
|
||||
Version: 3.10.1
|
||||
Release: 1
|
||||
Copyright: LGPL
|
||||
Group: Development/C++
|
||||
Source: cxxtest-%{version}.tar.gz
|
||||
BuildRoot: /tmp/cxxtest-build
|
||||
BuildArch: noarch
|
||||
Prefix: /usr
|
||||
|
||||
%description
|
||||
CxxTest is a JUnit/CppUnit/xUnit-like framework for C++.
|
||||
Its advantages over existing alternatives are that it:
|
||||
- Doesn't require RTTI
|
||||
- Doesn't require member template functions
|
||||
- Doesn't require exception handling
|
||||
- Doesn't require any external libraries (including memory management,
|
||||
file/console I/O, graphics libraries)
|
||||
|
||||
%prep
|
||||
%setup -n cxxtest
|
||||
|
||||
%build
|
||||
|
||||
%install
|
||||
install -m 755 -d $RPM_BUILD_ROOT/usr/bin $RPM_BUILD_ROOT/usr/include/cxxtest
|
||||
install -m 755 cxxtestgen.p[ly] $RPM_BUILD_ROOT/usr/bin/
|
||||
install -m 644 cxxtest/* $RPM_BUILD_ROOT/usr/include/cxxtest/
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-, root, root) %doc README
|
||||
%attr(-, root, root) %doc sample
|
||||
%attr(-, root, root) /usr/include/cxxtest
|
||||
%attr(-, root, root) /usr/bin/cxxtestgen.pl
|
||||
%attr(-, root, root) /usr/bin/cxxtestgen.py
|
||||
58
test/cxxtest/cxxtest/Descriptions.cpp
Normal file
58
test/cxxtest/cxxtest/Descriptions.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef __cxxtest__Descriptions_cpp__
|
||||
#define __cxxtest__Descriptions_cpp__
|
||||
|
||||
#include <cxxtest/Descriptions.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
TestDescription::~TestDescription() {}
|
||||
SuiteDescription::~SuiteDescription() {}
|
||||
WorldDescription::~WorldDescription() {}
|
||||
|
||||
//
|
||||
// Convert total tests to string
|
||||
//
|
||||
#ifndef _CXXTEST_FACTOR
|
||||
char *WorldDescription::strTotalTests( char *s ) const
|
||||
{
|
||||
numberToString( numTotalTests(), s );
|
||||
return s;
|
||||
}
|
||||
#else // _CXXTEST_FACTOR
|
||||
char *WorldDescription::strTotalTests( char *s ) const
|
||||
{
|
||||
char *p = numberToString( numTotalTests(), s );
|
||||
|
||||
if ( numTotalTests() <= 1 )
|
||||
return s;
|
||||
|
||||
unsigned n = numTotalTests();
|
||||
unsigned numFactors = 0;
|
||||
|
||||
for ( unsigned factor = 2; (factor * factor) <= n; factor += (factor == 2) ? 1 : 2 ) {
|
||||
unsigned power;
|
||||
|
||||
for ( power = 0; (n % factor) == 0; n /= factor )
|
||||
++ power;
|
||||
|
||||
if ( !power )
|
||||
continue;
|
||||
|
||||
p = numberToString( factor, copyString( p, (numFactors == 0) ? " = " : " * " ) );
|
||||
if ( power > 1 )
|
||||
p = numberToString( power, copyString( p, "^" ) );
|
||||
++ numFactors;
|
||||
}
|
||||
|
||||
if ( n > 1 ) {
|
||||
if ( !numFactors )
|
||||
copyString( p, tracker().failedTests() ? " :(" : tracker().warnings() ? " :|" : " :)" );
|
||||
else
|
||||
numberToString( n, copyString( p, " * " ) );
|
||||
}
|
||||
return s;
|
||||
}
|
||||
#endif // _CXXTEST_FACTOR
|
||||
}
|
||||
|
||||
#endif // __cxxtest__Descriptions_cpp__
|
||||
73
test/cxxtest/cxxtest/Descriptions.h
Normal file
73
test/cxxtest/cxxtest/Descriptions.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#ifndef __cxxtest__Descriptions_h__
|
||||
#define __cxxtest__Descriptions_h__
|
||||
|
||||
//
|
||||
// TestDescription, SuiteDescription and WorldDescription
|
||||
// hold information about tests so they can be run and reported.
|
||||
//
|
||||
|
||||
#include <cxxtest/LinkedList.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class TestSuite;
|
||||
|
||||
class TestDescription : public Link
|
||||
{
|
||||
public:
|
||||
virtual ~TestDescription();
|
||||
|
||||
virtual const char *file() const = 0;
|
||||
virtual unsigned line() const = 0;
|
||||
virtual const char *testName() const = 0;
|
||||
virtual const char *suiteName() const = 0;
|
||||
|
||||
virtual void run() = 0;
|
||||
|
||||
virtual const TestDescription *next() const = 0;
|
||||
virtual TestDescription *next() = 0;
|
||||
};
|
||||
|
||||
class SuiteDescription : public Link
|
||||
{
|
||||
public:
|
||||
virtual ~SuiteDescription();
|
||||
|
||||
virtual const char *file() const = 0;
|
||||
virtual unsigned line() const = 0;
|
||||
virtual const char *suiteName() const = 0;
|
||||
virtual TestSuite *suite() const = 0;
|
||||
|
||||
virtual unsigned numTests() const = 0;
|
||||
virtual const TestDescription &testDescription( unsigned /*i*/ ) const = 0;
|
||||
|
||||
virtual TestDescription *firstTest() = 0;
|
||||
virtual const TestDescription *firstTest() const = 0;
|
||||
virtual SuiteDescription *next() = 0;
|
||||
virtual const SuiteDescription *next() const = 0;
|
||||
|
||||
virtual void activateAllTests() = 0;
|
||||
virtual bool leaveOnly( const char * /*testName*/ ) = 0;
|
||||
};
|
||||
|
||||
class WorldDescription : public Link
|
||||
{
|
||||
public:
|
||||
virtual ~WorldDescription();
|
||||
|
||||
virtual unsigned numSuites( void ) const = 0;
|
||||
virtual unsigned numTotalTests( void ) const = 0;
|
||||
virtual const SuiteDescription &suiteDescription( unsigned /*i*/ ) const = 0;
|
||||
|
||||
enum { MAX_STRLEN_TOTAL_TESTS = 32 };
|
||||
char *strTotalTests( char * /*buffer*/ ) const;
|
||||
|
||||
virtual SuiteDescription *firstSuite() = 0;
|
||||
virtual const SuiteDescription *firstSuite() const = 0;
|
||||
|
||||
virtual void activateAllTests() = 0;
|
||||
virtual bool leaveOnly( const char * /*suiteName*/, const char * /*testName*/ = 0 ) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __cxxtest__Descriptions_h__
|
||||
48
test/cxxtest/cxxtest/DummyDescriptions.cpp
Normal file
48
test/cxxtest/cxxtest/DummyDescriptions.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <cxxtest/DummyDescriptions.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
DummyTestDescription::DummyTestDescription() {}
|
||||
|
||||
const char *DummyTestDescription::file() const { return "<no file>"; }
|
||||
unsigned DummyTestDescription::line() const { return 0; }
|
||||
const char *DummyTestDescription::testName() const { return "<no test>"; }
|
||||
const char *DummyTestDescription::suiteName() const { return "<no suite>"; }
|
||||
bool DummyTestDescription::setUp() { return true;}
|
||||
void DummyTestDescription::run() {}
|
||||
bool DummyTestDescription::tearDown() { return true;}
|
||||
|
||||
TestDescription *DummyTestDescription::next() { return 0; }
|
||||
const TestDescription *DummyTestDescription::next() const { return 0; }
|
||||
|
||||
DummySuiteDescription::DummySuiteDescription() : _test() {}
|
||||
|
||||
const char *DummySuiteDescription::file() const { return "<no file>"; }
|
||||
unsigned DummySuiteDescription::line() const { return 0; }
|
||||
const char *DummySuiteDescription::suiteName() const { return "<no suite>"; }
|
||||
TestSuite *DummySuiteDescription::suite() const { return 0; }
|
||||
unsigned DummySuiteDescription::numTests() const { return 0; }
|
||||
const TestDescription &DummySuiteDescription::testDescription( unsigned ) const { return _test; }
|
||||
SuiteDescription *DummySuiteDescription::next() { return 0; }
|
||||
TestDescription *DummySuiteDescription::firstTest() { return 0; }
|
||||
const SuiteDescription *DummySuiteDescription::next() const { return 0; }
|
||||
const TestDescription *DummySuiteDescription::firstTest() const { return 0; }
|
||||
void DummySuiteDescription::activateAllTests() {}
|
||||
bool DummySuiteDescription::leaveOnly( const char * /*testName*/ ) { return false; }
|
||||
|
||||
bool DummySuiteDescription::setUp() { return true;}
|
||||
bool DummySuiteDescription::tearDown() { return true;}
|
||||
|
||||
DummyWorldDescription::DummyWorldDescription() : _suite() {}
|
||||
|
||||
unsigned DummyWorldDescription::numSuites( void ) const { return 0; }
|
||||
unsigned DummyWorldDescription::numTotalTests( void ) const { return 0; }
|
||||
const SuiteDescription &DummyWorldDescription::suiteDescription( unsigned ) const { return _suite; }
|
||||
SuiteDescription *DummyWorldDescription::firstSuite() { return 0; }
|
||||
const SuiteDescription *DummyWorldDescription::firstSuite() const { return 0; }
|
||||
void DummyWorldDescription::activateAllTests() {}
|
||||
bool DummyWorldDescription::leaveOnly( const char * /*suiteName*/, const char * /*testName*/ ) { return false; }
|
||||
|
||||
bool DummyWorldDescription::setUp() { return true;}
|
||||
bool DummyWorldDescription::tearDown() { return true;}
|
||||
}
|
||||
75
test/cxxtest/cxxtest/DummyDescriptions.h
Normal file
75
test/cxxtest/cxxtest/DummyDescriptions.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#ifndef __cxxtest__DummyDescriptions_h__
|
||||
#define __cxxtest__DummyDescriptions_h__
|
||||
|
||||
//
|
||||
// DummyTestDescription, DummySuiteDescription and DummyWorldDescription
|
||||
//
|
||||
|
||||
#include <cxxtest/Descriptions.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class DummyTestDescription : public TestDescription
|
||||
{
|
||||
public:
|
||||
DummyTestDescription();
|
||||
|
||||
const char *file() const;
|
||||
unsigned line() const;
|
||||
const char *testName() const;
|
||||
const char *suiteName() const;
|
||||
bool setUp();
|
||||
void run();
|
||||
bool tearDown();
|
||||
|
||||
TestDescription *next();
|
||||
const TestDescription *next() const;
|
||||
};
|
||||
|
||||
class DummySuiteDescription : public SuiteDescription
|
||||
{
|
||||
public:
|
||||
DummySuiteDescription();
|
||||
|
||||
const char *file() const;
|
||||
unsigned line() const;
|
||||
const char *suiteName() const;
|
||||
TestSuite *suite() const;
|
||||
unsigned numTests() const;
|
||||
const TestDescription &testDescription( unsigned ) const;
|
||||
SuiteDescription *next();
|
||||
TestDescription *firstTest();
|
||||
const SuiteDescription *next() const;
|
||||
const TestDescription *firstTest() const;
|
||||
void activateAllTests();
|
||||
bool leaveOnly( const char * /*testName*/ );
|
||||
|
||||
bool setUp();
|
||||
bool tearDown();
|
||||
|
||||
private:
|
||||
DummyTestDescription _test;
|
||||
};
|
||||
|
||||
class DummyWorldDescription : public WorldDescription
|
||||
{
|
||||
public:
|
||||
DummyWorldDescription();
|
||||
|
||||
unsigned numSuites( void ) const;
|
||||
unsigned numTotalTests( void ) const;
|
||||
const SuiteDescription &suiteDescription( unsigned ) const;
|
||||
SuiteDescription *firstSuite();
|
||||
const SuiteDescription *firstSuite() const;
|
||||
void activateAllTests();
|
||||
bool leaveOnly( const char * /*suiteName*/, const char * /*testName*/ = 0 );
|
||||
|
||||
bool setUp();
|
||||
bool tearDown();
|
||||
|
||||
private:
|
||||
DummySuiteDescription _suite;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __cxxtest__DummyDescriptions_h__
|
||||
281
test/cxxtest/cxxtest/ErrorFormatter.h
Normal file
281
test/cxxtest/cxxtest/ErrorFormatter.h
Normal file
@@ -0,0 +1,281 @@
|
||||
#ifndef __cxxtest__ErrorFormatter_h__
|
||||
#define __cxxtest__ErrorFormatter_h__
|
||||
|
||||
//
|
||||
// The ErrorFormatter is a TestListener that
|
||||
// prints reports of the errors to an output
|
||||
// stream. Since we cannot rely ou the standard
|
||||
// iostreams, this header defines a base class
|
||||
// analogout to std::ostream.
|
||||
//
|
||||
|
||||
#include <cxxtest/TestRunner.h>
|
||||
#include <cxxtest/TestListener.h>
|
||||
#include <cxxtest/TestTracker.h>
|
||||
#include <cxxtest/ValueTraits.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class OutputStream
|
||||
{
|
||||
public:
|
||||
virtual ~OutputStream() {}
|
||||
virtual void flush() {}
|
||||
virtual OutputStream &operator<<( unsigned /*number*/ ) { return *this; }
|
||||
virtual OutputStream &operator<<( const char * /*string*/ ) { return *this; }
|
||||
|
||||
typedef void (*Manipulator)( OutputStream & );
|
||||
|
||||
virtual OutputStream &operator<<( Manipulator m ) { m( *this ); return *this; }
|
||||
static void endl( OutputStream &o ) { (o << "\n").flush(); }
|
||||
};
|
||||
|
||||
class ErrorFormatter : public TestListener
|
||||
{
|
||||
public:
|
||||
ErrorFormatter( OutputStream *o, const char *preLine = ":", const char *postLine = "" ) :
|
||||
_dotting( true ),
|
||||
_reported( false ),
|
||||
_o(o),
|
||||
_preLine(preLine),
|
||||
_postLine(postLine)
|
||||
{
|
||||
}
|
||||
|
||||
int run()
|
||||
{
|
||||
TestRunner::runAllTests( *this );
|
||||
return tracker().failedTests();
|
||||
}
|
||||
|
||||
void enterWorld( const WorldDescription & /*desc*/ )
|
||||
{
|
||||
(*_o) << "Running " << totalTests;
|
||||
_o->flush();
|
||||
_dotting = true;
|
||||
_reported = false;
|
||||
}
|
||||
|
||||
static void totalTests( OutputStream &o )
|
||||
{
|
||||
char s[WorldDescription::MAX_STRLEN_TOTAL_TESTS];
|
||||
const WorldDescription &wd = tracker().world();
|
||||
o << wd.strTotalTests( s ) << (wd.numTotalTests() == 1 ? " test" : " tests");
|
||||
}
|
||||
|
||||
void enterSuite( const SuiteDescription & )
|
||||
{
|
||||
_reported = false;
|
||||
}
|
||||
|
||||
void enterTest( const TestDescription & )
|
||||
{
|
||||
_reported = false;
|
||||
}
|
||||
|
||||
void leaveTest( const TestDescription & )
|
||||
{
|
||||
if ( !tracker().testFailed() ) {
|
||||
((*_o) << ".").flush();
|
||||
_dotting = true;
|
||||
}
|
||||
}
|
||||
|
||||
void leaveWorld( const WorldDescription &desc )
|
||||
{
|
||||
if ( !tracker().failedTests() ) {
|
||||
(*_o) << "OK!" << endl;
|
||||
return;
|
||||
}
|
||||
newLine();
|
||||
(*_o) << "Failed " << tracker().failedTests() << " of " << totalTests << endl;
|
||||
unsigned numPassed = desc.numTotalTests() - tracker().failedTests();
|
||||
(*_o) << "Success rate: " << (numPassed * 100 / desc.numTotalTests()) << "%" << endl;
|
||||
}
|
||||
|
||||
void trace( const char *file, unsigned line, const char *expression )
|
||||
{
|
||||
stop( file, line ) << "Trace: " <<
|
||||
expression << endl;
|
||||
}
|
||||
|
||||
void warning( const char *file, unsigned line, const char *expression )
|
||||
{
|
||||
stop( file, line ) << "Warning: " <<
|
||||
expression << endl;
|
||||
}
|
||||
|
||||
void failedTest( const char *file, unsigned line, const char *expression )
|
||||
{
|
||||
stop( file, line ) << "Error: Test failed: " <<
|
||||
expression << endl;
|
||||
}
|
||||
|
||||
void failedAssert( const char *file, unsigned line, const char *expression )
|
||||
{
|
||||
stop( file, line ) << "Error: Assertion failed: " <<
|
||||
expression << endl;
|
||||
}
|
||||
|
||||
void failedAssertEquals( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *x, const char *y )
|
||||
{
|
||||
stop( file, line ) << "Error: Expected (" <<
|
||||
xStr << " == " << yStr << "), found (" <<
|
||||
x << " != " << y << ")" << endl;
|
||||
}
|
||||
|
||||
void failedAssertSameData( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *sizeStr, const void *x,
|
||||
const void *y, unsigned size )
|
||||
{
|
||||
stop( file, line ) << "Error: Expected " << sizeStr << " (" << size << ") bytes to be equal at (" <<
|
||||
xStr << ") and (" << yStr << "), found:" << endl;
|
||||
dump( x, size );
|
||||
(*_o) << " differs from" << endl;
|
||||
dump( y, size );
|
||||
}
|
||||
|
||||
void failedAssertDelta( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr, const char *dStr,
|
||||
const char *x, const char *y, const char *d )
|
||||
{
|
||||
stop( file, line ) << "Error: Expected (" <<
|
||||
xStr << " == " << yStr << ") up to " << dStr << " (" << d << "), found (" <<
|
||||
x << " != " << y << ")" << endl;
|
||||
}
|
||||
|
||||
void failedAssertDiffers( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *value )
|
||||
{
|
||||
stop( file, line ) << "Error: Expected (" <<
|
||||
xStr << " != " << yStr << "), found (" <<
|
||||
value << ")" << endl;
|
||||
}
|
||||
|
||||
void failedAssertLessThan( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *x, const char *y )
|
||||
{
|
||||
stop( file, line ) << "Error: Expected (" <<
|
||||
xStr << " < " << yStr << "), found (" <<
|
||||
x << " >= " << y << ")" << endl;
|
||||
}
|
||||
|
||||
void failedAssertLessThanEquals( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *x, const char *y )
|
||||
{
|
||||
stop( file, line ) << "Error: Expected (" <<
|
||||
xStr << " <= " << yStr << "), found (" <<
|
||||
x << " > " << y << ")" << endl;
|
||||
}
|
||||
|
||||
void failedAssertRelation( const char *file, unsigned line,
|
||||
const char *relation, const char *xStr, const char *yStr,
|
||||
const char *x, const char *y )
|
||||
{
|
||||
stop( file, line ) << "Error: Expected " << relation << "( " <<
|
||||
xStr << ", " << yStr << " ), found !" << relation << "( " << x << ", " << y << " )" << endl;
|
||||
}
|
||||
|
||||
void failedAssertPredicate( const char *file, unsigned line,
|
||||
const char *predicate, const char *xStr, const char *x )
|
||||
{
|
||||
stop( file, line ) << "Error: Expected " << predicate << "( " <<
|
||||
xStr << " ), found !" << predicate << "( " << x << " )" << endl;
|
||||
}
|
||||
|
||||
void failedAssertThrows( const char *file, unsigned line,
|
||||
const char *expression, const char *type,
|
||||
bool otherThrown )
|
||||
{
|
||||
stop( file, line ) << "Error: Expected (" << expression << ") to throw (" <<
|
||||
type << ") but it " << (otherThrown ? "threw something else" : "didn't throw") <<
|
||||
endl;
|
||||
}
|
||||
|
||||
void failedAssertThrowsNot( const char *file, unsigned line, const char *expression )
|
||||
{
|
||||
stop( file, line ) << "Error: Expected (" << expression << ") not to throw, but it did" <<
|
||||
endl;
|
||||
}
|
||||
|
||||
protected:
|
||||
OutputStream *outputStream() const
|
||||
{
|
||||
return _o;
|
||||
}
|
||||
|
||||
private:
|
||||
ErrorFormatter( const ErrorFormatter & );
|
||||
ErrorFormatter &operator=( const ErrorFormatter & );
|
||||
|
||||
OutputStream &stop( const char *file, unsigned line )
|
||||
{
|
||||
newLine();
|
||||
reportTest();
|
||||
return (*_o) << file << _preLine << line << _postLine << ": ";
|
||||
}
|
||||
|
||||
void newLine( void )
|
||||
{
|
||||
if ( _dotting ) {
|
||||
(*_o) << endl;
|
||||
_dotting = false;
|
||||
}
|
||||
}
|
||||
|
||||
void reportTest( void )
|
||||
{
|
||||
if( _reported )
|
||||
return;
|
||||
(*_o) << "In " << tracker().suite().suiteName() << "::" << tracker().test().testName() << ":" << endl;
|
||||
_reported = true;
|
||||
}
|
||||
|
||||
void dump( const void *buffer, unsigned size )
|
||||
{
|
||||
if ( !buffer )
|
||||
dumpNull();
|
||||
else
|
||||
dumpBuffer( buffer, size );
|
||||
}
|
||||
|
||||
void dumpNull()
|
||||
{
|
||||
(*_o) << " (null)" << endl;
|
||||
}
|
||||
|
||||
void dumpBuffer( const void *buffer, unsigned size )
|
||||
{
|
||||
unsigned dumpSize = size;
|
||||
if ( maxDumpSize() && dumpSize > maxDumpSize() )
|
||||
dumpSize = maxDumpSize();
|
||||
|
||||
const unsigned char *p = (const unsigned char *)buffer;
|
||||
(*_o) << " { ";
|
||||
for ( unsigned i = 0; i < dumpSize; ++ i )
|
||||
(*_o) << byteToHex( *p++ ) << " ";
|
||||
if ( dumpSize < size )
|
||||
(*_o) << "... ";
|
||||
(*_o) << "}" << endl;
|
||||
}
|
||||
|
||||
static void endl( OutputStream &o )
|
||||
{
|
||||
OutputStream::endl( o );
|
||||
}
|
||||
|
||||
bool _dotting;
|
||||
bool _reported;
|
||||
OutputStream *_o;
|
||||
const char *_preLine;
|
||||
const char *_postLine;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __cxxtest__ErrorFormatter_h__
|
||||
55
test/cxxtest/cxxtest/ErrorPrinter.h
Normal file
55
test/cxxtest/cxxtest/ErrorPrinter.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef __cxxtest__ErrorPrinter_h__
|
||||
#define __cxxtest__ErrorPrinter_h__
|
||||
|
||||
//
|
||||
// The ErrorPrinter is a simple TestListener that
|
||||
// just prints "OK" if everything goes well, otherwise
|
||||
// reports the error in the format of compiler messages.
|
||||
// The ErrorPrinter uses std::cout
|
||||
//
|
||||
|
||||
#include <cxxtest/Flags.h>
|
||||
|
||||
#ifndef _CXXTEST_HAVE_STD
|
||||
# define _CXXTEST_HAVE_STD
|
||||
#endif // _CXXTEST_HAVE_STD
|
||||
|
||||
#include <cxxtest/ErrorFormatter.h>
|
||||
#include <cxxtest/StdValueTraits.h>
|
||||
|
||||
#ifdef _CXXTEST_OLD_STD
|
||||
# include <iostream.h>
|
||||
#else // !_CXXTEST_OLD_STD
|
||||
# include <iostream>
|
||||
#endif // _CXXTEST_OLD_STD
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class ErrorPrinter : public ErrorFormatter
|
||||
{
|
||||
public:
|
||||
ErrorPrinter( CXXTEST_STD(ostream) &o = CXXTEST_STD(cout), const char *preLine = ":", const char *postLine = "" ) :
|
||||
ErrorFormatter( new Adapter(o), preLine, postLine ) {}
|
||||
virtual ~ErrorPrinter() { delete outputStream(); }
|
||||
|
||||
private:
|
||||
class Adapter : public OutputStream
|
||||
{
|
||||
CXXTEST_STD(ostream) &_o;
|
||||
public:
|
||||
Adapter( CXXTEST_STD(ostream) &o ) : _o(o) {}
|
||||
void flush() { _o.flush(); }
|
||||
OutputStream &operator<<( const char *s ) { _o << s; return *this; }
|
||||
OutputStream &operator<<( Manipulator m ) { return OutputStream::operator<<( m ); }
|
||||
OutputStream &operator<<( unsigned i )
|
||||
{
|
||||
char s[1 + 3 * sizeof(unsigned)];
|
||||
numberToString( i, s );
|
||||
_o << s;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __cxxtest__ErrorPrinter_h__
|
||||
121
test/cxxtest/cxxtest/Flags.h
Normal file
121
test/cxxtest/cxxtest/Flags.h
Normal file
@@ -0,0 +1,121 @@
|
||||
#ifndef __cxxtest__Flags_h__
|
||||
#define __cxxtest__Flags_h__
|
||||
|
||||
//
|
||||
// These are the flags that control CxxTest
|
||||
//
|
||||
|
||||
#if !defined(CXXTEST_FLAGS)
|
||||
# define CXXTEST_FLAGS
|
||||
#endif // !CXXTEST_FLAGS
|
||||
|
||||
#if defined(CXXTEST_HAVE_EH) && !defined(_CXXTEST_HAVE_EH)
|
||||
# define _CXXTEST_HAVE_EH
|
||||
#endif // CXXTEST_HAVE_EH
|
||||
|
||||
#if defined(CXXTEST_HAVE_STD) && !defined(_CXXTEST_HAVE_STD)
|
||||
# define _CXXTEST_HAVE_STD
|
||||
#endif // CXXTEST_HAVE_STD
|
||||
|
||||
#if defined(CXXTEST_OLD_TEMPLATE_SYNTAX) && !defined(_CXXTEST_OLD_TEMPLATE_SYNTAX)
|
||||
# define _CXXTEST_OLD_TEMPLATE_SYNTAX
|
||||
#endif // CXXTEST_OLD_TEMPLATE_SYNTAX
|
||||
|
||||
#if defined(CXXTEST_OLD_STD) && !defined(_CXXTEST_OLD_STD)
|
||||
# define _CXXTEST_OLD_STD
|
||||
#endif // CXXTEST_OLD_STD
|
||||
|
||||
#if defined(CXXTEST_ABORT_TEST_ON_FAIL) && !defined(_CXXTEST_ABORT_TEST_ON_FAIL)
|
||||
# define _CXXTEST_ABORT_TEST_ON_FAIL
|
||||
#endif // CXXTEST_ABORT_TEST_ON_FAIL
|
||||
|
||||
#if defined(CXXTEST_NO_COPY_CONST) && !defined(_CXXTEST_NO_COPY_CONST)
|
||||
# define _CXXTEST_NO_COPY_CONST
|
||||
#endif // CXXTEST_NO_COPY_CONST
|
||||
|
||||
#if defined(CXXTEST_FACTOR) && !defined(_CXXTEST_FACTOR)
|
||||
# define _CXXTEST_FACTOR
|
||||
#endif // CXXTEST_FACTOR
|
||||
|
||||
#if defined(CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION) && !defined(_CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION)
|
||||
# define _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
|
||||
#endif // CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
|
||||
|
||||
#if defined(CXXTEST_LONGLONG)
|
||||
# if defined(_CXXTEST_LONGLONG)
|
||||
# undef _CXXTEST_LONGLONG
|
||||
# endif
|
||||
# define _CXXTEST_LONGLONG CXXTEST_LONGLONG
|
||||
#endif // CXXTEST_LONGLONG
|
||||
|
||||
#ifndef CXXTEST_MAX_DUMP_SIZE
|
||||
# define CXXTEST_MAX_DUMP_SIZE 0
|
||||
#endif // CXXTEST_MAX_DUMP_SIZE
|
||||
|
||||
#if defined(_CXXTEST_ABORT_TEST_ON_FAIL) && !defined(CXXTEST_DEFAULT_ABORT)
|
||||
# define CXXTEST_DEFAULT_ABORT true
|
||||
#endif // _CXXTEST_ABORT_TEST_ON_FAIL && !CXXTEST_DEFAULT_ABORT
|
||||
|
||||
#if !defined(CXXTEST_DEFAULT_ABORT)
|
||||
# define CXXTEST_DEFAULT_ABORT false
|
||||
#endif // !CXXTEST_DEFAULT_ABORT
|
||||
|
||||
#if defined(_CXXTEST_ABORT_TEST_ON_FAIL) && !defined(_CXXTEST_HAVE_EH)
|
||||
# warning "CXXTEST_ABORT_TEST_ON_FAIL is meaningless without CXXTEST_HAVE_EH"
|
||||
# undef _CXXTEST_ABORT_TEST_ON_FAIL
|
||||
#endif // _CXXTEST_ABORT_TEST_ON_FAIL && !_CXXTEST_HAVE_EH
|
||||
|
||||
//
|
||||
// Some minimal per-compiler configuration to allow us to compile
|
||||
//
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
# if __BORLANDC__ <= 0x520 // Borland C++ 5.2 or earlier
|
||||
# ifndef _CXXTEST_OLD_STD
|
||||
# define _CXXTEST_OLD_STD
|
||||
# endif
|
||||
# ifndef _CXXTEST_OLD_TEMPLATE_SYNTAX
|
||||
# define _CXXTEST_OLD_TEMPLATE_SYNTAX
|
||||
# endif
|
||||
# endif
|
||||
# if __BORLANDC__ >= 0x540 // C++ Builder 4.0 or later
|
||||
# ifndef _CXXTEST_NO_COPY_CONST
|
||||
# define _CXXTEST_NO_COPY_CONST
|
||||
# endif
|
||||
# ifndef _CXXTEST_LONGLONG
|
||||
# define _CXXTEST_LONGLONG __int64
|
||||
# endif
|
||||
# endif
|
||||
#endif // __BORLANDC__
|
||||
|
||||
#ifdef _MSC_VER // Visual C++
|
||||
# ifndef _CXXTEST_LONGLONG
|
||||
# define _CXXTEST_LONGLONG __int64
|
||||
# endif
|
||||
# if (_MSC_VER >= 0x51E)
|
||||
# ifndef _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
|
||||
# define _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
|
||||
# endif
|
||||
# endif
|
||||
# pragma warning( disable : 4127 )
|
||||
# pragma warning( disable : 4290 )
|
||||
# pragma warning( disable : 4511 )
|
||||
# pragma warning( disable : 4512 )
|
||||
# pragma warning( disable : 4514 )
|
||||
#endif // _MSC_VER
|
||||
|
||||
#ifdef __GNUC__
|
||||
# if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 9)
|
||||
# ifndef _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
|
||||
# define _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
|
||||
# endif
|
||||
# endif
|
||||
#endif // __GNUC__
|
||||
|
||||
#ifdef __DMC__ // Digital Mars
|
||||
# ifndef _CXXTEST_OLD_STD
|
||||
# define _CXXTEST_OLD_STD
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif // __cxxtest__Flags_h__
|
||||
22
test/cxxtest/cxxtest/GlobalFixture.cpp
Normal file
22
test/cxxtest/cxxtest/GlobalFixture.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef __cxxtest__GlobalFixture_cpp__
|
||||
#define __cxxtest__GlobalFixture_cpp__
|
||||
|
||||
#include <cxxtest/GlobalFixture.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
bool GlobalFixture::setUpWorld() { return true; }
|
||||
bool GlobalFixture::tearDownWorld() { return true; }
|
||||
bool GlobalFixture::setUp() { return true; }
|
||||
bool GlobalFixture::tearDown() { return true; }
|
||||
|
||||
GlobalFixture::GlobalFixture() { attach( _list ); }
|
||||
GlobalFixture::~GlobalFixture() { detach( _list ); }
|
||||
|
||||
GlobalFixture *GlobalFixture::firstGlobalFixture() { return (GlobalFixture *)_list.head(); }
|
||||
GlobalFixture *GlobalFixture::lastGlobalFixture() { return (GlobalFixture *)_list.tail(); }
|
||||
GlobalFixture *GlobalFixture::nextGlobalFixture() { return (GlobalFixture *)next(); }
|
||||
GlobalFixture *GlobalFixture::prevGlobalFixture() { return (GlobalFixture *)prev(); }
|
||||
}
|
||||
|
||||
#endif // __cxxtest__GlobalFixture_cpp__
|
||||
29
test/cxxtest/cxxtest/GlobalFixture.h
Normal file
29
test/cxxtest/cxxtest/GlobalFixture.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef __cxxtest__GlobalFixture_h__
|
||||
#define __cxxtest__GlobalFixture_h__
|
||||
|
||||
#include <cxxtest/LinkedList.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class GlobalFixture : public Link
|
||||
{
|
||||
public:
|
||||
virtual bool setUpWorld();
|
||||
virtual bool tearDownWorld();
|
||||
virtual bool setUp();
|
||||
virtual bool tearDown();
|
||||
|
||||
GlobalFixture();
|
||||
~GlobalFixture();
|
||||
|
||||
static GlobalFixture *firstGlobalFixture();
|
||||
static GlobalFixture *lastGlobalFixture();
|
||||
GlobalFixture *nextGlobalFixture();
|
||||
GlobalFixture *prevGlobalFixture();
|
||||
|
||||
private:
|
||||
static List _list;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __cxxtest__GlobalFixture_h__
|
||||
178
test/cxxtest/cxxtest/Gui.h
Normal file
178
test/cxxtest/cxxtest/Gui.h
Normal file
@@ -0,0 +1,178 @@
|
||||
#ifndef __CXXTEST__GUI_H
|
||||
#define __CXXTEST__GUI_H
|
||||
|
||||
//
|
||||
// GuiListener is a simple base class for the differes GUIs
|
||||
// GuiTuiRunner<GuiT, TuiT> combines a GUI with a text-mode error formatter
|
||||
//
|
||||
|
||||
#include <cxxtest/TeeListener.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class GuiListener : public TestListener
|
||||
{
|
||||
public:
|
||||
GuiListener() : _state( GREEN_BAR ) {}
|
||||
virtual ~GuiListener() {}
|
||||
|
||||
virtual void runGui( int &argc, char **argv, TestListener &listener )
|
||||
{
|
||||
enterGui( argc, argv );
|
||||
TestRunner::runAllTests( listener );
|
||||
leaveGui();
|
||||
}
|
||||
|
||||
virtual void enterGui( int & /*argc*/, char ** /*argv*/ ) {}
|
||||
virtual void leaveGui() {}
|
||||
|
||||
//
|
||||
// The easy way is to implement these functions:
|
||||
//
|
||||
virtual void guiEnterWorld( unsigned /*numTotalTests*/ ) {}
|
||||
virtual void guiEnterSuite( const char * /*suiteName*/ ) {}
|
||||
virtual void guiEnterTest( const char * /*suiteName*/, const char * /*testName*/ ) {}
|
||||
virtual void yellowBar() {}
|
||||
virtual void redBar() {}
|
||||
|
||||
//
|
||||
// The hard way is this:
|
||||
//
|
||||
void enterWorld( const WorldDescription &d ) { guiEnterWorld( d.numTotalTests() ); }
|
||||
void enterSuite( const SuiteDescription &d ) { guiEnterSuite( d.suiteName() ); }
|
||||
void enterTest( const TestDescription &d ) { guiEnterTest( d.suiteName(), d.testName() ); }
|
||||
void leaveTest( const TestDescription & ) {}
|
||||
void leaveSuite( const SuiteDescription & ) {}
|
||||
void leaveWorld( const WorldDescription & ) {}
|
||||
|
||||
void warning( const char * /*file*/, unsigned /*line*/, const char * /*expression*/ )
|
||||
{
|
||||
yellowBarSafe();
|
||||
}
|
||||
|
||||
void failedTest( const char * /*file*/, unsigned /*line*/, const char * /*expression*/ )
|
||||
{
|
||||
redBarSafe();
|
||||
}
|
||||
|
||||
void failedAssert( const char * /*file*/, unsigned /*line*/, const char * /*expression*/ )
|
||||
{
|
||||
redBarSafe();
|
||||
}
|
||||
|
||||
void failedAssertEquals( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*xStr*/, const char * /*yStr*/,
|
||||
const char * /*x*/, const char * /*y*/ )
|
||||
{
|
||||
redBarSafe();
|
||||
}
|
||||
|
||||
void failedAssertSameData( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*xStr*/, const char * /*yStr*/,
|
||||
const char * /*sizeStr*/, const void * /*x*/,
|
||||
const void * /*y*/, unsigned /*size*/ )
|
||||
{
|
||||
redBarSafe();
|
||||
}
|
||||
|
||||
void failedAssertDelta( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*xStr*/, const char * /*yStr*/, const char * /*dStr*/,
|
||||
const char * /*x*/, const char * /*y*/, const char * /*d*/ )
|
||||
{
|
||||
redBarSafe();
|
||||
}
|
||||
|
||||
void failedAssertDiffers( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*xStr*/, const char * /*yStr*/,
|
||||
const char * /*value*/ )
|
||||
{
|
||||
redBarSafe();
|
||||
}
|
||||
|
||||
void failedAssertLessThan( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*xStr*/, const char * /*yStr*/,
|
||||
const char * /*x*/, const char * /*y*/ )
|
||||
{
|
||||
redBarSafe();
|
||||
}
|
||||
|
||||
void failedAssertLessThanEquals( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*xStr*/, const char * /*yStr*/,
|
||||
const char * /*x*/, const char * /*y*/ )
|
||||
{
|
||||
redBarSafe();
|
||||
}
|
||||
|
||||
void failedAssertPredicate( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*predicate*/, const char * /*xStr*/, const char * /*x*/ )
|
||||
{
|
||||
redBarSafe();
|
||||
}
|
||||
|
||||
void failedAssertRelation( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*relation*/, const char * /*xStr*/, const char * /*yStr*/,
|
||||
const char * /*x*/, const char * /*y*/ )
|
||||
{
|
||||
redBarSafe();
|
||||
}
|
||||
|
||||
void failedAssertThrows( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*expression*/, const char * /*type*/,
|
||||
bool /*otherThrown*/ )
|
||||
{
|
||||
redBarSafe();
|
||||
}
|
||||
|
||||
void failedAssertThrowsNot( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*expression*/ )
|
||||
{
|
||||
redBarSafe();
|
||||
}
|
||||
|
||||
protected:
|
||||
void yellowBarSafe()
|
||||
{
|
||||
if ( _state < YELLOW_BAR ) {
|
||||
yellowBar();
|
||||
_state = YELLOW_BAR;
|
||||
}
|
||||
}
|
||||
|
||||
void redBarSafe()
|
||||
{
|
||||
if ( _state < RED_BAR ) {
|
||||
redBar();
|
||||
_state = RED_BAR;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
enum { GREEN_BAR, YELLOW_BAR, RED_BAR } _state;
|
||||
};
|
||||
|
||||
template<class GuiT, class TuiT>
|
||||
class GuiTuiRunner : public TeeListener
|
||||
{
|
||||
int &_argc;
|
||||
char **_argv;
|
||||
GuiT _gui;
|
||||
TuiT _tui;
|
||||
|
||||
public:
|
||||
GuiTuiRunner( int &argc, char **argv ) :
|
||||
_argc( argc ),
|
||||
_argv( argv )
|
||||
{
|
||||
setFirst( _gui );
|
||||
setSecond( _tui );
|
||||
}
|
||||
|
||||
int run()
|
||||
{
|
||||
_gui.runGui( _argc, _argv, *this );
|
||||
return tracker().failedTests();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif //__CXXTEST__GUI_H
|
||||
172
test/cxxtest/cxxtest/LinkedList.cpp
Normal file
172
test/cxxtest/cxxtest/LinkedList.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
#ifndef __cxxtest__LinkedList_cpp__
|
||||
#define __cxxtest__LinkedList_cpp__
|
||||
|
||||
#include <cxxtest/LinkedList.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
List GlobalFixture::_list = { 0, 0 };
|
||||
List RealSuiteDescription::_suites = { 0, 0 };
|
||||
|
||||
void List::initialize()
|
||||
{
|
||||
_head = _tail = 0;
|
||||
}
|
||||
|
||||
Link *List::head()
|
||||
{
|
||||
Link *l = _head;
|
||||
while ( l && !l->active() )
|
||||
l = l->next();
|
||||
return l;
|
||||
}
|
||||
|
||||
const Link *List::head() const
|
||||
{
|
||||
Link *l = _head;
|
||||
while ( l && !l->active() )
|
||||
l = l->next();
|
||||
return l;
|
||||
}
|
||||
|
||||
Link *List::tail()
|
||||
{
|
||||
Link *l = _tail;
|
||||
while ( l && !l->active() )
|
||||
l = l->prev();
|
||||
return l;
|
||||
}
|
||||
|
||||
const Link *List::tail() const
|
||||
{
|
||||
Link *l = _tail;
|
||||
while ( l && !l->active() )
|
||||
l = l->prev();
|
||||
return l;
|
||||
}
|
||||
|
||||
bool List::empty() const
|
||||
{
|
||||
return (_head == 0);
|
||||
}
|
||||
|
||||
unsigned List::size() const
|
||||
{
|
||||
unsigned count = 0;
|
||||
for ( const Link *l = head(); l != 0; l = l->next() )
|
||||
++ count;
|
||||
return count;
|
||||
}
|
||||
|
||||
Link *List::nth( unsigned n )
|
||||
{
|
||||
Link *l = head();
|
||||
while ( n -- )
|
||||
l = l->next();
|
||||
return l;
|
||||
}
|
||||
|
||||
void List::activateAll()
|
||||
{
|
||||
for ( Link *l = _head; l != 0; l = l->justNext() )
|
||||
l->setActive( true );
|
||||
}
|
||||
|
||||
void List::leaveOnly( const Link &link )
|
||||
{
|
||||
for ( Link *l = head(); l != 0; l = l->next() )
|
||||
if ( l != &link )
|
||||
l->setActive( false );
|
||||
}
|
||||
|
||||
Link::Link() :
|
||||
_next( 0 ),
|
||||
_prev( 0 ),
|
||||
_active( true )
|
||||
{
|
||||
}
|
||||
|
||||
Link::~Link()
|
||||
{
|
||||
}
|
||||
|
||||
bool Link::active() const
|
||||
{
|
||||
return _active;
|
||||
}
|
||||
|
||||
void Link::setActive( bool value )
|
||||
{
|
||||
_active = value;
|
||||
}
|
||||
|
||||
Link * Link::justNext()
|
||||
{
|
||||
return _next;
|
||||
}
|
||||
|
||||
Link * Link::justPrev()
|
||||
{
|
||||
return _prev;
|
||||
}
|
||||
|
||||
Link * Link::next()
|
||||
{
|
||||
Link *l = _next;
|
||||
while ( l && !l->_active )
|
||||
l = l->_next;
|
||||
return l;
|
||||
}
|
||||
|
||||
Link * Link::prev()
|
||||
{
|
||||
Link *l = _prev;
|
||||
while ( l && !l->_active )
|
||||
l = l->_prev;
|
||||
return l;
|
||||
}
|
||||
|
||||
const Link * Link::next() const
|
||||
{
|
||||
Link *l = _next;
|
||||
while ( l && !l->_active )
|
||||
l = l->_next;
|
||||
return l;
|
||||
}
|
||||
|
||||
const Link * Link::prev() const
|
||||
{
|
||||
Link *l = _prev;
|
||||
while ( l && !l->_active )
|
||||
l = l->_prev;
|
||||
return l;
|
||||
}
|
||||
|
||||
void Link::attach( List &l )
|
||||
{
|
||||
if ( l._tail )
|
||||
l._tail->_next = this;
|
||||
|
||||
_prev = l._tail;
|
||||
_next = 0;
|
||||
|
||||
if ( l._head == 0 )
|
||||
l._head = this;
|
||||
l._tail = this;
|
||||
}
|
||||
|
||||
void Link::detach( List &l )
|
||||
{
|
||||
if ( _prev )
|
||||
_prev->_next = _next;
|
||||
else
|
||||
l._head = _next;
|
||||
|
||||
if ( _next )
|
||||
_next->_prev = _prev;
|
||||
else
|
||||
l._tail = _prev;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __cxxtest__LinkedList_cpp__
|
||||
64
test/cxxtest/cxxtest/LinkedList.h
Normal file
64
test/cxxtest/cxxtest/LinkedList.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef __cxxtest__LinkedList_h__
|
||||
#define __cxxtest__LinkedList_h__
|
||||
|
||||
#include <cxxtest/Flags.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
struct List;
|
||||
class Link;
|
||||
|
||||
struct List
|
||||
{
|
||||
Link *_head;
|
||||
Link *_tail;
|
||||
|
||||
void initialize();
|
||||
|
||||
Link *head();
|
||||
const Link *head() const;
|
||||
Link *tail();
|
||||
const Link *tail() const;
|
||||
|
||||
bool empty() const;
|
||||
unsigned size() const;
|
||||
Link *nth( unsigned n );
|
||||
|
||||
void activateAll();
|
||||
void leaveOnly( const Link &link );
|
||||
};
|
||||
|
||||
class Link
|
||||
{
|
||||
public:
|
||||
Link();
|
||||
virtual ~Link();
|
||||
|
||||
bool active() const;
|
||||
void setActive( bool value = true );
|
||||
|
||||
Link *justNext();
|
||||
Link *justPrev();
|
||||
|
||||
Link *next();
|
||||
Link *prev();
|
||||
const Link *next() const;
|
||||
const Link *prev() const;
|
||||
|
||||
virtual bool setUp() = 0;
|
||||
virtual bool tearDown() = 0;
|
||||
|
||||
void attach( List &l );
|
||||
void detach( List &l );
|
||||
|
||||
private:
|
||||
Link *_next;
|
||||
Link *_prev;
|
||||
bool _active;
|
||||
|
||||
Link( const Link & );
|
||||
Link &operator=( const Link & );
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __cxxtest__LinkedList_h__
|
||||
350
test/cxxtest/cxxtest/Mock.h
Normal file
350
test/cxxtest/cxxtest/Mock.h
Normal file
@@ -0,0 +1,350 @@
|
||||
#ifndef __cxxtest__Mock_h__
|
||||
#define __cxxtest__Mock_h__
|
||||
|
||||
//
|
||||
// The default namespace is T::
|
||||
//
|
||||
#ifndef CXXTEST_MOCK_NAMESPACE
|
||||
# define CXXTEST_MOCK_NAMESPACE T
|
||||
#endif // CXXTEST_MOCK_NAMESPACE
|
||||
|
||||
//
|
||||
// MockTraits: What to return when no mock object has been created
|
||||
//
|
||||
#define __CXXTEST_MOCK__TRAITS \
|
||||
namespace CXXTEST_MOCK_NAMESPACE \
|
||||
{ \
|
||||
template<class T> \
|
||||
class MockTraits \
|
||||
{ \
|
||||
public: \
|
||||
static T defaultValue() { return 0; } \
|
||||
}; \
|
||||
};
|
||||
|
||||
//
|
||||
// extern "C" when needed
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
# define CXXTEST_EXTERN_C extern "C"
|
||||
#else
|
||||
# define CXXTEST_EXTERN_C
|
||||
#endif // __cplusplus
|
||||
|
||||
//
|
||||
// Prototypes: For "normal" headers
|
||||
//
|
||||
#define __CXXTEST_MOCK__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
namespace CXXTEST_MOCK_NAMESPACE { TYPE NAME ARGS; }
|
||||
|
||||
#define __CXXTEST_MOCK_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK__PROTOTYPE( MOCK, void, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#define __CXXTEST_SUPPLY__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
TYPE REAL ARGS;
|
||||
|
||||
#define __CXXTEST_SUPPLY_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_SUPPLY__PROTOTYPE( MOCK, void, NAME, ARGS, REAL, CALL )
|
||||
|
||||
//
|
||||
// Class declarations: For test files
|
||||
//
|
||||
#define __CXXTEST_MOCK__CLASS_DECLARATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
namespace CXXTEST_MOCK_NAMESPACE { \
|
||||
class Base_##MOCK : public CxxTest::Link \
|
||||
{ \
|
||||
public: \
|
||||
Base_##MOCK(); \
|
||||
~Base_##MOCK(); \
|
||||
bool setUp(); \
|
||||
bool tearDown(); \
|
||||
\
|
||||
static Base_##MOCK ¤t(); \
|
||||
\
|
||||
virtual TYPE NAME ARGS = 0; \
|
||||
\
|
||||
private: \
|
||||
static CxxTest::List _list; \
|
||||
}; \
|
||||
\
|
||||
class Real_##MOCK : public Base_##MOCK \
|
||||
{ \
|
||||
public: \
|
||||
TYPE NAME ARGS; \
|
||||
}; \
|
||||
\
|
||||
class _Unimplemented_##MOCK : public Base_##MOCK \
|
||||
{ \
|
||||
public: \
|
||||
TYPE NAME ARGS; \
|
||||
}; \
|
||||
}
|
||||
|
||||
#define __CXXTEST_MOCK_VOID__CLASS_DECLARATION( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK__CLASS_DECLARATION( MOCK, void, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#define __CXXTEST_SUPPLY__CLASS_DECLARATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
namespace CXXTEST_MOCK_NAMESPACE { \
|
||||
class Base_##MOCK : public CxxTest::Link \
|
||||
{ \
|
||||
public: \
|
||||
Base_##MOCK(); \
|
||||
~Base_##MOCK(); \
|
||||
bool setUp(); \
|
||||
bool tearDown(); \
|
||||
\
|
||||
static Base_##MOCK ¤t(); \
|
||||
\
|
||||
virtual TYPE NAME ARGS = 0; \
|
||||
\
|
||||
private: \
|
||||
static CxxTest::List _list; \
|
||||
}; \
|
||||
\
|
||||
class _Unimplemented_##MOCK : public Base_##MOCK \
|
||||
{ \
|
||||
public: \
|
||||
TYPE NAME ARGS; \
|
||||
}; \
|
||||
}
|
||||
|
||||
#define __CXXTEST_SUPPLY_VOID__CLASS_DECLARATION( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_SUPPLY__CLASS_DECLARATION( MOCK, void, NAME, ARGS, REAL, CALL )
|
||||
|
||||
//
|
||||
// Class implementation: For test source files
|
||||
//
|
||||
#define __CXXTEST_MOCK__COMMON_CLASS_IMPLEMENTATION( MOCK, NAME ) \
|
||||
namespace CXXTEST_MOCK_NAMESPACE { \
|
||||
\
|
||||
CxxTest::List Base_##MOCK::_list = { 0, 0 }; \
|
||||
\
|
||||
Base_##MOCK::Base_##MOCK() { attach( _list ); } \
|
||||
Base_##MOCK::~Base_##MOCK() { detach( _list ); } \
|
||||
bool Base_##MOCK::setUp() { return true; } \
|
||||
bool Base_##MOCK::tearDown() { return true; } \
|
||||
\
|
||||
Base_##MOCK &Base_##MOCK::current() \
|
||||
{ \
|
||||
if ( _list.empty() ) \
|
||||
static _Unimplemented_##MOCK unimplemented; \
|
||||
return *(Base_##MOCK *)_list.tail(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define __CXXTEST_MOCK__CLASS_IMPLEMENTATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK__COMMON_CLASS_IMPLEMENTATION( MOCK, NAME ) \
|
||||
namespace CXXTEST_MOCK_NAMESPACE { \
|
||||
TYPE Real_##MOCK::NAME ARGS \
|
||||
{ \
|
||||
return REAL CALL; \
|
||||
} \
|
||||
\
|
||||
TYPE _Unimplemented_##MOCK::NAME ARGS \
|
||||
{ \
|
||||
while ( false ) \
|
||||
return NAME CALL; \
|
||||
__CXXTEST_MOCK_UNIMPLEMENTED( NAME, ARGS ); \
|
||||
return MockTraits<TYPE>::defaultValue(); \
|
||||
} \
|
||||
\
|
||||
TYPE NAME ARGS \
|
||||
{ \
|
||||
return Base_##MOCK::current().NAME CALL; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define __CXXTEST_MOCK_VOID__CLASS_IMPLEMENTATION( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK__COMMON_CLASS_IMPLEMENTATION( MOCK, NAME ) \
|
||||
namespace CXXTEST_MOCK_NAMESPACE { \
|
||||
void Real_##MOCK::NAME ARGS \
|
||||
{ \
|
||||
REAL CALL; \
|
||||
} \
|
||||
\
|
||||
void _Unimplemented_##MOCK::NAME ARGS \
|
||||
{ \
|
||||
while ( false ) \
|
||||
NAME CALL; \
|
||||
__CXXTEST_MOCK_UNIMPLEMENTED( NAME, ARGS ); \
|
||||
} \
|
||||
\
|
||||
void NAME ARGS \
|
||||
{ \
|
||||
Base_##MOCK::current().NAME CALL; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define __CXXTEST_SUPPLY__CLASS_IMPLEMENTATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK__COMMON_CLASS_IMPLEMENTATION( MOCK, NAME ) \
|
||||
namespace CXXTEST_MOCK_NAMESPACE { \
|
||||
TYPE _Unimplemented_##MOCK::NAME ARGS \
|
||||
{ \
|
||||
while ( false ) \
|
||||
return NAME CALL; \
|
||||
__CXXTEST_MOCK_UNIMPLEMENTED( NAME, ARGS ); \
|
||||
return MockTraits<TYPE>::defaultValue(); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
TYPE REAL ARGS \
|
||||
{ \
|
||||
return CXXTEST_MOCK_NAMESPACE::Base_##MOCK::current().NAME CALL; \
|
||||
}
|
||||
|
||||
#define __CXXTEST_SUPPLY_VOID__CLASS_IMPLEMENTATION( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK__COMMON_CLASS_IMPLEMENTATION( MOCK, NAME ) \
|
||||
namespace CXXTEST_MOCK_NAMESPACE { \
|
||||
void _Unimplemented_##MOCK::NAME ARGS \
|
||||
{ \
|
||||
while ( false ) \
|
||||
NAME CALL; \
|
||||
__CXXTEST_MOCK_UNIMPLEMENTED( NAME, ARGS ); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void REAL ARGS \
|
||||
{ \
|
||||
CXXTEST_MOCK_NAMESPACE::Base_##MOCK::current().NAME CALL; \
|
||||
} \
|
||||
|
||||
//
|
||||
// Error for calling mock function w/o object
|
||||
//
|
||||
#define __CXXTEST_MOCK_UNIMPLEMENTED( NAME, ARGS ) \
|
||||
TS_FAIL( CXXTEST_MOCK_NAMESPACE_STR #NAME #ARGS " called with no " \
|
||||
CXXTEST_MOCK_NAMESPACE_STR "Base_" #NAME " object" ); \
|
||||
|
||||
#define CXXTEST_MOCK_NAMESPACE_STR __CXXTEST_STR(CXXTEST_MOCK_NAMESPACE) "::"
|
||||
#define __CXXTEST_STR(X) __CXXTEST_XSTR(X)
|
||||
#define __CXXTEST_XSTR(X) #X
|
||||
|
||||
#if defined(CXXTEST_MOCK_TEST_SOURCE_FILE)
|
||||
//
|
||||
// Test source file: Prototypes, class declarations and implementation
|
||||
//
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
__CXXTEST_MOCK__TRAITS;
|
||||
|
||||
#define CXXTEST_MOCK( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK__CLASS_DECLARATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK__CLASS_IMPLEMENTATION( MOCK, TYPE, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#define CXXTEST_MOCK_VOID( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK_VOID__CLASS_DECLARATION( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK_VOID__CLASS_IMPLEMENTATION( MOCK, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#define CXXTEST_SUPPLY( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_SUPPLY__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_SUPPLY__CLASS_DECLARATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_SUPPLY__CLASS_IMPLEMENTATION( MOCK, TYPE, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#define CXXTEST_SUPPLY_VOID( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_SUPPLY_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_SUPPLY_VOID__CLASS_DECLARATION( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_SUPPLY_VOID__CLASS_IMPLEMENTATION( MOCK, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#elif defined(CXXTEST_FLAGS) || defined(CXXTEST_RUNNING)
|
||||
//
|
||||
// Test file other than source: Prototypes and class declarations
|
||||
//
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
__CXXTEST_MOCK__TRAITS;
|
||||
|
||||
#define CXXTEST_MOCK( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK__CLASS_DECLARATION( MOCK, TYPE, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#define CXXTEST_MOCK_VOID( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK_VOID__CLASS_DECLARATION( MOCK, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#define CXXTEST_SUPPLY( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_SUPPLY__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_SUPPLY__CLASS_DECLARATION( MOCK, TYPE, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#define CXXTEST_SUPPLY_VOID( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_SUPPLY_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_SUPPLY_VOID__CLASS_DECLARATION( MOCK, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#elif defined(CXXTEST_MOCK_REAL_SOURCE_FILE)
|
||||
//
|
||||
// Real source file: "Real" implementations
|
||||
//
|
||||
#define CXXTEST_MOCK( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
namespace CXXTEST_MOCK_NAMESPACE { TYPE NAME ARGS { return REAL CALL; } }
|
||||
|
||||
#define CXXTEST_MOCK_VOID( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
namespace CXXTEST_MOCK_NAMESPACE { void NAME ARGS { REAL CALL; } }
|
||||
|
||||
#else
|
||||
//
|
||||
// Ordinary header file: Just prototypes
|
||||
//
|
||||
|
||||
#define CXXTEST_MOCK( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#define CXXTEST_MOCK_VOID( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_MOCK_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#define CXXTEST_SUPPLY( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_SUPPLY__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#define CXXTEST_SUPPLY_VOID( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
__CXXTEST_SUPPLY_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#endif // Ordinary header file
|
||||
|
||||
//
|
||||
// How to supply extern "C" functions
|
||||
//
|
||||
#define CXXTEST_SUPPLY_C( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
CXXTEST_EXTERN_C __CXXTEST_SUPPLY__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
|
||||
CXXTEST_SUPPLY( MOCK, TYPE, NAME, ARGS, REAL, CALL )
|
||||
|
||||
#define CXXTEST_SUPPLY_VOID_C( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
CXXTEST_EXTERN_C __CXXTEST_SUPPLY_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
|
||||
CXXTEST_SUPPLY_VOID( MOCK, NAME, ARGS, REAL, CALL )
|
||||
|
||||
//
|
||||
// Usually we mean the global namespace
|
||||
//
|
||||
#define CXXTEST_MOCK_GLOBAL( TYPE, NAME, ARGS, CALL ) \
|
||||
CXXTEST_MOCK( NAME, TYPE, NAME, ARGS, ::NAME, CALL )
|
||||
|
||||
#define CXXTEST_MOCK_VOID_GLOBAL( NAME, ARGS, CALL ) \
|
||||
CXXTEST_MOCK_VOID( NAME, NAME, ARGS, ::NAME, CALL )
|
||||
|
||||
#define CXXTEST_SUPPLY_GLOBAL( TYPE, NAME, ARGS, CALL ) \
|
||||
CXXTEST_SUPPLY( NAME, TYPE, NAME, ARGS, NAME, CALL )
|
||||
|
||||
#define CXXTEST_SUPPLY_VOID_GLOBAL( NAME, ARGS, CALL ) \
|
||||
CXXTEST_SUPPLY_VOID( NAME, NAME, ARGS, NAME, CALL )
|
||||
|
||||
#define CXXTEST_SUPPLY_GLOBAL_C( TYPE, NAME, ARGS, CALL ) \
|
||||
CXXTEST_SUPPLY_C( NAME, TYPE, NAME, ARGS, NAME, CALL )
|
||||
|
||||
#define CXXTEST_SUPPLY_VOID_GLOBAL_C( NAME, ARGS, CALL ) \
|
||||
CXXTEST_SUPPLY_VOID_C( NAME, NAME, ARGS, NAME, CALL )
|
||||
|
||||
//
|
||||
// What to return when no mock object has been created.
|
||||
// The default value of 0 usually works, but some cases may need this.
|
||||
//
|
||||
#define CXXTEST_MOCK_DEFAULT_VALUE( TYPE, VALUE ) \
|
||||
namespace CXXTEST_MOCK_NAMESPACE \
|
||||
{ \
|
||||
template<> \
|
||||
class MockTraits<TYPE> \
|
||||
{ \
|
||||
public: \
|
||||
static TYPE defaultValue() { return VALUE; } \
|
||||
}; \
|
||||
}
|
||||
|
||||
#endif // __cxxtest__Mock_h__
|
||||
21
test/cxxtest/cxxtest/ParenPrinter.h
Normal file
21
test/cxxtest/cxxtest/ParenPrinter.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef __cxxtest__ParenPrinter_h__
|
||||
#define __cxxtest__ParenPrinter_h__
|
||||
|
||||
//
|
||||
// The ParenPrinter is identical to the ErrorPrinter, except it
|
||||
// prints the line number in a format expected by some compilers
|
||||
// (notably, MSVC).
|
||||
//
|
||||
|
||||
#include <cxxtest/ErrorPrinter.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class ParenPrinter : public ErrorPrinter
|
||||
{
|
||||
public:
|
||||
ParenPrinter( CXXTEST_STD(ostream) &o = CXXTEST_STD(cout) ) : ErrorPrinter( o, "(", ")" ) {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __cxxtest__ParenPrinter_h__
|
||||
271
test/cxxtest/cxxtest/QtGui.h
Normal file
271
test/cxxtest/cxxtest/QtGui.h
Normal file
@@ -0,0 +1,271 @@
|
||||
#ifndef __cxxtest__QtGui_h__
|
||||
#define __cxxtest__QtGui_h__
|
||||
|
||||
//
|
||||
// The QtGui displays a simple progress bar using the Qt Toolkit. It
|
||||
// has been tested with versions 2.x and 3.x.
|
||||
//
|
||||
// Apart from normal Qt command-line arguments, it accepts the following options:
|
||||
// -minimized Start minimized, pop up on error
|
||||
// -keep Don't close the window at the end
|
||||
// -title TITLE Set the window caption
|
||||
//
|
||||
// If both are -minimized and -keep specified, GUI will only keep the
|
||||
// window if it's in focus.
|
||||
//
|
||||
|
||||
#include <cxxtest/Gui.h>
|
||||
|
||||
#include <qapplication.h>
|
||||
#include <qglobal.h>
|
||||
#include <qlabel.h>
|
||||
#include <qlayout.h>
|
||||
#include <qmessagebox.h>
|
||||
#include <qpixmap.h>
|
||||
#include <qprogressbar.h>
|
||||
#include <qstatusbar.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class QtGui : public GuiListener
|
||||
{
|
||||
public:
|
||||
void enterGui( int &argc, char **argv )
|
||||
{
|
||||
parseCommandLine( argc, argv );
|
||||
createApplication( argc, argv );
|
||||
}
|
||||
|
||||
void enterWorld( const WorldDescription &wd )
|
||||
{
|
||||
createWindow( wd );
|
||||
processEvents();
|
||||
}
|
||||
|
||||
void guiEnterSuite( const char *suiteName )
|
||||
{
|
||||
showSuiteName( suiteName );
|
||||
}
|
||||
|
||||
void guiEnterTest( const char *suiteName, const char *testName )
|
||||
{
|
||||
setCaption( suiteName, testName );
|
||||
advanceProgressBar();
|
||||
showTestName( testName );
|
||||
showTestsDone( _progressBar->progress() );
|
||||
processEvents();
|
||||
}
|
||||
|
||||
void yellowBar()
|
||||
{
|
||||
setColor( 255, 255, 0 );
|
||||
setIcon( QMessageBox::Warning );
|
||||
getTotalTests();
|
||||
processEvents();
|
||||
}
|
||||
|
||||
void redBar()
|
||||
{
|
||||
if ( _startMinimized && _mainWindow->isMinimized() )
|
||||
showNormal();
|
||||
setColor( 255, 0, 0 );
|
||||
setIcon( QMessageBox::Critical );
|
||||
getTotalTests();
|
||||
processEvents();
|
||||
}
|
||||
|
||||
void leaveGui()
|
||||
{
|
||||
if ( keep() ) {
|
||||
showSummary();
|
||||
_application->exec();
|
||||
}
|
||||
else
|
||||
_mainWindow->close( true );
|
||||
}
|
||||
|
||||
private:
|
||||
QString _title;
|
||||
bool _startMinimized, _keep;
|
||||
unsigned _numTotalTests;
|
||||
QString _strTotalTests;
|
||||
QApplication *_application;
|
||||
QWidget *_mainWindow;
|
||||
QVBoxLayout *_layout;
|
||||
QProgressBar *_progressBar;
|
||||
QStatusBar *_statusBar;
|
||||
QLabel *_suiteName, *_testName, *_testsDone;
|
||||
|
||||
void parseCommandLine( int argc, char **argv )
|
||||
{
|
||||
_startMinimized = _keep = false;
|
||||
_title = argv[0];
|
||||
|
||||
for ( int i = 1; i < argc; ++ i ) {
|
||||
QString arg( argv[i] );
|
||||
if ( arg == "-minimized" )
|
||||
_startMinimized = true;
|
||||
else if ( arg == "-keep" )
|
||||
_keep = true;
|
||||
else if ( arg == "-title" && (i + 1 < argc) )
|
||||
_title = argv[++i];
|
||||
}
|
||||
}
|
||||
|
||||
void createApplication( int &argc, char **argv )
|
||||
{
|
||||
_application = new QApplication( argc, argv );
|
||||
}
|
||||
|
||||
void createWindow( const WorldDescription &wd )
|
||||
{
|
||||
getTotalTests( wd );
|
||||
createMainWindow();
|
||||
createProgressBar();
|
||||
createStatusBar();
|
||||
setMainWidget();
|
||||
if ( _startMinimized )
|
||||
showMinimized();
|
||||
else
|
||||
showNormal();
|
||||
}
|
||||
|
||||
void getTotalTests()
|
||||
{
|
||||
getTotalTests( tracker().world() );
|
||||
}
|
||||
|
||||
void getTotalTests( const WorldDescription &wd )
|
||||
{
|
||||
_numTotalTests = wd.numTotalTests();
|
||||
char s[WorldDescription::MAX_STRLEN_TOTAL_TESTS];
|
||||
_strTotalTests = wd.strTotalTests( s );
|
||||
}
|
||||
|
||||
void createMainWindow()
|
||||
{
|
||||
_mainWindow = new QWidget();
|
||||
_layout = new QVBoxLayout( _mainWindow );
|
||||
}
|
||||
|
||||
void createProgressBar()
|
||||
{
|
||||
_layout->addWidget( _progressBar = new QProgressBar( _numTotalTests, _mainWindow ) );
|
||||
_progressBar->setProgress( 0 );
|
||||
setColor( 0, 255, 0 );
|
||||
setIcon( QMessageBox::Information );
|
||||
}
|
||||
|
||||
void createStatusBar()
|
||||
{
|
||||
_layout->addWidget( _statusBar = new QStatusBar( _mainWindow ) );
|
||||
_statusBar->addWidget( _suiteName = new QLabel( _statusBar ), 2 );
|
||||
_statusBar->addWidget( _testName = new QLabel( _statusBar ), 4 );
|
||||
_statusBar->addWidget( _testsDone = new QLabel( _statusBar ), 1 );
|
||||
}
|
||||
|
||||
void setMainWidget()
|
||||
{
|
||||
_application->setMainWidget( _mainWindow );
|
||||
}
|
||||
|
||||
void showMinimized()
|
||||
{
|
||||
_mainWindow->showMinimized();
|
||||
}
|
||||
|
||||
void showNormal()
|
||||
{
|
||||
_mainWindow->showNormal();
|
||||
centerWindow();
|
||||
}
|
||||
|
||||
void setCaption( const QString &suiteName, const QString &testName )
|
||||
{
|
||||
_mainWindow->setCaption( _title + " - " + suiteName + "::" + testName + "()" );
|
||||
}
|
||||
|
||||
void showSuiteName( const QString &suiteName )
|
||||
{
|
||||
_suiteName->setText( "class " + suiteName );
|
||||
}
|
||||
|
||||
void advanceProgressBar()
|
||||
{
|
||||
_progressBar->setProgress( _progressBar->progress() + 1 );
|
||||
}
|
||||
|
||||
void showTestName( const QString &testName )
|
||||
{
|
||||
_testName->setText( testName + "()" );
|
||||
}
|
||||
|
||||
void showTestsDone( unsigned testsDone )
|
||||
{
|
||||
_testsDone->setText( asString( testsDone ) + " of " + _strTotalTests );
|
||||
}
|
||||
|
||||
static QString asString( unsigned n )
|
||||
{
|
||||
return QString::number( n );
|
||||
}
|
||||
|
||||
void setColor( int r, int g, int b )
|
||||
{
|
||||
QPalette palette = _progressBar->palette();
|
||||
palette.setColor( QColorGroup::Highlight, QColor( r, g, b ) );
|
||||
_progressBar->setPalette( palette );
|
||||
}
|
||||
|
||||
void setIcon( QMessageBox::Icon icon )
|
||||
{
|
||||
#if QT_VERSION >= 0x030000
|
||||
_mainWindow->setIcon( QMessageBox::standardIcon( icon ) );
|
||||
#else // Qt version < 3.0.0
|
||||
_mainWindow->setIcon( QMessageBox::standardIcon( icon, QApplication::style().guiStyle() ) );
|
||||
#endif // QT_VERSION
|
||||
}
|
||||
|
||||
void processEvents()
|
||||
{
|
||||
_application->processEvents();
|
||||
}
|
||||
|
||||
void centerWindow()
|
||||
{
|
||||
QWidget *desktop = QApplication::desktop();
|
||||
int xCenter = desktop->x() + (desktop->width() / 2);
|
||||
int yCenter = desktop->y() + (desktop->height() / 2);
|
||||
|
||||
int windowWidth = (desktop->width() * 4) / 5;
|
||||
int windowHeight = _mainWindow->height();
|
||||
_mainWindow->setGeometry( xCenter - (windowWidth / 2), yCenter - (windowHeight / 2), windowWidth, windowHeight );
|
||||
}
|
||||
|
||||
bool keep()
|
||||
{
|
||||
if ( !_keep )
|
||||
return false;
|
||||
if ( !_startMinimized )
|
||||
return true;
|
||||
return (_mainWindow == _application->activeWindow());
|
||||
}
|
||||
|
||||
void showSummary()
|
||||
{
|
||||
QString summary = _strTotalTests + (_numTotalTests == 1 ? " test" : " tests");
|
||||
if ( tracker().failedTests() )
|
||||
summary = "Failed " + asString( tracker().failedTests() ) + " of " + summary;
|
||||
else
|
||||
summary = summary + " passed";
|
||||
|
||||
_mainWindow->setCaption( _title + " - " + summary );
|
||||
|
||||
_statusBar->removeWidget( _suiteName );
|
||||
_statusBar->removeWidget( _testName );
|
||||
_testsDone->setText( summary );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __cxxtest__QtGui_h__
|
||||
310
test/cxxtest/cxxtest/RealDescriptions.cpp
Normal file
310
test/cxxtest/cxxtest/RealDescriptions.cpp
Normal file
@@ -0,0 +1,310 @@
|
||||
#ifndef __cxxtest__RealDescriptions_cpp__
|
||||
#define __cxxtest__RealDescriptions_cpp__
|
||||
|
||||
//
|
||||
// NOTE: If an error occur during world construction/deletion, CxxTest cannot
|
||||
// know where the error originated.
|
||||
//
|
||||
|
||||
#include <cxxtest/RealDescriptions.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
RealTestDescription::RealTestDescription()
|
||||
{
|
||||
}
|
||||
|
||||
RealTestDescription::RealTestDescription( List &argList,
|
||||
SuiteDescription &argSuite,
|
||||
unsigned argLine,
|
||||
const char *argTestName )
|
||||
{
|
||||
initialize( argList, argSuite, argLine, argTestName );
|
||||
}
|
||||
|
||||
void RealTestDescription::initialize( List &argList,
|
||||
SuiteDescription &argSuite,
|
||||
unsigned argLine,
|
||||
const char *argTestName )
|
||||
{
|
||||
_suite = &argSuite;
|
||||
_line = argLine;
|
||||
_testName = argTestName;
|
||||
attach( argList );
|
||||
}
|
||||
|
||||
bool RealTestDescription::setUp()
|
||||
{
|
||||
if ( !suite() )
|
||||
return false;
|
||||
|
||||
for ( GlobalFixture *gf = GlobalFixture::firstGlobalFixture(); gf != 0; gf = gf->nextGlobalFixture() ) {
|
||||
bool ok;
|
||||
_TS_TRY { ok = gf->setUp(); }
|
||||
_TS_LAST_CATCH( { ok = false; } );
|
||||
|
||||
if ( !ok ) {
|
||||
doFailTest( file(), line(), "Error in GlobalFixture::setUp()" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_TS_TRY {
|
||||
_TSM_ASSERT_THROWS_NOTHING( file(), line(), "Exception thrown from setUp()", suite()->setUp() );
|
||||
}
|
||||
_TS_CATCH_ABORT( { return false; } );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RealTestDescription::tearDown()
|
||||
{
|
||||
if ( !suite() )
|
||||
return false;
|
||||
|
||||
_TS_TRY {
|
||||
_TSM_ASSERT_THROWS_NOTHING( file(), line(), "Exception thrown from tearDown()", suite()->tearDown() );
|
||||
}
|
||||
_TS_CATCH_ABORT( { return false; } );
|
||||
|
||||
for ( GlobalFixture *gf = GlobalFixture::lastGlobalFixture(); gf != 0; gf = gf->prevGlobalFixture() ) {
|
||||
bool ok;
|
||||
_TS_TRY { ok = gf->tearDown(); }
|
||||
_TS_LAST_CATCH( { ok = false; } );
|
||||
|
||||
if ( !ok ) {
|
||||
doFailTest( file(), line(), "Error in GlobalFixture::tearDown()" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *RealTestDescription::file() const { return _suite->file(); }
|
||||
unsigned RealTestDescription::line() const { return _line; }
|
||||
const char *RealTestDescription::testName() const { return _testName; }
|
||||
const char *RealTestDescription::suiteName() const { return _suite->suiteName(); }
|
||||
|
||||
TestDescription *RealTestDescription::next() { return (RealTestDescription *)Link::next(); }
|
||||
const TestDescription *RealTestDescription::next() const { return (const RealTestDescription *)Link::next(); }
|
||||
|
||||
TestSuite *RealTestDescription::suite() const { return _suite->suite(); }
|
||||
|
||||
void RealTestDescription::run()
|
||||
{
|
||||
_TS_TRY { runTest(); }
|
||||
_TS_CATCH_ABORT( {} )
|
||||
___TSM_CATCH( file(), line(), "Exception thrown from test" );
|
||||
}
|
||||
|
||||
RealSuiteDescription::RealSuiteDescription() {}
|
||||
RealSuiteDescription::RealSuiteDescription( const char *argFile,
|
||||
unsigned argLine,
|
||||
const char *argSuiteName,
|
||||
List &argTests )
|
||||
{
|
||||
initialize( argFile, argLine, argSuiteName, argTests );
|
||||
}
|
||||
|
||||
void RealSuiteDescription::initialize( const char *argFile,
|
||||
unsigned argLine,
|
||||
const char *argSuiteName,
|
||||
List &argTests )
|
||||
{
|
||||
_file = argFile;
|
||||
_line = argLine;
|
||||
_suiteName = argSuiteName;
|
||||
_tests = &argTests;
|
||||
|
||||
attach( _suites );
|
||||
}
|
||||
|
||||
const char *RealSuiteDescription::file() const { return _file; }
|
||||
unsigned RealSuiteDescription::line() const { return _line; }
|
||||
const char *RealSuiteDescription::suiteName() const { return _suiteName; }
|
||||
|
||||
TestDescription *RealSuiteDescription::firstTest() { return (RealTestDescription *)_tests->head(); }
|
||||
const TestDescription *RealSuiteDescription::firstTest() const { return (const RealTestDescription *)_tests->head(); }
|
||||
SuiteDescription *RealSuiteDescription::next() { return (RealSuiteDescription *)Link::next(); }
|
||||
const SuiteDescription *RealSuiteDescription::next() const { return (const RealSuiteDescription *)Link::next(); }
|
||||
|
||||
unsigned RealSuiteDescription::numTests() const { return _tests->size(); }
|
||||
|
||||
const TestDescription &RealSuiteDescription::testDescription( unsigned i ) const
|
||||
{
|
||||
return *(RealTestDescription *)_tests->nth( i );
|
||||
}
|
||||
|
||||
void RealSuiteDescription::activateAllTests()
|
||||
{
|
||||
_tests->activateAll();
|
||||
}
|
||||
|
||||
bool RealSuiteDescription::leaveOnly( const char *testName )
|
||||
{
|
||||
for ( TestDescription *td = firstTest(); td != 0; td = td->next() ) {
|
||||
if ( stringsEqual( td->testName(), testName ) ) {
|
||||
_tests->leaveOnly( *td );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
StaticSuiteDescription::StaticSuiteDescription() {}
|
||||
StaticSuiteDescription::StaticSuiteDescription( const char *argFile, unsigned argLine,
|
||||
const char *argSuiteName, TestSuite &argSuite,
|
||||
List &argTests ) :
|
||||
RealSuiteDescription( argFile, argLine, argSuiteName, argTests )
|
||||
{
|
||||
doInitialize( argSuite );
|
||||
}
|
||||
|
||||
void StaticSuiteDescription::initialize( const char *argFile, unsigned argLine,
|
||||
const char *argSuiteName, TestSuite &argSuite,
|
||||
List &argTests )
|
||||
{
|
||||
RealSuiteDescription::initialize( argFile, argLine, argSuiteName, argTests );
|
||||
doInitialize( argSuite );
|
||||
}
|
||||
|
||||
void StaticSuiteDescription::doInitialize( TestSuite &argSuite )
|
||||
{
|
||||
_suite = &argSuite;
|
||||
}
|
||||
|
||||
TestSuite *StaticSuiteDescription::suite() const
|
||||
{
|
||||
return _suite;
|
||||
}
|
||||
|
||||
bool StaticSuiteDescription::setUp() { return true; }
|
||||
bool StaticSuiteDescription::tearDown() { return true; }
|
||||
|
||||
CommonDynamicSuiteDescription::CommonDynamicSuiteDescription() {}
|
||||
CommonDynamicSuiteDescription::CommonDynamicSuiteDescription( const char *argFile, unsigned argLine,
|
||||
const char *argSuiteName, List &argTests,
|
||||
unsigned argCreateLine, unsigned argDestroyLine ) :
|
||||
RealSuiteDescription( argFile, argLine, argSuiteName, argTests )
|
||||
{
|
||||
doInitialize( argCreateLine, argDestroyLine );
|
||||
}
|
||||
|
||||
void CommonDynamicSuiteDescription::initialize( const char *argFile, unsigned argLine,
|
||||
const char *argSuiteName, List &argTests,
|
||||
unsigned argCreateLine, unsigned argDestroyLine )
|
||||
{
|
||||
RealSuiteDescription::initialize( argFile, argLine, argSuiteName, argTests );
|
||||
doInitialize( argCreateLine, argDestroyLine );
|
||||
}
|
||||
|
||||
void CommonDynamicSuiteDescription::doInitialize( unsigned argCreateLine, unsigned argDestroyLine )
|
||||
{
|
||||
_createLine = argCreateLine;
|
||||
_destroyLine = argDestroyLine;
|
||||
}
|
||||
|
||||
List &RealWorldDescription::suites()
|
||||
{
|
||||
return RealSuiteDescription::_suites;
|
||||
}
|
||||
|
||||
unsigned RealWorldDescription::numSuites( void ) const
|
||||
{
|
||||
return suites().size();
|
||||
}
|
||||
|
||||
unsigned RealWorldDescription::numTotalTests( void ) const
|
||||
{
|
||||
unsigned count = 0;
|
||||
for ( const SuiteDescription *sd = firstSuite(); sd != 0; sd = sd->next() )
|
||||
count += sd->numTests();
|
||||
return count;
|
||||
}
|
||||
|
||||
SuiteDescription *RealWorldDescription::firstSuite()
|
||||
{
|
||||
return (RealSuiteDescription *)suites().head();
|
||||
}
|
||||
|
||||
const SuiteDescription *RealWorldDescription::firstSuite() const
|
||||
{
|
||||
return (const RealSuiteDescription *)suites().head();
|
||||
}
|
||||
|
||||
const SuiteDescription &RealWorldDescription::suiteDescription( unsigned i ) const
|
||||
{
|
||||
return *(const RealSuiteDescription *)suites().nth( i );
|
||||
}
|
||||
|
||||
void RealWorldDescription::activateAllTests()
|
||||
{
|
||||
suites().activateAll();
|
||||
for ( SuiteDescription *sd = firstSuite(); sd != 0; sd = sd->next() )
|
||||
sd->activateAllTests();
|
||||
}
|
||||
|
||||
bool RealWorldDescription::leaveOnly( const char *suiteName, const char *testName )
|
||||
{
|
||||
for ( SuiteDescription *sd = firstSuite(); sd != 0; sd = sd->next() ) {
|
||||
if ( stringsEqual( sd->suiteName(), suiteName ) ) {
|
||||
if ( testName )
|
||||
if ( !sd->leaveOnly( testName ) )
|
||||
return false;
|
||||
suites().leaveOnly( *sd );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RealWorldDescription::setUp()
|
||||
{
|
||||
for ( GlobalFixture *gf = GlobalFixture::firstGlobalFixture(); gf != 0; gf = gf->nextGlobalFixture() ) {
|
||||
bool ok;
|
||||
_TS_TRY { ok = gf->setUpWorld(); }
|
||||
_TS_LAST_CATCH( { ok = false; } );
|
||||
|
||||
if ( !ok ) {
|
||||
reportError( "Error setting up world" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RealWorldDescription::tearDown()
|
||||
{
|
||||
for ( GlobalFixture *gf = GlobalFixture::lastGlobalFixture(); gf != 0; gf = gf->prevGlobalFixture() ) {
|
||||
bool ok;
|
||||
_TS_TRY { ok = gf->tearDownWorld(); }
|
||||
_TS_LAST_CATCH( { ok = false; } );
|
||||
|
||||
if ( !ok ) {
|
||||
reportError( "Error tearing down world" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RealWorldDescription::reportError( const char *message )
|
||||
{
|
||||
doWarn( __FILE__, 5, message );
|
||||
}
|
||||
|
||||
void activateAllTests()
|
||||
{
|
||||
RealWorldDescription().activateAllTests();
|
||||
}
|
||||
|
||||
bool leaveOnly( const char *suiteName, const char *testName )
|
||||
{
|
||||
return RealWorldDescription().leaveOnly( suiteName, testName );
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __cxxtest__RealDescriptions_cpp__
|
||||
222
test/cxxtest/cxxtest/RealDescriptions.h
Normal file
222
test/cxxtest/cxxtest/RealDescriptions.h
Normal file
@@ -0,0 +1,222 @@
|
||||
#ifndef __cxxtest__RealDescriptions_h__
|
||||
#define __cxxtest__RealDescriptions_h__
|
||||
|
||||
//
|
||||
// The "real" description classes
|
||||
//
|
||||
|
||||
#include <cxxtest/Descriptions.h>
|
||||
#include <cxxtest/TestSuite.h>
|
||||
#include <cxxtest/GlobalFixture.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class RealTestDescription : public TestDescription
|
||||
{
|
||||
public:
|
||||
RealTestDescription();
|
||||
RealTestDescription( List &argList, SuiteDescription &argSuite, unsigned argLine, const char *argTestName );
|
||||
void initialize( List &argList, SuiteDescription &argSuite, unsigned argLine, const char *argTestName );
|
||||
|
||||
const char *file() const;
|
||||
unsigned line() const;
|
||||
const char *testName() const;
|
||||
const char *suiteName() const;
|
||||
|
||||
TestDescription *next();
|
||||
const TestDescription *next() const;
|
||||
|
||||
TestSuite *suite() const;
|
||||
|
||||
bool setUp();
|
||||
void run();
|
||||
bool tearDown();
|
||||
|
||||
private:
|
||||
RealTestDescription( const RealTestDescription & );
|
||||
RealTestDescription &operator=( const RealTestDescription & );
|
||||
|
||||
virtual void runTest() = 0;
|
||||
|
||||
SuiteDescription *_suite;
|
||||
unsigned _line;
|
||||
const char *_testName;
|
||||
};
|
||||
|
||||
class RealSuiteDescription : public SuiteDescription
|
||||
{
|
||||
public:
|
||||
RealSuiteDescription();
|
||||
RealSuiteDescription( const char *argFile, unsigned argLine, const char *argSuiteName, List &argTests );
|
||||
|
||||
void initialize( const char *argFile, unsigned argLine, const char *argSuiteName, List &argTests );
|
||||
|
||||
const char *file() const;
|
||||
unsigned line() const;
|
||||
const char *suiteName() const;
|
||||
|
||||
TestDescription *firstTest();
|
||||
const TestDescription *firstTest() const;
|
||||
SuiteDescription *next();
|
||||
const SuiteDescription *next() const;
|
||||
|
||||
unsigned numTests() const;
|
||||
const TestDescription &testDescription( unsigned i ) const;
|
||||
|
||||
void activateAllTests();
|
||||
bool leaveOnly( const char *testName );
|
||||
|
||||
private:
|
||||
RealSuiteDescription( const RealSuiteDescription & );
|
||||
RealSuiteDescription &operator=( const RealSuiteDescription & );
|
||||
|
||||
const char *_file;
|
||||
unsigned _line;
|
||||
const char *_suiteName;
|
||||
List *_tests;
|
||||
|
||||
static List _suites;
|
||||
friend class RealWorldDescription;
|
||||
};
|
||||
|
||||
class StaticSuiteDescription : public RealSuiteDescription
|
||||
{
|
||||
public:
|
||||
StaticSuiteDescription();
|
||||
StaticSuiteDescription( const char *argFile, unsigned argLine,
|
||||
const char *argSuiteName, TestSuite &argSuite,
|
||||
List &argTests );
|
||||
|
||||
void initialize( const char *argFile, unsigned argLine,
|
||||
const char *argSuiteName, TestSuite &argSuite,
|
||||
List &argTests );
|
||||
TestSuite *suite() const;
|
||||
|
||||
bool setUp();
|
||||
bool tearDown();
|
||||
|
||||
private:
|
||||
StaticSuiteDescription( const StaticSuiteDescription & );
|
||||
StaticSuiteDescription &operator=( const StaticSuiteDescription & );
|
||||
|
||||
void doInitialize( TestSuite &argSuite );
|
||||
|
||||
TestSuite *_suite;
|
||||
};
|
||||
|
||||
class CommonDynamicSuiteDescription : public RealSuiteDescription
|
||||
{
|
||||
public:
|
||||
CommonDynamicSuiteDescription();
|
||||
CommonDynamicSuiteDescription( const char *argFile, unsigned argLine,
|
||||
const char *argSuiteName, List &argTests,
|
||||
unsigned argCreateLine, unsigned argDestroyLine );
|
||||
|
||||
void initialize( const char *argFile, unsigned argLine,
|
||||
const char *argSuiteName, List &argTests,
|
||||
unsigned argCreateLine, unsigned argDestroyLine );
|
||||
|
||||
protected:
|
||||
unsigned _createLine, _destroyLine;
|
||||
|
||||
private:
|
||||
void doInitialize( unsigned argCreateLine, unsigned argDestroyLine );
|
||||
};
|
||||
|
||||
template<class S>
|
||||
class DynamicSuiteDescription : public CommonDynamicSuiteDescription
|
||||
{
|
||||
public:
|
||||
DynamicSuiteDescription() {}
|
||||
DynamicSuiteDescription( const char *argFile, unsigned argLine,
|
||||
const char *argSuiteName, List &argTests,
|
||||
S *&argSuite, unsigned argCreateLine,
|
||||
unsigned argDestroyLine ) :
|
||||
CommonDynamicSuiteDescription( argFile, argLine, argSuiteName, argTests, argCreateLine, argDestroyLine )
|
||||
{
|
||||
_suite = &argSuite;
|
||||
}
|
||||
|
||||
void initialize( const char *argFile, unsigned argLine,
|
||||
const char *argSuiteName, List &argTests,
|
||||
S *&argSuite, unsigned argCreateLine,
|
||||
unsigned argDestroyLine )
|
||||
{
|
||||
CommonDynamicSuiteDescription::initialize( argFile, argLine,
|
||||
argSuiteName, argTests,
|
||||
argCreateLine, argDestroyLine );
|
||||
_suite = &argSuite;
|
||||
}
|
||||
|
||||
TestSuite *suite() const { return realSuite(); }
|
||||
|
||||
bool setUp();
|
||||
bool tearDown();
|
||||
|
||||
private:
|
||||
S *realSuite() const { return *_suite; }
|
||||
void setSuite( S *s ) { *_suite = s; }
|
||||
|
||||
void createSuite()
|
||||
{
|
||||
setSuite( S::createSuite() );
|
||||
}
|
||||
|
||||
void destroySuite()
|
||||
{
|
||||
S *s = realSuite();
|
||||
setSuite( 0 );
|
||||
S::destroySuite( s );
|
||||
}
|
||||
|
||||
S **_suite;
|
||||
};
|
||||
|
||||
template<class S>
|
||||
bool DynamicSuiteDescription<S>::setUp()
|
||||
{
|
||||
_TS_TRY {
|
||||
_TSM_ASSERT_THROWS_NOTHING( file(), _createLine, "Exception thrown from createSuite()", createSuite() );
|
||||
_TSM_ASSERT( file(), _createLine, "createSuite() failed", suite() != 0 );
|
||||
}
|
||||
_TS_CATCH_ABORT( { return false; } );
|
||||
|
||||
return (suite() != 0);
|
||||
}
|
||||
|
||||
template<class S>
|
||||
bool DynamicSuiteDescription<S>::tearDown()
|
||||
{
|
||||
if ( !_suite )
|
||||
return true;
|
||||
|
||||
_TS_TRY {
|
||||
_TSM_ASSERT_THROWS_NOTHING( file(), _destroyLine, "destroySuite() failed", destroySuite() );
|
||||
}
|
||||
_TS_CATCH_ABORT( { return false; } );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class RealWorldDescription : public WorldDescription
|
||||
{
|
||||
public:
|
||||
static List &suites();
|
||||
unsigned numSuites( void ) const;
|
||||
unsigned numTotalTests( void ) const;
|
||||
SuiteDescription *firstSuite();
|
||||
const SuiteDescription *firstSuite() const;
|
||||
const SuiteDescription &suiteDescription( unsigned i ) const;
|
||||
void activateAllTests();
|
||||
bool leaveOnly( const char *suiteName, const char *testName = 0 );
|
||||
|
||||
bool setUp();
|
||||
bool tearDown();
|
||||
static void reportError( const char *message );
|
||||
};
|
||||
|
||||
void activateAllTests();
|
||||
bool leaveOnly( const char *suiteName, const char *testName = 0 );
|
||||
}
|
||||
|
||||
#endif // __cxxtest__RealDescriptions_h__
|
||||
18
test/cxxtest/cxxtest/Root.cpp
Normal file
18
test/cxxtest/cxxtest/Root.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef __cxxtest__Root_cpp__
|
||||
#define __cxxtest__Root_cpp__
|
||||
|
||||
//
|
||||
// This file holds the "root" of CxxTest, i.e.
|
||||
// the parts that must be in a source file file.
|
||||
//
|
||||
|
||||
#include <cxxtest/Descriptions.cpp>
|
||||
#include <cxxtest/DummyDescriptions.cpp>
|
||||
#include <cxxtest/GlobalFixture.cpp>
|
||||
#include <cxxtest/LinkedList.cpp>
|
||||
#include <cxxtest/RealDescriptions.cpp>
|
||||
#include <cxxtest/TestSuite.cpp>
|
||||
#include <cxxtest/TestTracker.cpp>
|
||||
#include <cxxtest/ValueTraits.cpp>
|
||||
|
||||
#endif // __cxxtest__Root_cpp__
|
||||
7
test/cxxtest/cxxtest/SelfTest.h
Normal file
7
test/cxxtest/cxxtest/SelfTest.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef __cxxtest_SelfTest_h__
|
||||
#define __cxxtest_SelfTest_h__
|
||||
|
||||
#define CXXTEST_SUITE(name)
|
||||
#define CXXTEST_CODE(member)
|
||||
|
||||
#endif // __cxxtest_SelfTest_h__
|
||||
25
test/cxxtest/cxxtest/StdHeaders.h
Normal file
25
test/cxxtest/cxxtest/StdHeaders.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef __cxxtest_StdHeaders_h__
|
||||
#define __cxxtest_StdHeaders_h__
|
||||
|
||||
//
|
||||
// This file basically #includes the STL headers.
|
||||
// It exists to support warning level 4 in Visual C++
|
||||
//
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning( push, 1 )
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <complex>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning( pop )
|
||||
#endif // _MSC_VER
|
||||
|
||||
#endif // __cxxtest_StdHeaders_h__
|
||||
229
test/cxxtest/cxxtest/StdValueTraits.h
Normal file
229
test/cxxtest/cxxtest/StdValueTraits.h
Normal file
@@ -0,0 +1,229 @@
|
||||
#ifndef __cxxtest_StdValueTraits_h__
|
||||
#define __cxxtest_StdValueTraits_h__
|
||||
|
||||
//
|
||||
// This file defines ValueTraits for std:: stuff.
|
||||
// It is #included by <cxxtest/ValueTraits.h> if you
|
||||
// define CXXTEST_HAVE_STD
|
||||
//
|
||||
|
||||
#include <cxxtest/ValueTraits.h>
|
||||
#include <cxxtest/StdHeaders.h>
|
||||
|
||||
#ifdef _CXXTEST_OLD_STD
|
||||
# define CXXTEST_STD(x) x
|
||||
#else // !_CXXTEST_OLD_STD
|
||||
# define CXXTEST_STD(x) std::x
|
||||
#endif // _CXXTEST_OLD_STD
|
||||
|
||||
#ifndef CXXTEST_USER_VALUE_TRAITS
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
//
|
||||
// NOTE: This should have been
|
||||
// template<class Char, class Traits, class Allocator>
|
||||
// class ValueTraits< std::basic_string<Char, Traits, Allocator> > {};
|
||||
// But MSVC doesn't support it (yet).
|
||||
//
|
||||
|
||||
//
|
||||
// If we have std::string, we might as well use it
|
||||
//
|
||||
class StdTraitsBase
|
||||
{
|
||||
public:
|
||||
StdTraitsBase &operator<<( const CXXTEST_STD(string) &s ) { _s += s; return *this; }
|
||||
const char *asString() const { return _s.c_str(); }
|
||||
|
||||
private:
|
||||
CXXTEST_STD(string) _s;
|
||||
};
|
||||
|
||||
//
|
||||
// std::string
|
||||
//
|
||||
CXXTEST_TEMPLATE_INSTANTIATION
|
||||
class ValueTraits<const CXXTEST_STD(string)> : public StdTraitsBase
|
||||
{
|
||||
public:
|
||||
ValueTraits( const CXXTEST_STD(string) &s )
|
||||
{
|
||||
*this << "\"";
|
||||
for ( unsigned i = 0; i < s.length(); ++ i ) {
|
||||
char c[sizeof("\\xXX")];
|
||||
charToString( s[i], c );
|
||||
*this << c;
|
||||
}
|
||||
*this << "\"";
|
||||
}
|
||||
};
|
||||
|
||||
CXXTEST_COPY_CONST_TRAITS( CXXTEST_STD(string) );
|
||||
|
||||
#ifndef _CXXTEST_OLD_STD
|
||||
//
|
||||
// std::wstring
|
||||
//
|
||||
CXXTEST_TEMPLATE_INSTANTIATION
|
||||
class ValueTraits<const CXXTEST_STD(basic_string<wchar_t>)> : public StdTraitsBase
|
||||
{
|
||||
public:
|
||||
ValueTraits( const CXXTEST_STD(basic_string<wchar_t>) &s )
|
||||
{
|
||||
*this << "L\"";
|
||||
for ( unsigned i = 0; i < s.length(); ++ i ) {
|
||||
char c[sizeof("\\x12345678")];
|
||||
charToString( (unsigned long)s[i], c );
|
||||
*this << c;
|
||||
}
|
||||
*this << "\"";
|
||||
}
|
||||
};
|
||||
|
||||
CXXTEST_COPY_CONST_TRAITS( CXXTEST_STD(basic_string<wchar_t>) );
|
||||
#endif // _CXXTEST_OLD_STD
|
||||
|
||||
//
|
||||
// Convert a range defined by iterators to a string
|
||||
// This is useful for almost all STL containers
|
||||
//
|
||||
template<class Stream, class Iterator>
|
||||
void dumpRange( Stream &s, Iterator first, Iterator last )
|
||||
{
|
||||
s << "{ ";
|
||||
while ( first != last ) {
|
||||
s << TS_AS_STRING(*first);
|
||||
++ first;
|
||||
s << ((first == last) ? " }" : ", ");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
|
||||
//
|
||||
// std::pair
|
||||
//
|
||||
template<class First, class Second>
|
||||
class ValueTraits< CXXTEST_STD(pair)<First, Second> > : public StdTraitsBase
|
||||
{
|
||||
public:
|
||||
ValueTraits( const CXXTEST_STD(pair)<First, Second> &p )
|
||||
{
|
||||
*this << "<" << TS_AS_STRING( p.first ) << ", " << TS_AS_STRING( p.second ) << ">";
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// std::vector
|
||||
//
|
||||
template<class Element>
|
||||
class ValueTraits< CXXTEST_STD(vector)<Element> > : public StdTraitsBase
|
||||
{
|
||||
public:
|
||||
ValueTraits( const CXXTEST_STD(vector)<Element> &v )
|
||||
{
|
||||
dumpRange( *this, v.begin(), v.end() );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// std::list
|
||||
//
|
||||
template<class Element>
|
||||
class ValueTraits< CXXTEST_STD(list)<Element> > : public StdTraitsBase
|
||||
{
|
||||
public:
|
||||
ValueTraits( const CXXTEST_STD(list)<Element> &l )
|
||||
{
|
||||
dumpRange( *this, l.begin(), l.end() );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// std::set
|
||||
//
|
||||
template<class Element>
|
||||
class ValueTraits< CXXTEST_STD(set)<Element> > : public StdTraitsBase
|
||||
{
|
||||
public:
|
||||
ValueTraits( const CXXTEST_STD(set)<Element> &s )
|
||||
{
|
||||
dumpRange( *this, s.begin(), s.end() );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// std::map
|
||||
//
|
||||
template<class Key, class Value>
|
||||
class ValueTraits< CXXTEST_STD(map)<Key, Value> > : public StdTraitsBase
|
||||
{
|
||||
public:
|
||||
ValueTraits( const CXXTEST_STD(map)<Key, Value> &m )
|
||||
{
|
||||
dumpRange( *this, m.begin(), m.end() );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// std::deque
|
||||
//
|
||||
template<class Element>
|
||||
class ValueTraits< CXXTEST_STD(deque)<Element> > : public StdTraitsBase
|
||||
{
|
||||
public:
|
||||
ValueTraits( const CXXTEST_STD(deque)<Element> &d )
|
||||
{
|
||||
dumpRange( *this, d.begin(), d.end() );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// std::multiset
|
||||
//
|
||||
template<class Element>
|
||||
class ValueTraits< CXXTEST_STD(multiset)<Element> > : public StdTraitsBase
|
||||
{
|
||||
public:
|
||||
ValueTraits( const CXXTEST_STD(multiset)<Element> &ms )
|
||||
{
|
||||
dumpRange( *this, ms.begin(), ms.end() );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// std::multimap
|
||||
//
|
||||
template<class Key, class Value>
|
||||
class ValueTraits< CXXTEST_STD(multimap)<Key, Value> > : public StdTraitsBase
|
||||
{
|
||||
public:
|
||||
ValueTraits( const CXXTEST_STD(multimap)<Key, Value> &mm )
|
||||
{
|
||||
dumpRange( *this, mm.begin(), mm.end() );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// std::complex
|
||||
//
|
||||
template<class Number>
|
||||
class ValueTraits< CXXTEST_STD(complex)<Number> > : public StdTraitsBase
|
||||
{
|
||||
public:
|
||||
ValueTraits( const CXXTEST_STD(complex)<Number> &c )
|
||||
{
|
||||
if ( !c.imag() )
|
||||
*this << TS_AS_STRING(c.real());
|
||||
else if ( !c.real() )
|
||||
*this << "(" << TS_AS_STRING(c.imag()) << " * i)";
|
||||
else
|
||||
*this << "(" << TS_AS_STRING(c.real()) << " + " << TS_AS_STRING(c.imag()) << " * i)";
|
||||
}
|
||||
};
|
||||
#endif // _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
|
||||
}
|
||||
|
||||
#endif // CXXTEST_USER_VALUE_TRAITS
|
||||
|
||||
#endif // __cxxtest_StdValueTraits_h__
|
||||
41
test/cxxtest/cxxtest/StdioFilePrinter.h
Normal file
41
test/cxxtest/cxxtest/StdioFilePrinter.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef __cxxtest__StdioFilePrinter_h__
|
||||
#define __cxxtest__StdioFilePrinter_h__
|
||||
|
||||
//
|
||||
// The StdioFilePrinter is a simple TestListener that
|
||||
// just prints "OK" if everything goes well, otherwise
|
||||
// reports the error in the format of compiler messages.
|
||||
// This class uses <stdio.h>, i.e. FILE * and fprintf().
|
||||
//
|
||||
|
||||
#include <cxxtest/ErrorFormatter.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class StdioFilePrinter : public ErrorFormatter
|
||||
{
|
||||
public:
|
||||
StdioFilePrinter( FILE *o, const char *preLine = ":", const char *postLine = "" ) :
|
||||
ErrorFormatter( new Adapter(o), preLine, postLine ) {}
|
||||
virtual ~StdioFilePrinter() { delete outputStream(); }
|
||||
|
||||
private:
|
||||
class Adapter : public OutputStream
|
||||
{
|
||||
Adapter( const Adapter & );
|
||||
Adapter &operator=( const Adapter & );
|
||||
|
||||
FILE *_o;
|
||||
|
||||
public:
|
||||
Adapter( FILE *o ) : _o(o) {}
|
||||
void flush() { fflush( _o ); }
|
||||
OutputStream &operator<<( unsigned i ) { fprintf( _o, "%u", i ); return *this; }
|
||||
OutputStream &operator<<( const char *s ) { fputs( s, _o ); return *this; }
|
||||
OutputStream &operator<<( Manipulator m ) { return OutputStream::operator<<( m ); }
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __cxxtest__StdioFilePrinter_h__
|
||||
22
test/cxxtest/cxxtest/StdioPrinter.h
Normal file
22
test/cxxtest/cxxtest/StdioPrinter.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef __cxxtest__StdioPrinter_h__
|
||||
#define __cxxtest__StdioPrinter_h__
|
||||
|
||||
//
|
||||
// The StdioPrinter is an StdioFilePrinter which defaults to stdout.
|
||||
// This should have been called StdOutPrinter or something, but the name
|
||||
// has been historically used.
|
||||
//
|
||||
|
||||
#include <cxxtest/StdioFilePrinter.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class StdioPrinter : public StdioFilePrinter
|
||||
{
|
||||
public:
|
||||
StdioPrinter( FILE *o = stdout, const char *preLine = ":", const char *postLine = "" ) :
|
||||
StdioFilePrinter( o, preLine, postLine ) {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __cxxtest__StdioPrinter_h__
|
||||
181
test/cxxtest/cxxtest/TeeListener.h
Normal file
181
test/cxxtest/cxxtest/TeeListener.h
Normal file
@@ -0,0 +1,181 @@
|
||||
#ifndef __cxxtest__TeeListener_h__
|
||||
#define __cxxtest__TeeListener_h__
|
||||
|
||||
//
|
||||
// A TeeListener notifies two "reular" TestListeners
|
||||
//
|
||||
|
||||
#include <cxxtest/TestListener.h>
|
||||
#include <cxxtest/TestListener.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class TeeListener : public TestListener
|
||||
{
|
||||
public:
|
||||
TeeListener()
|
||||
{
|
||||
setFirst( _dummy );
|
||||
setSecond( _dummy );
|
||||
}
|
||||
|
||||
virtual ~TeeListener()
|
||||
{
|
||||
}
|
||||
|
||||
void setFirst( TestListener &first )
|
||||
{
|
||||
_first = &first;
|
||||
}
|
||||
|
||||
void setSecond( TestListener &second )
|
||||
{
|
||||
_second = &second;
|
||||
}
|
||||
|
||||
void enterWorld( const WorldDescription &d )
|
||||
{
|
||||
_first->enterWorld( d );
|
||||
_second->enterWorld( d );
|
||||
}
|
||||
|
||||
void enterSuite( const SuiteDescription &d )
|
||||
{
|
||||
_first->enterSuite( d );
|
||||
_second->enterSuite( d );
|
||||
}
|
||||
|
||||
void enterTest( const TestDescription &d )
|
||||
{
|
||||
_first->enterTest( d );
|
||||
_second->enterTest( d );
|
||||
}
|
||||
|
||||
void trace( const char *file, unsigned line, const char *expression )
|
||||
{
|
||||
_first->trace( file, line, expression );
|
||||
_second->trace( file, line, expression );
|
||||
}
|
||||
|
||||
void warning( const char *file, unsigned line, const char *expression )
|
||||
{
|
||||
_first->warning( file, line, expression );
|
||||
_second->warning( file, line, expression );
|
||||
}
|
||||
|
||||
void failedTest( const char *file, unsigned line, const char *expression )
|
||||
{
|
||||
_first->failedTest( file, line, expression );
|
||||
_second->failedTest( file, line, expression );
|
||||
}
|
||||
|
||||
void failedAssert( const char *file, unsigned line, const char *expression )
|
||||
{
|
||||
_first->failedAssert( file, line, expression );
|
||||
_second->failedAssert( file, line, expression );
|
||||
}
|
||||
|
||||
void failedAssertEquals( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *x, const char *y )
|
||||
{
|
||||
_first->failedAssertEquals( file, line, xStr, yStr, x, y );
|
||||
_second->failedAssertEquals( file, line, xStr, yStr, x, y );
|
||||
}
|
||||
|
||||
void failedAssertSameData( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *sizeStr, const void *x,
|
||||
const void *y, unsigned size )
|
||||
{
|
||||
_first->failedAssertSameData( file, line, xStr, yStr, sizeStr, x, y, size );
|
||||
_second->failedAssertSameData( file, line, xStr, yStr, sizeStr, x, y, size );
|
||||
}
|
||||
|
||||
void failedAssertDelta( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr, const char *dStr,
|
||||
const char *x, const char *y, const char *d )
|
||||
{
|
||||
_first->failedAssertDelta( file, line, xStr, yStr, dStr, x, y, d );
|
||||
_second->failedAssertDelta( file, line, xStr, yStr, dStr, x, y, d );
|
||||
}
|
||||
|
||||
void failedAssertDiffers( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *value )
|
||||
{
|
||||
_first->failedAssertDiffers( file, line, xStr, yStr, value );
|
||||
_second->failedAssertDiffers( file, line, xStr, yStr, value );
|
||||
}
|
||||
|
||||
void failedAssertLessThan( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *x, const char *y )
|
||||
{
|
||||
_first->failedAssertLessThan( file, line, xStr, yStr, x, y );
|
||||
_second->failedAssertLessThan( file, line, xStr, yStr, x, y );
|
||||
}
|
||||
|
||||
void failedAssertLessThanEquals( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *x, const char *y )
|
||||
{
|
||||
_first->failedAssertLessThanEquals( file, line, xStr, yStr, x, y );
|
||||
_second->failedAssertLessThanEquals( file, line, xStr, yStr, x, y );
|
||||
}
|
||||
|
||||
void failedAssertPredicate( const char *file, unsigned line,
|
||||
const char *predicate, const char *xStr, const char *x )
|
||||
{
|
||||
_first->failedAssertPredicate( file, line, predicate, xStr, x );
|
||||
_second->failedAssertPredicate( file, line, predicate, xStr, x );
|
||||
}
|
||||
|
||||
void failedAssertRelation( const char *file, unsigned line,
|
||||
const char *relation, const char *xStr, const char *yStr,
|
||||
const char *x, const char *y )
|
||||
{
|
||||
_first->failedAssertRelation( file, line, relation, xStr, yStr, x, y );
|
||||
_second->failedAssertRelation( file, line, relation, xStr, yStr, x, y );
|
||||
}
|
||||
|
||||
void failedAssertThrows( const char *file, unsigned line,
|
||||
const char *expression, const char *type,
|
||||
bool otherThrown )
|
||||
{
|
||||
_first->failedAssertThrows( file, line, expression, type, otherThrown );
|
||||
_second->failedAssertThrows( file, line, expression, type, otherThrown );
|
||||
}
|
||||
|
||||
void failedAssertThrowsNot( const char *file, unsigned line,
|
||||
const char *expression )
|
||||
{
|
||||
_first->failedAssertThrowsNot( file, line, expression );
|
||||
_second->failedAssertThrowsNot( file, line, expression );
|
||||
}
|
||||
|
||||
void leaveTest( const TestDescription &d )
|
||||
{
|
||||
_first->leaveTest(d);
|
||||
_second->leaveTest(d);
|
||||
}
|
||||
|
||||
void leaveSuite( const SuiteDescription &d )
|
||||
{
|
||||
_first->leaveSuite(d);
|
||||
_second->leaveSuite(d);
|
||||
}
|
||||
|
||||
void leaveWorld( const WorldDescription &d )
|
||||
{
|
||||
_first->leaveWorld(d);
|
||||
_second->leaveWorld(d);
|
||||
}
|
||||
|
||||
private:
|
||||
TestListener *_first, *_second;
|
||||
TestListener _dummy;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __cxxtest__TeeListener_h__
|
||||
70
test/cxxtest/cxxtest/TestListener.h
Normal file
70
test/cxxtest/cxxtest/TestListener.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#ifndef __cxxtest__TestListener_h__
|
||||
#define __cxxtest__TestListener_h__
|
||||
|
||||
//
|
||||
// TestListener is the base class for all "listeners",
|
||||
// i.e. classes that receive notifications of the
|
||||
// testing process.
|
||||
//
|
||||
// The names of the parameters are in comments to avoid
|
||||
// "unused parameter" warnings.
|
||||
//
|
||||
|
||||
#include <cxxtest/Descriptions.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class TestListener
|
||||
{
|
||||
public:
|
||||
TestListener() {}
|
||||
virtual ~TestListener() {}
|
||||
|
||||
virtual void enterWorld( const WorldDescription & /*desc*/ ) {}
|
||||
virtual void enterSuite( const SuiteDescription & /*desc*/ ) {}
|
||||
virtual void enterTest( const TestDescription & /*desc*/ ) {}
|
||||
virtual void trace( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*expression*/ ) {}
|
||||
virtual void warning( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*expression*/ ) {}
|
||||
virtual void failedTest( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*expression*/ ) {}
|
||||
virtual void failedAssert( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*expression*/ ) {}
|
||||
virtual void failedAssertEquals( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*xStr*/, const char * /*yStr*/,
|
||||
const char * /*x*/, const char * /*y*/ ) {}
|
||||
virtual void failedAssertSameData( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*xStr*/, const char * /*yStr*/,
|
||||
const char * /*sizeStr*/, const void * /*x*/,
|
||||
const void * /*y*/, unsigned /*size*/ ) {}
|
||||
virtual void failedAssertDelta( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*xStr*/, const char * /*yStr*/,
|
||||
const char * /*dStr*/, const char * /*x*/,
|
||||
const char * /*y*/, const char * /*d*/ ) {}
|
||||
virtual void failedAssertDiffers( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*xStr*/, const char * /*yStr*/,
|
||||
const char * /*value*/ ) {}
|
||||
virtual void failedAssertLessThan( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*xStr*/, const char * /*yStr*/,
|
||||
const char * /*x*/, const char * /*y*/ ) {}
|
||||
virtual void failedAssertLessThanEquals( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*xStr*/, const char * /*yStr*/,
|
||||
const char * /*x*/, const char * /*y*/ ) {}
|
||||
virtual void failedAssertPredicate( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*predicate*/, const char * /*xStr*/, const char * /*x*/ ) {}
|
||||
virtual void failedAssertRelation( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*relation*/, const char * /*xStr*/, const char * /*yStr*/,
|
||||
const char * /*x*/, const char * /*y*/ ) {}
|
||||
virtual void failedAssertThrows( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*expression*/, const char * /*type*/,
|
||||
bool /*otherThrown*/ ) {}
|
||||
virtual void failedAssertThrowsNot( const char * /*file*/, unsigned /*line*/,
|
||||
const char * /*expression*/ ) {}
|
||||
virtual void leaveTest( const TestDescription & /*desc*/ ) {}
|
||||
virtual void leaveSuite( const SuiteDescription & /*desc*/ ) {}
|
||||
virtual void leaveWorld( const WorldDescription & /*desc*/ ) {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __cxxtest__TestListener_h__
|
||||
125
test/cxxtest/cxxtest/TestRunner.h
Normal file
125
test/cxxtest/cxxtest/TestRunner.h
Normal file
@@ -0,0 +1,125 @@
|
||||
#ifndef __cxxtest_TestRunner_h__
|
||||
#define __cxxtest_TestRunner_h__
|
||||
|
||||
//
|
||||
// TestRunner is the class that runs all the tests.
|
||||
// To use it, create an object that implements the TestListener
|
||||
// interface and call TestRunner::runAllTests( myListener );
|
||||
//
|
||||
|
||||
#include <cxxtest/TestListener.h>
|
||||
#include <cxxtest/RealDescriptions.h>
|
||||
#include <cxxtest/TestSuite.h>
|
||||
#include <cxxtest/TestTracker.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class TestRunner
|
||||
{
|
||||
public:
|
||||
static void runAllTests( TestListener &listener )
|
||||
{
|
||||
tracker().setListener( &listener );
|
||||
_TS_TRY { TestRunner().runWorld(); }
|
||||
_TS_LAST_CATCH( { tracker().failedTest( __FILE__, __LINE__, "Exception thrown from world" ); } );
|
||||
tracker().setListener( 0 );
|
||||
}
|
||||
|
||||
static void runAllTests( TestListener *listener )
|
||||
{
|
||||
if ( listener ) {
|
||||
listener->warning( __FILE__, __LINE__, "Deprecated; Use runAllTests( TestListener & )" );
|
||||
runAllTests( *listener );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void runWorld()
|
||||
{
|
||||
RealWorldDescription wd;
|
||||
WorldGuard sg;
|
||||
|
||||
tracker().enterWorld( wd );
|
||||
if ( wd.setUp() ) {
|
||||
for ( SuiteDescription *sd = wd.firstSuite(); sd; sd = sd->next() )
|
||||
if ( sd->active() )
|
||||
runSuite( *sd );
|
||||
|
||||
wd.tearDown();
|
||||
}
|
||||
tracker().leaveWorld( wd );
|
||||
}
|
||||
|
||||
void runSuite( SuiteDescription &sd )
|
||||
{
|
||||
StateGuard sg;
|
||||
|
||||
tracker().enterSuite( sd );
|
||||
if ( sd.setUp() ) {
|
||||
for ( TestDescription *td = sd.firstTest(); td; td = td->next() )
|
||||
if ( td->active() )
|
||||
runTest( *td );
|
||||
|
||||
sd.tearDown();
|
||||
}
|
||||
tracker().leaveSuite( sd );
|
||||
}
|
||||
|
||||
void runTest( TestDescription &td )
|
||||
{
|
||||
StateGuard sg;
|
||||
|
||||
tracker().enterTest( td );
|
||||
if ( td.setUp() ) {
|
||||
td.run();
|
||||
td.tearDown();
|
||||
}
|
||||
tracker().leaveTest( td );
|
||||
}
|
||||
|
||||
class StateGuard
|
||||
{
|
||||
#ifdef _CXXTEST_HAVE_EH
|
||||
bool _abortTestOnFail;
|
||||
#endif // _CXXTEST_HAVE_EH
|
||||
unsigned _maxDumpSize;
|
||||
|
||||
public:
|
||||
StateGuard()
|
||||
{
|
||||
#ifdef _CXXTEST_HAVE_EH
|
||||
_abortTestOnFail = abortTestOnFail();
|
||||
#endif // _CXXTEST_HAVE_EH
|
||||
_maxDumpSize = maxDumpSize();
|
||||
}
|
||||
|
||||
~StateGuard()
|
||||
{
|
||||
#ifdef _CXXTEST_HAVE_EH
|
||||
setAbortTestOnFail( _abortTestOnFail );
|
||||
#endif // _CXXTEST_HAVE_EH
|
||||
setMaxDumpSize( _maxDumpSize );
|
||||
}
|
||||
};
|
||||
|
||||
class WorldGuard : public StateGuard
|
||||
{
|
||||
public:
|
||||
WorldGuard() : StateGuard()
|
||||
{
|
||||
#ifdef _CXXTEST_HAVE_EH
|
||||
setAbortTestOnFail( CXXTEST_DEFAULT_ABORT );
|
||||
#endif // _CXXTEST_HAVE_EH
|
||||
setMaxDumpSize( CXXTEST_MAX_DUMP_SIZE );
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
//
|
||||
// For --no-static-init
|
||||
//
|
||||
void initialize();
|
||||
}
|
||||
|
||||
|
||||
#endif // __cxxtest_TestRunner_h__
|
||||
138
test/cxxtest/cxxtest/TestSuite.cpp
Normal file
138
test/cxxtest/cxxtest/TestSuite.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
#ifndef __cxxtest__TestSuite_cpp__
|
||||
#define __cxxtest__TestSuite_cpp__
|
||||
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
//
|
||||
// TestSuite members
|
||||
//
|
||||
TestSuite::~TestSuite() {}
|
||||
void TestSuite::setUp() {}
|
||||
void TestSuite::tearDown() {}
|
||||
|
||||
//
|
||||
// Test-aborting stuff
|
||||
//
|
||||
static bool currentAbortTestOnFail = false;
|
||||
|
||||
bool abortTestOnFail()
|
||||
{
|
||||
return currentAbortTestOnFail;
|
||||
}
|
||||
|
||||
void setAbortTestOnFail( bool value )
|
||||
{
|
||||
currentAbortTestOnFail = value;
|
||||
}
|
||||
|
||||
void doAbortTest()
|
||||
{
|
||||
# if defined(_CXXTEST_HAVE_EH)
|
||||
if ( currentAbortTestOnFail )
|
||||
throw AbortTest();
|
||||
# endif // _CXXTEST_HAVE_EH
|
||||
}
|
||||
|
||||
//
|
||||
// Max dump size
|
||||
//
|
||||
static unsigned currentMaxDumpSize = CXXTEST_MAX_DUMP_SIZE;
|
||||
|
||||
unsigned maxDumpSize()
|
||||
{
|
||||
return currentMaxDumpSize;
|
||||
}
|
||||
|
||||
void setMaxDumpSize( unsigned value )
|
||||
{
|
||||
currentMaxDumpSize = value;
|
||||
}
|
||||
|
||||
//
|
||||
// Some non-template functions
|
||||
//
|
||||
void doTrace( const char *file, unsigned line, const char *message )
|
||||
{
|
||||
tracker().trace( file, line, message );
|
||||
}
|
||||
|
||||
void doWarn( const char *file, unsigned line, const char *message )
|
||||
{
|
||||
tracker().warning( file, line, message );
|
||||
}
|
||||
|
||||
void doFailTest( const char *file, unsigned line, const char *message )
|
||||
{
|
||||
tracker().failedTest( file, line, message );
|
||||
TS_ABORT();
|
||||
}
|
||||
|
||||
void doFailAssert( const char *file, unsigned line,
|
||||
const char *expression, const char *message )
|
||||
{
|
||||
if ( message )
|
||||
tracker().failedTest( file, line, message );
|
||||
tracker().failedAssert( file, line, expression );
|
||||
TS_ABORT();
|
||||
}
|
||||
|
||||
bool sameData( const void *x, const void *y, unsigned size )
|
||||
{
|
||||
if ( size == 0 )
|
||||
return true;
|
||||
|
||||
if ( x == y )
|
||||
return true;
|
||||
|
||||
if ( !x || !y )
|
||||
return false;
|
||||
|
||||
const char *cx = (const char *)x;
|
||||
const char *cy = (const char *)y;
|
||||
while ( size -- )
|
||||
if ( *cx++ != *cy++ )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void doAssertSameData( const char *file, unsigned line,
|
||||
const char *xExpr, const void *x,
|
||||
const char *yExpr, const void *y,
|
||||
const char *sizeExpr, unsigned size,
|
||||
const char *message )
|
||||
{
|
||||
if ( !sameData( x, y, size ) ) {
|
||||
if ( message )
|
||||
tracker().failedTest( file, line, message );
|
||||
tracker().failedAssertSameData( file, line, xExpr, yExpr, sizeExpr, x, y, size );
|
||||
TS_ABORT();
|
||||
}
|
||||
}
|
||||
|
||||
void doFailAssertThrows( const char *file, unsigned line,
|
||||
const char *expr, const char *type,
|
||||
bool otherThrown,
|
||||
const char *message )
|
||||
{
|
||||
if ( message )
|
||||
tracker().failedTest( file, line, message );
|
||||
|
||||
tracker().failedAssertThrows( file, line, expr, type, otherThrown );
|
||||
TS_ABORT();
|
||||
}
|
||||
|
||||
void doFailAssertThrowsNot( const char *file, unsigned line,
|
||||
const char *expression, const char *message )
|
||||
{
|
||||
if ( message )
|
||||
tracker().failedTest( file, line, message );
|
||||
|
||||
tracker().failedAssertThrowsNot( file, line, expression );
|
||||
TS_ABORT();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __cxxtest__TestSuite_cpp__
|
||||
518
test/cxxtest/cxxtest/TestSuite.h
Normal file
518
test/cxxtest/cxxtest/TestSuite.h
Normal file
@@ -0,0 +1,518 @@
|
||||
#ifndef __cxxtest__TestSuite_h__
|
||||
#define __cxxtest__TestSuite_h__
|
||||
|
||||
//
|
||||
// class TestSuite is the base class for all test suites.
|
||||
// To define a test suite, derive from this class and add
|
||||
// member functions called void test*();
|
||||
//
|
||||
|
||||
#include <cxxtest/Flags.h>
|
||||
#include <cxxtest/TestTracker.h>
|
||||
#include <cxxtest/Descriptions.h>
|
||||
#include <cxxtest/ValueTraits.h>
|
||||
|
||||
#ifdef _CXXTEST_HAVE_STD
|
||||
# include <stdexcept>
|
||||
#endif // _CXXTEST_HAVE_STD
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class TestSuite
|
||||
{
|
||||
public:
|
||||
virtual ~TestSuite();
|
||||
virtual void setUp();
|
||||
virtual void tearDown();
|
||||
};
|
||||
|
||||
class AbortTest {};
|
||||
void doAbortTest();
|
||||
# define TS_ABORT() CxxTest::doAbortTest()
|
||||
|
||||
bool abortTestOnFail();
|
||||
void setAbortTestOnFail( bool value = CXXTEST_DEFAULT_ABORT );
|
||||
|
||||
unsigned maxDumpSize();
|
||||
void setMaxDumpSize( unsigned value = CXXTEST_MAX_DUMP_SIZE );
|
||||
|
||||
void doTrace( const char *file, unsigned line, const char *message );
|
||||
void doWarn( const char *file, unsigned line, const char *message );
|
||||
void doFailTest( const char *file, unsigned line, const char *message );
|
||||
void doFailAssert( const char *file, unsigned line, const char *expression, const char *message );
|
||||
|
||||
template<class X, class Y>
|
||||
bool equals( X x, Y y )
|
||||
{
|
||||
return (x == y);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool equals<bool, int>(bool x, int y)
|
||||
{
|
||||
return (x == (bool)y);
|
||||
}
|
||||
|
||||
template<class X, class Y>
|
||||
void doAssertEquals( const char *file, unsigned line,
|
||||
const char *xExpr, X x,
|
||||
const char *yExpr, Y y,
|
||||
const char *message )
|
||||
{
|
||||
if ( !equals( x, y ) ) {
|
||||
if ( message )
|
||||
tracker().failedTest( file, line, message );
|
||||
tracker().failedAssertEquals( file, line, xExpr, yExpr, TS_AS_STRING(x), TS_AS_STRING(y) );
|
||||
TS_ABORT();
|
||||
}
|
||||
}
|
||||
|
||||
void doAssertSameData( const char *file, unsigned line,
|
||||
const char *xExpr, const void *x,
|
||||
const char *yExpr, const void *y,
|
||||
const char *sizeExpr, unsigned size,
|
||||
const char *message );
|
||||
|
||||
template<class X, class Y>
|
||||
bool differs( X x, Y y )
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
template<class X, class Y>
|
||||
void doAssertDiffers( const char *file, unsigned line,
|
||||
const char *xExpr, X x,
|
||||
const char *yExpr, Y y,
|
||||
const char *message )
|
||||
{
|
||||
if ( !differs( x, y ) ) {
|
||||
if ( message )
|
||||
tracker().failedTest( file, line, message );
|
||||
tracker().failedAssertDiffers( file, line, xExpr, yExpr, TS_AS_STRING(x) );
|
||||
TS_ABORT();
|
||||
}
|
||||
}
|
||||
|
||||
template<class X, class Y>
|
||||
bool lessThan( X x, Y y )
|
||||
{
|
||||
return (x < y);
|
||||
}
|
||||
|
||||
template<class X, class Y>
|
||||
void doAssertLessThan( const char *file, unsigned line,
|
||||
const char *xExpr, X x,
|
||||
const char *yExpr, Y y,
|
||||
const char *message )
|
||||
{
|
||||
if ( !lessThan(x, y) ) {
|
||||
if ( message )
|
||||
tracker().failedTest( file, line, message );
|
||||
tracker().failedAssertLessThan( file, line, xExpr, yExpr, TS_AS_STRING(x), TS_AS_STRING(y) );
|
||||
TS_ABORT();
|
||||
}
|
||||
}
|
||||
|
||||
template<class X, class Y>
|
||||
bool lessThanEquals( X x, Y y )
|
||||
{
|
||||
return (x <= y);
|
||||
}
|
||||
|
||||
template<class X, class Y>
|
||||
void doAssertLessThanEquals( const char *file, unsigned line,
|
||||
const char *xExpr, X x,
|
||||
const char *yExpr, Y y,
|
||||
const char *message )
|
||||
{
|
||||
if ( !lessThanEquals( x, y ) ) {
|
||||
if ( message )
|
||||
tracker().failedTest( file, line, message );
|
||||
tracker().failedAssertLessThanEquals( file, line, xExpr, yExpr, TS_AS_STRING(x), TS_AS_STRING(y) );
|
||||
TS_ABORT();
|
||||
}
|
||||
}
|
||||
|
||||
template<class X, class P>
|
||||
void doAssertPredicate( const char *file, unsigned line,
|
||||
const char *pExpr, const P &p,
|
||||
const char *xExpr, X x,
|
||||
const char *message )
|
||||
{
|
||||
if ( !p( x ) ) {
|
||||
if ( message )
|
||||
tracker().failedTest( file, line, message );
|
||||
tracker().failedAssertPredicate( file, line, pExpr, xExpr, TS_AS_STRING(x) );
|
||||
TS_ABORT();
|
||||
}
|
||||
}
|
||||
|
||||
template<class X, class Y, class R>
|
||||
void doAssertRelation( const char *file, unsigned line,
|
||||
const char *rExpr, const R &r,
|
||||
const char *xExpr, X x,
|
||||
const char *yExpr, Y y,
|
||||
const char *message )
|
||||
{
|
||||
if ( !r( x, y ) ) {
|
||||
if ( message )
|
||||
tracker().failedTest( file, line, message );
|
||||
tracker().failedAssertRelation( file, line, rExpr, xExpr, yExpr, TS_AS_STRING(x), TS_AS_STRING(y) );
|
||||
TS_ABORT();
|
||||
}
|
||||
}
|
||||
|
||||
template<class X, class Y, class D>
|
||||
bool delta( X x, Y y, D d )
|
||||
{
|
||||
return ((y >= x - d) && (y <= x + d));
|
||||
}
|
||||
|
||||
template<class X, class Y, class D>
|
||||
void doAssertDelta( const char *file, unsigned line,
|
||||
const char *xExpr, X x,
|
||||
const char *yExpr, Y y,
|
||||
const char *dExpr, D d,
|
||||
const char *message )
|
||||
{
|
||||
if ( !delta( x, y, d ) ) {
|
||||
if ( message )
|
||||
tracker().failedTest( file, line, message );
|
||||
|
||||
tracker().failedAssertDelta( file, line, xExpr, yExpr, dExpr,
|
||||
TS_AS_STRING(x), TS_AS_STRING(y), TS_AS_STRING(d) );
|
||||
TS_ABORT();
|
||||
}
|
||||
}
|
||||
|
||||
void doFailAssertThrows( const char *file, unsigned line,
|
||||
const char *expr, const char *type,
|
||||
bool otherThrown,
|
||||
const char *message );
|
||||
|
||||
void doFailAssertThrowsNot( const char *file, unsigned line,
|
||||
const char *expression, const char *message );
|
||||
|
||||
# ifdef _CXXTEST_HAVE_EH
|
||||
# define _TS_TRY try
|
||||
# define _TS_CATCH_TYPE(t, b) catch t b
|
||||
# define _TS_CATCH_ABORT(b) _TS_CATCH_TYPE( (const CxxTest::AbortTest &), b )
|
||||
# define _TS_LAST_CATCH(b) _TS_CATCH_TYPE( (...), b )
|
||||
# define _TSM_LAST_CATCH(f,l,m) _TS_LAST_CATCH( { (CxxTest::tracker()).failedTest(f,l,m); } )
|
||||
# ifdef _CXXTEST_HAVE_STD
|
||||
# define ___TSM_CATCH(f,l,m) \
|
||||
catch(const std::exception &e) { (CxxTest::tracker()).failedTest(f,l,e.what()); } \
|
||||
_TSM_LAST_CATCH(f,l,m)
|
||||
# else // !_CXXTEST_HAVE_STD
|
||||
# define ___TSM_CATCH(f,l,m) _TSM_LAST_CATCH(f,l,m)
|
||||
# endif // _CXXTEST_HAVE_STD
|
||||
# define __TSM_CATCH(f,l,m) \
|
||||
_TS_CATCH_ABORT( { throw; } ) \
|
||||
___TSM_CATCH(f,l,m)
|
||||
# define __TS_CATCH(f,l) __TSM_CATCH(f,l,"Unhandled exception")
|
||||
# define _TS_CATCH __TS_CATCH(__FILE__,__LINE__)
|
||||
# else // !_CXXTEST_HAVE_EH
|
||||
# define _TS_TRY
|
||||
# define ___TSM_CATCH(f,l,m)
|
||||
# define __TSM_CATCH(f,l,m)
|
||||
# define __TS_CATCH(f,l)
|
||||
# define _TS_CATCH
|
||||
# define _TS_CATCH_TYPE(t, b)
|
||||
# define _TS_LAST_CATCH(b)
|
||||
# define _TS_CATCH_ABORT(b)
|
||||
# endif // _CXXTEST_HAVE_EH
|
||||
|
||||
// TS_TRACE
|
||||
# define _TS_TRACE(f,l,e) CxxTest::doTrace( (f), (l), TS_AS_STRING(e) )
|
||||
# define TS_TRACE(e) _TS_TRACE( __FILE__, __LINE__, e )
|
||||
|
||||
// TS_WARN
|
||||
# define _TS_WARN(f,l,e) CxxTest::doWarn( (f), (l), TS_AS_STRING(e) )
|
||||
# define TS_WARN(e) _TS_WARN( __FILE__, __LINE__, e )
|
||||
|
||||
// TS_FAIL
|
||||
# define _TS_FAIL(f,l,e) CxxTest::doFailTest( (f), (l), TS_AS_STRING(e) )
|
||||
# define TS_FAIL(e) _TS_FAIL( __FILE__, __LINE__, e )
|
||||
|
||||
// TS_ASSERT
|
||||
# define ___ETS_ASSERT(f,l,e,m) { if ( !(e) ) CxxTest::doFailAssert( (f), (l), #e, (m) ); }
|
||||
# define ___TS_ASSERT(f,l,e,m) { _TS_TRY { ___ETS_ASSERT(f,l,e,m); } __TS_CATCH(f,l) }
|
||||
|
||||
# define _ETS_ASSERT(f,l,e) ___ETS_ASSERT(f,l,e,0)
|
||||
# define _TS_ASSERT(f,l,e) ___TS_ASSERT(f,l,e,0)
|
||||
|
||||
# define ETS_ASSERT(e) _ETS_ASSERT(__FILE__,__LINE__,e)
|
||||
# define TS_ASSERT(e) _TS_ASSERT(__FILE__,__LINE__,e)
|
||||
|
||||
# define _ETSM_ASSERT(f,l,m,e) ___ETS_ASSERT(f,l,e,TS_AS_STRING(m) )
|
||||
# define _TSM_ASSERT(f,l,m,e) ___TS_ASSERT(f,l,e,TS_AS_STRING(m) )
|
||||
|
||||
# define ETSM_ASSERT(m,e) _ETSM_ASSERT(__FILE__,__LINE__,m,e)
|
||||
# define TSM_ASSERT(m,e) _TSM_ASSERT(__FILE__,__LINE__,m,e)
|
||||
|
||||
// TS_ASSERT_EQUALS
|
||||
# define ___ETS_ASSERT_EQUALS(f,l,x,y,m) CxxTest::doAssertEquals( (f), (l), #x, (x), #y, (y), (m) )
|
||||
# define ___TS_ASSERT_EQUALS(f,l,x,y,m) { _TS_TRY { ___ETS_ASSERT_EQUALS(f,l,x,y,m); } __TS_CATCH(f,l) }
|
||||
|
||||
# define _ETS_ASSERT_EQUALS(f,l,x,y) ___ETS_ASSERT_EQUALS(f,l,x,y,0)
|
||||
# define _TS_ASSERT_EQUALS(f,l,x,y) ___TS_ASSERT_EQUALS(f,l,x,y,0)
|
||||
|
||||
# define ETS_ASSERT_EQUALS(x,y) _ETS_ASSERT_EQUALS(__FILE__,__LINE__,x,y)
|
||||
# define TS_ASSERT_EQUALS(x,y) _TS_ASSERT_EQUALS(__FILE__,__LINE__,x,y)
|
||||
|
||||
# define _ETSM_ASSERT_EQUALS(f,l,m,x,y) ___ETS_ASSERT_EQUALS(f,l,x,y,TS_AS_STRING(m))
|
||||
# define _TSM_ASSERT_EQUALS(f,l,m,x,y) ___TS_ASSERT_EQUALS(f,l,x,y,TS_AS_STRING(m))
|
||||
|
||||
# define ETSM_ASSERT_EQUALS(m,x,y) _ETSM_ASSERT_EQUALS(__FILE__,__LINE__,m,x,y)
|
||||
# define TSM_ASSERT_EQUALS(m,x,y) _TSM_ASSERT_EQUALS(__FILE__,__LINE__,m,x,y)
|
||||
|
||||
// TS_ASSERT_SAME_DATA
|
||||
# define ___ETS_ASSERT_SAME_DATA(f,l,x,y,s,m) CxxTest::doAssertSameData( (f), (l), #x, (x), #y, (y), #s, (s), (m) )
|
||||
# define ___TS_ASSERT_SAME_DATA(f,l,x,y,s,m) { _TS_TRY { ___ETS_ASSERT_SAME_DATA(f,l,x,y,s,m); } __TS_CATCH(f,l) }
|
||||
|
||||
# define _ETS_ASSERT_SAME_DATA(f,l,x,y,s) ___ETS_ASSERT_SAME_DATA(f,l,x,y,s,0)
|
||||
# define _TS_ASSERT_SAME_DATA(f,l,x,y,s) ___TS_ASSERT_SAME_DATA(f,l,x,y,s,0)
|
||||
|
||||
# define ETS_ASSERT_SAME_DATA(x,y,s) _ETS_ASSERT_SAME_DATA(__FILE__,__LINE__,x,y,s)
|
||||
# define TS_ASSERT_SAME_DATA(x,y,s) _TS_ASSERT_SAME_DATA(__FILE__,__LINE__,x,y,s)
|
||||
|
||||
# define _ETSM_ASSERT_SAME_DATA(f,l,m,x,y,s) ___ETS_ASSERT_SAME_DATA(f,l,x,y,s,TS_AS_STRING(m))
|
||||
# define _TSM_ASSERT_SAME_DATA(f,l,m,x,y,s) ___TS_ASSERT_SAME_DATA(f,l,x,y,s,TS_AS_STRING(m))
|
||||
|
||||
# define ETSM_ASSERT_SAME_DATA(m,x,y,s) _ETSM_ASSERT_SAME_DATA(__FILE__,__LINE__,m,x,y,s)
|
||||
# define TSM_ASSERT_SAME_DATA(m,x,y,s) _TSM_ASSERT_SAME_DATA(__FILE__,__LINE__,m,x,y,s)
|
||||
|
||||
// TS_ASSERT_DIFFERS
|
||||
# define ___ETS_ASSERT_DIFFERS(f,l,x,y,m) CxxTest::doAssertDiffers( (f), (l), #x, (x), #y, (y), (m) )
|
||||
# define ___TS_ASSERT_DIFFERS(f,l,x,y,m) { _TS_TRY { ___ETS_ASSERT_DIFFERS(f,l,x,y,m); } __TS_CATCH(f,l) }
|
||||
|
||||
# define _ETS_ASSERT_DIFFERS(f,l,x,y) ___ETS_ASSERT_DIFFERS(f,l,x,y,0)
|
||||
# define _TS_ASSERT_DIFFERS(f,l,x,y) ___TS_ASSERT_DIFFERS(f,l,x,y,0)
|
||||
|
||||
# define ETS_ASSERT_DIFFERS(x,y) _ETS_ASSERT_DIFFERS(__FILE__,__LINE__,x,y)
|
||||
# define TS_ASSERT_DIFFERS(x,y) _TS_ASSERT_DIFFERS(__FILE__,__LINE__,x,y)
|
||||
|
||||
# define _ETSM_ASSERT_DIFFERS(f,l,m,x,y) ___ETS_ASSERT_DIFFERS(f,l,x,y,TS_AS_STRING(m))
|
||||
# define _TSM_ASSERT_DIFFERS(f,l,m,x,y) ___TS_ASSERT_DIFFERS(f,l,x,y,TS_AS_STRING(m))
|
||||
|
||||
# define ETSM_ASSERT_DIFFERS(m,x,y) _ETSM_ASSERT_DIFFERS(__FILE__,__LINE__,m,x,y)
|
||||
# define TSM_ASSERT_DIFFERS(m,x,y) _TSM_ASSERT_DIFFERS(__FILE__,__LINE__,m,x,y)
|
||||
|
||||
// TS_ASSERT_LESS_THAN
|
||||
# define ___ETS_ASSERT_LESS_THAN(f,l,x,y,m) CxxTest::doAssertLessThan( (f), (l), #x, (x), #y, (y), (m) )
|
||||
# define ___TS_ASSERT_LESS_THAN(f,l,x,y,m) { _TS_TRY { ___ETS_ASSERT_LESS_THAN(f,l,x,y,m); } __TS_CATCH(f,l) }
|
||||
|
||||
# define _ETS_ASSERT_LESS_THAN(f,l,x,y) ___ETS_ASSERT_LESS_THAN(f,l,x,y,0)
|
||||
# define _TS_ASSERT_LESS_THAN(f,l,x,y) ___TS_ASSERT_LESS_THAN(f,l,x,y,0)
|
||||
|
||||
# define ETS_ASSERT_LESS_THAN(x,y) _ETS_ASSERT_LESS_THAN(__FILE__,__LINE__,x,y)
|
||||
# define TS_ASSERT_LESS_THAN(x,y) _TS_ASSERT_LESS_THAN(__FILE__,__LINE__,x,y)
|
||||
|
||||
# define _ETSM_ASSERT_LESS_THAN(f,l,m,x,y) ___ETS_ASSERT_LESS_THAN(f,l,x,y,TS_AS_STRING(m))
|
||||
# define _TSM_ASSERT_LESS_THAN(f,l,m,x,y) ___TS_ASSERT_LESS_THAN(f,l,x,y,TS_AS_STRING(m))
|
||||
|
||||
# define ETSM_ASSERT_LESS_THAN(m,x,y) _ETSM_ASSERT_LESS_THAN(__FILE__,__LINE__,m,x,y)
|
||||
# define TSM_ASSERT_LESS_THAN(m,x,y) _TSM_ASSERT_LESS_THAN(__FILE__,__LINE__,m,x,y)
|
||||
|
||||
// TS_ASSERT_LESS_THAN_EQUALS
|
||||
# define ___ETS_ASSERT_LESS_THAN_EQUALS(f,l,x,y,m) \
|
||||
CxxTest::doAssertLessThanEquals( (f), (l), #x, (x), #y, (y), (m) )
|
||||
# define ___TS_ASSERT_LESS_THAN_EQUALS(f,l,x,y,m) \
|
||||
{ _TS_TRY { ___ETS_ASSERT_LESS_THAN_EQUALS(f,l,x,y,m); } __TS_CATCH(f,l) }
|
||||
|
||||
# define _ETS_ASSERT_LESS_THAN_EQUALS(f,l,x,y) ___ETS_ASSERT_LESS_THAN_EQUALS(f,l,x,y,0)
|
||||
# define _TS_ASSERT_LESS_THAN_EQUALS(f,l,x,y) ___TS_ASSERT_LESS_THAN_EQUALS(f,l,x,y,0)
|
||||
|
||||
# define ETS_ASSERT_LESS_THAN_EQUALS(x,y) _ETS_ASSERT_LESS_THAN_EQUALS(__FILE__,__LINE__,x,y)
|
||||
# define TS_ASSERT_LESS_THAN_EQUALS(x,y) _TS_ASSERT_LESS_THAN_EQUALS(__FILE__,__LINE__,x,y)
|
||||
|
||||
# define _ETSM_ASSERT_LESS_THAN_EQUALS(f,l,m,x,y) ___ETS_ASSERT_LESS_THAN_EQUALS(f,l,x,y,TS_AS_STRING(m))
|
||||
# define _TSM_ASSERT_LESS_THAN_EQUALS(f,l,m,x,y) ___TS_ASSERT_LESS_THAN_EQUALS(f,l,x,y,TS_AS_STRING(m))
|
||||
|
||||
# define ETSM_ASSERT_LESS_THAN_EQUALS(m,x,y) _ETSM_ASSERT_LESS_THAN_EQUALS(__FILE__,__LINE__,m,x,y)
|
||||
# define TSM_ASSERT_LESS_THAN_EQUALS(m,x,y) _TSM_ASSERT_LESS_THAN_EQUALS(__FILE__,__LINE__,m,x,y)
|
||||
|
||||
// TS_ASSERT_PREDICATE
|
||||
# define ___ETS_ASSERT_PREDICATE(f,l,p,x,m) \
|
||||
CxxTest::doAssertPredicate( (f), (l), #p, p(), #x, (x), (m) )
|
||||
# define ___TS_ASSERT_PREDICATE(f,l,p,x,m) \
|
||||
{ _TS_TRY { ___ETS_ASSERT_PREDICATE(f,l,p,x,m); } __TS_CATCH(f,l) }
|
||||
|
||||
# define _ETS_ASSERT_PREDICATE(f,l,p,x) ___ETS_ASSERT_PREDICATE(f,l,p,x,0)
|
||||
# define _TS_ASSERT_PREDICATE(f,l,p,x) ___TS_ASSERT_PREDICATE(f,l,p,x,0)
|
||||
|
||||
# define ETS_ASSERT_PREDICATE(p,x) _ETS_ASSERT_PREDICATE(__FILE__,__LINE__,p,x)
|
||||
# define TS_ASSERT_PREDICATE(p,x) _TS_ASSERT_PREDICATE(__FILE__,__LINE__,p,x)
|
||||
|
||||
# define _ETSM_ASSERT_PREDICATE(f,l,m,p,x) ___ETS_ASSERT_PREDICATE(f,l,p,x,TS_AS_STRING(m))
|
||||
# define _TSM_ASSERT_PREDICATE(f,l,m,p,x) ___TS_ASSERT_PREDICATE(f,l,p,x,TS_AS_STRING(m))
|
||||
|
||||
# define ETSM_ASSERT_PREDICATE(m,p,x) _ETSM_ASSERT_PREDICATE(__FILE__,__LINE__,m,p,x)
|
||||
# define TSM_ASSERT_PREDICATE(m,p,x) _TSM_ASSERT_PREDICATE(__FILE__,__LINE__,m,p,x)
|
||||
|
||||
// TS_ASSERT_RELATION
|
||||
# define ___ETS_ASSERT_RELATION(f,l,r,x,y,m) \
|
||||
CxxTest::doAssertRelation( (f), (l), #r, r(), #x, (x), #y, (y), (m) )
|
||||
# define ___TS_ASSERT_RELATION(f,l,r,x,y,m) \
|
||||
{ _TS_TRY { ___ETS_ASSERT_RELATION(f,l,r,x,y,m); } __TS_CATCH(f,l) }
|
||||
|
||||
# define _ETS_ASSERT_RELATION(f,l,r,x,y) ___ETS_ASSERT_RELATION(f,l,r,x,y,0)
|
||||
# define _TS_ASSERT_RELATION(f,l,r,x,y) ___TS_ASSERT_RELATION(f,l,r,x,y,0)
|
||||
|
||||
# define ETS_ASSERT_RELATION(r,x,y) _ETS_ASSERT_RELATION(__FILE__,__LINE__,r,x,y)
|
||||
# define TS_ASSERT_RELATION(r,x,y) _TS_ASSERT_RELATION(__FILE__,__LINE__,r,x,y)
|
||||
|
||||
# define _ETSM_ASSERT_RELATION(f,l,m,r,x,y) ___ETS_ASSERT_RELATION(f,l,r,x,y,TS_AS_STRING(m))
|
||||
# define _TSM_ASSERT_RELATION(f,l,m,r,x,y) ___TS_ASSERT_RELATION(f,l,r,x,y,TS_AS_STRING(m))
|
||||
|
||||
# define ETSM_ASSERT_RELATION(m,r,x,y) _ETSM_ASSERT_RELATION(__FILE__,__LINE__,m,r,x,y)
|
||||
# define TSM_ASSERT_RELATION(m,r,x,y) _TSM_ASSERT_RELATION(__FILE__,__LINE__,m,r,x,y)
|
||||
|
||||
// TS_ASSERT_DELTA
|
||||
# define ___ETS_ASSERT_DELTA(f,l,x,y,d,m) CxxTest::doAssertDelta( (f), (l), #x, (x), #y, (y), #d, (d), (m) )
|
||||
# define ___TS_ASSERT_DELTA(f,l,x,y,d,m) { _TS_TRY { ___ETS_ASSERT_DELTA(f,l,x,y,d,m); } __TS_CATCH(f,l) }
|
||||
|
||||
# define _ETS_ASSERT_DELTA(f,l,x,y,d) ___ETS_ASSERT_DELTA(f,l,x,y,d,0)
|
||||
# define _TS_ASSERT_DELTA(f,l,x,y,d) ___TS_ASSERT_DELTA(f,l,x,y,d,0)
|
||||
|
||||
# define ETS_ASSERT_DELTA(x,y,d) _ETS_ASSERT_DELTA(__FILE__,__LINE__,x,y,d)
|
||||
# define TS_ASSERT_DELTA(x,y,d) _TS_ASSERT_DELTA(__FILE__,__LINE__,x,y,d)
|
||||
|
||||
# define _ETSM_ASSERT_DELTA(f,l,m,x,y,d) ___ETS_ASSERT_DELTA(f,l,x,y,d,TS_AS_STRING(m))
|
||||
# define _TSM_ASSERT_DELTA(f,l,m,x,y,d) ___TS_ASSERT_DELTA(f,l,x,y,d,TS_AS_STRING(m))
|
||||
|
||||
# define ETSM_ASSERT_DELTA(m,x,y,d) _ETSM_ASSERT_DELTA(__FILE__,__LINE__,m,x,y,d)
|
||||
# define TSM_ASSERT_DELTA(m,x,y,d) _TSM_ASSERT_DELTA(__FILE__,__LINE__,m,x,y,d)
|
||||
|
||||
// TS_ASSERT_THROWS
|
||||
# define ___TS_ASSERT_THROWS(f,l,e,t,m) { \
|
||||
bool _ts_threw_expected = false, _ts_threw_else = false; \
|
||||
_TS_TRY { e; } \
|
||||
_TS_CATCH_TYPE( (t), { _ts_threw_expected = true; } ) \
|
||||
_TS_CATCH_ABORT( { throw; } ) \
|
||||
_TS_LAST_CATCH( { _ts_threw_else = true; } ) \
|
||||
if ( !_ts_threw_expected ) { CxxTest::doFailAssertThrows( (f), (l), #e, #t, _ts_threw_else, (m) ); } }
|
||||
|
||||
# define _TS_ASSERT_THROWS(f,l,e,t) ___TS_ASSERT_THROWS(f,l,e,t,0)
|
||||
# define TS_ASSERT_THROWS(e,t) _TS_ASSERT_THROWS(__FILE__,__LINE__,e,t)
|
||||
|
||||
# define _TSM_ASSERT_THROWS(f,l,m,e,t) ___TS_ASSERT_THROWS(f,l,e,t,TS_AS_STRING(m))
|
||||
# define TSM_ASSERT_THROWS(m,e,t) _TSM_ASSERT_THROWS(__FILE__,__LINE__,m,e,t)
|
||||
|
||||
// TS_ASSERT_THROWS_ASSERT
|
||||
# define ___TS_ASSERT_THROWS_ASSERT(f,l,e,t,a,m) { \
|
||||
bool _ts_threw_expected = false, _ts_threw_else = false; \
|
||||
_TS_TRY { e; } \
|
||||
_TS_CATCH_TYPE( (t), { a; _ts_threw_expected = true; } ) \
|
||||
_TS_CATCH_ABORT( { throw; } ) \
|
||||
_TS_LAST_CATCH( { _ts_threw_else = true; } ) \
|
||||
if ( !_ts_threw_expected ) { CxxTest::doFailAssertThrows( (f), (l), #e, #t, _ts_threw_else, (m) ); } }
|
||||
|
||||
# define _TS_ASSERT_THROWS_ASSERT(f,l,e,t,a) ___TS_ASSERT_THROWS_ASSERT(f,l,e,t,a,0)
|
||||
# define TS_ASSERT_THROWS_ASSERT(e,t,a) _TS_ASSERT_THROWS_ASSERT(__FILE__,__LINE__,e,t,a)
|
||||
|
||||
# define _TSM_ASSERT_THROWS_ASSERT(f,l,m,e,t,a) ___TS_ASSERT_THROWS_ASSERT(f,l,e,t,a,TS_AS_STRING(m))
|
||||
# define TSM_ASSERT_THROWS_ASSERT(m,e,t,a) _TSM_ASSERT_THROWS_ASSERT(__FILE__,__LINE__,m,e,t,a)
|
||||
|
||||
// TS_ASSERT_THROWS_EQUALS
|
||||
# define TS_ASSERT_THROWS_EQUALS(e,t,x,y) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_EQUALS(x,y))
|
||||
# define TSM_ASSERT_THROWS_EQUALS(m,e,t,x,y) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_EQUALS(m,x,y))
|
||||
|
||||
// TS_ASSERT_THROWS_DIFFERS
|
||||
# define TS_ASSERT_THROWS_DIFFERS(e,t,x,y) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_DIFFERS(x,y))
|
||||
# define TSM_ASSERT_THROWS_DIFFERS(m,e,t,x,y) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_DIFFERS(m,x,y))
|
||||
|
||||
// TS_ASSERT_THROWS_DELTA
|
||||
# define TS_ASSERT_THROWS_DELTA(e,t,x,y,d) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_DELTA(x,y,d))
|
||||
# define TSM_ASSERT_THROWS_DELTA(m,e,t,x,y,d) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_DELTA(m,x,y,d))
|
||||
|
||||
// TS_ASSERT_THROWS_SAME_DATA
|
||||
# define TS_ASSERT_THROWS_SAME_DATA(e,t,x,y,s) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_SAME_DATA(x,y,s))
|
||||
# define TSM_ASSERT_THROWS_SAME_DATA(m,e,t,x,y,s) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_SAME_DATA(m,x,y,s))
|
||||
|
||||
// TS_ASSERT_THROWS_LESS_THAN
|
||||
# define TS_ASSERT_THROWS_LESS_THAN(e,t,x,y) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_LESS_THAN(x,y))
|
||||
# define TSM_ASSERT_THROWS_LESS_THAN(m,e,t,x,y) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_LESS_THAN(m,x,y))
|
||||
|
||||
// TS_ASSERT_THROWS_LESS_THAN_EQUALS
|
||||
# define TS_ASSERT_THROWS_LESS_THAN_EQUALS(e,t,x,y) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_LESS_THAN_EQUALS(x,y))
|
||||
# define TSM_ASSERT_THROWS_LESS_THAN_EQUALS(m,e,t,x,y) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_LESS_THAN_EQUALS(m,x,y))
|
||||
|
||||
// TS_ASSERT_THROWS_PREDICATE
|
||||
# define TS_ASSERT_THROWS_PREDICATE(e,t,p,v) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_PREDICATE(p,v))
|
||||
# define TSM_ASSERT_THROWS_PREDICATE(m,e,t,p,v) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_PREDICATE(m,p,v))
|
||||
|
||||
// TS_ASSERT_THROWS_RELATION
|
||||
# define TS_ASSERT_THROWS_RELATION(e,t,r,x,y) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_RELATION(r,x,y))
|
||||
# define TSM_ASSERT_THROWS_RELATION(m,e,t,r,x,y) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_RELATION(m,r,x,y))
|
||||
|
||||
// TS_ASSERT_THROWS_ANYTHING
|
||||
# define ___TS_ASSERT_THROWS_ANYTHING(f,l,e,m) { \
|
||||
bool _ts_threw = false; \
|
||||
_TS_TRY { e; } \
|
||||
_TS_LAST_CATCH( { _ts_threw = true; } ) \
|
||||
if ( !_ts_threw ) { CxxTest::doFailAssertThrows( (f), (l), #e, "...", false, (m) ); } }
|
||||
|
||||
# define _TS_ASSERT_THROWS_ANYTHING(f,l,e) ___TS_ASSERT_THROWS_ANYTHING(f,l,e,0)
|
||||
# define TS_ASSERT_THROWS_ANYTHING(e) _TS_ASSERT_THROWS_ANYTHING(__FILE__, __LINE__, e)
|
||||
|
||||
# define _TSM_ASSERT_THROWS_ANYTHING(f,l,m,e) ___TS_ASSERT_THROWS_ANYTHING(f,l,e,TS_AS_STRING(m))
|
||||
# define TSM_ASSERT_THROWS_ANYTHING(m,e) _TSM_ASSERT_THROWS_ANYTHING(__FILE__,__LINE__,m,e)
|
||||
|
||||
// TS_ASSERT_THROWS_NOTHING
|
||||
# define ___TS_ASSERT_THROWS_NOTHING(f,l,e,m) { \
|
||||
_TS_TRY { e; } \
|
||||
_TS_CATCH_ABORT( { throw; } ) \
|
||||
_TS_LAST_CATCH( { CxxTest::doFailAssertThrowsNot( (f), (l), #e, (m) ); } ) }
|
||||
|
||||
# define _TS_ASSERT_THROWS_NOTHING(f,l,e) ___TS_ASSERT_THROWS_NOTHING(f,l,e,0)
|
||||
# define TS_ASSERT_THROWS_NOTHING(e) _TS_ASSERT_THROWS_NOTHING(__FILE__,__LINE__,e)
|
||||
|
||||
# define _TSM_ASSERT_THROWS_NOTHING(f,l,m,e) ___TS_ASSERT_THROWS_NOTHING(f,l,e,TS_AS_STRING(m))
|
||||
# define TSM_ASSERT_THROWS_NOTHING(m,e) _TSM_ASSERT_THROWS_NOTHING(__FILE__,__LINE__,m,e)
|
||||
|
||||
|
||||
//
|
||||
// This takes care of "signed <-> unsigned" warnings
|
||||
//
|
||||
# define CXXTEST_COMPARISONS(CXXTEST_X, CXXTEST_Y, CXXTEST_T) \
|
||||
inline bool equals( CXXTEST_X x, CXXTEST_Y y ) { return (((CXXTEST_T)x) == ((CXXTEST_T)y)); } \
|
||||
inline bool equals( CXXTEST_Y y, CXXTEST_X x ) { return (((CXXTEST_T)y) == ((CXXTEST_T)x)); } \
|
||||
inline bool differs( CXXTEST_X x, CXXTEST_Y y ) { return (((CXXTEST_T)x) != ((CXXTEST_T)y)); } \
|
||||
inline bool differs( CXXTEST_Y y, CXXTEST_X x ) { return (((CXXTEST_T)y) != ((CXXTEST_T)x)); } \
|
||||
inline bool lessThan( CXXTEST_X x, CXXTEST_Y y ) { return (((CXXTEST_T)x) < ((CXXTEST_T)y)); } \
|
||||
inline bool lessThan( CXXTEST_Y y, CXXTEST_X x ) { return (((CXXTEST_T)y) < ((CXXTEST_T)x)); } \
|
||||
inline bool lessThanEquals( CXXTEST_X x, CXXTEST_Y y ) { return (((CXXTEST_T)x) <= ((CXXTEST_T)y)); } \
|
||||
inline bool lessThanEquals( CXXTEST_Y y, CXXTEST_X x ) { return (((CXXTEST_T)y) <= ((CXXTEST_T)x)); }
|
||||
|
||||
# define CXXTEST_INTEGRAL(CXXTEST_T) \
|
||||
CXXTEST_COMPARISONS( signed CXXTEST_T, unsigned CXXTEST_T, unsigned CXXTEST_T )
|
||||
|
||||
CXXTEST_INTEGRAL( char )
|
||||
CXXTEST_INTEGRAL( short )
|
||||
CXXTEST_INTEGRAL( int )
|
||||
CXXTEST_INTEGRAL( long )
|
||||
# ifdef _CXXTEST_LONGLONG
|
||||
CXXTEST_INTEGRAL( _CXXTEST_LONGLONG )
|
||||
# endif // _CXXTEST_LONGLONG
|
||||
|
||||
# define CXXTEST_SMALL_BIG(CXXTEST_SMALL, CXXTEST_BIG) \
|
||||
CXXTEST_COMPARISONS( signed CXXTEST_SMALL, unsigned CXXTEST_BIG, unsigned CXXTEST_BIG ) \
|
||||
CXXTEST_COMPARISONS( signed CXXTEST_BIG, unsigned CXXTEST_SMALL, unsigned CXXTEST_BIG )
|
||||
|
||||
CXXTEST_SMALL_BIG( char, short )
|
||||
CXXTEST_SMALL_BIG( char, int )
|
||||
CXXTEST_SMALL_BIG( short, int )
|
||||
CXXTEST_SMALL_BIG( char, long )
|
||||
CXXTEST_SMALL_BIG( short, long )
|
||||
CXXTEST_SMALL_BIG( int, long )
|
||||
|
||||
# ifdef _CXXTEST_LONGLONG
|
||||
CXXTEST_SMALL_BIG( char, _CXXTEST_LONGLONG )
|
||||
CXXTEST_SMALL_BIG( short, _CXXTEST_LONGLONG )
|
||||
CXXTEST_SMALL_BIG( int, _CXXTEST_LONGLONG )
|
||||
CXXTEST_SMALL_BIG( long, _CXXTEST_LONGLONG )
|
||||
# endif // _CXXTEST_LONGLONG
|
||||
}
|
||||
|
||||
#endif // __cxxtest__TestSuite_h__
|
||||
248
test/cxxtest/cxxtest/TestTracker.cpp
Normal file
248
test/cxxtest/cxxtest/TestTracker.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
#ifndef __cxxtest__TestTracker_cpp__
|
||||
#define __cxxtest__TestTracker_cpp__
|
||||
|
||||
#include <cxxtest/TestTracker.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
bool TestTracker::_created = false;
|
||||
|
||||
TestTracker::TestTracker()
|
||||
{
|
||||
if ( !_created ) {
|
||||
initialize();
|
||||
_created = true;
|
||||
}
|
||||
}
|
||||
|
||||
TestTracker::~TestTracker()
|
||||
{
|
||||
}
|
||||
|
||||
TestTracker & TestTracker::tracker()
|
||||
{
|
||||
static TestTracker theTracker;
|
||||
return theTracker;
|
||||
}
|
||||
|
||||
void TestTracker::initialize()
|
||||
{
|
||||
_warnings = 0;
|
||||
_failedTests = 0;
|
||||
_testFailedAsserts = 0;
|
||||
_suiteFailedTests = 0;
|
||||
_failedSuites = 0;
|
||||
setListener( 0 );
|
||||
_world = 0;
|
||||
_suite = 0;
|
||||
_test = 0;
|
||||
}
|
||||
|
||||
const TestDescription *TestTracker::fixTest( const TestDescription *d ) const
|
||||
{
|
||||
return d ? d : &dummyTest();
|
||||
}
|
||||
|
||||
const SuiteDescription *TestTracker::fixSuite( const SuiteDescription *d ) const
|
||||
{
|
||||
return d ? d : &dummySuite();
|
||||
}
|
||||
|
||||
const WorldDescription *TestTracker::fixWorld( const WorldDescription *d ) const
|
||||
{
|
||||
return d ? d : &dummyWorld();
|
||||
}
|
||||
|
||||
const TestDescription &TestTracker::dummyTest() const
|
||||
{
|
||||
return dummySuite().testDescription(0);
|
||||
}
|
||||
|
||||
const SuiteDescription &TestTracker::dummySuite() const
|
||||
{
|
||||
return dummyWorld().suiteDescription(0);
|
||||
}
|
||||
|
||||
const WorldDescription &TestTracker::dummyWorld() const
|
||||
{
|
||||
return _dummyWorld;
|
||||
}
|
||||
|
||||
void TestTracker::setListener( TestListener *l )
|
||||
{
|
||||
_l = l ? l : &_dummyListener;
|
||||
}
|
||||
|
||||
void TestTracker::enterWorld( const WorldDescription &wd )
|
||||
{
|
||||
setWorld( &wd );
|
||||
_warnings = _failedTests = _testFailedAsserts = _suiteFailedTests = _failedSuites = 0;
|
||||
_l->enterWorld( wd );
|
||||
}
|
||||
|
||||
void TestTracker::enterSuite( const SuiteDescription &sd )
|
||||
{
|
||||
setSuite( &sd );
|
||||
_testFailedAsserts = _suiteFailedTests = 0;
|
||||
_l->enterSuite(sd);
|
||||
}
|
||||
|
||||
void TestTracker::enterTest( const TestDescription &td )
|
||||
{
|
||||
setTest( &td );
|
||||
_testFailedAsserts = false;
|
||||
_l->enterTest(td);
|
||||
}
|
||||
|
||||
void TestTracker::leaveTest( const TestDescription &td )
|
||||
{
|
||||
_l->leaveTest( td );
|
||||
setTest( 0 );
|
||||
}
|
||||
|
||||
void TestTracker::leaveSuite( const SuiteDescription &sd )
|
||||
{
|
||||
_l->leaveSuite( sd );
|
||||
setSuite( 0 );
|
||||
}
|
||||
|
||||
void TestTracker::leaveWorld( const WorldDescription &wd )
|
||||
{
|
||||
_l->leaveWorld( wd );
|
||||
setWorld( 0 );
|
||||
}
|
||||
|
||||
void TestTracker::trace( const char *file, unsigned line, const char *expression )
|
||||
{
|
||||
_l->trace( file, line, expression );
|
||||
}
|
||||
|
||||
void TestTracker::warning( const char *file, unsigned line, const char *expression )
|
||||
{
|
||||
countWarning();
|
||||
_l->warning( file, line, expression );
|
||||
}
|
||||
|
||||
void TestTracker::failedTest( const char *file, unsigned line, const char *expression )
|
||||
{
|
||||
countFailure();
|
||||
_l->failedTest( file, line, expression );
|
||||
}
|
||||
|
||||
void TestTracker::failedAssert( const char *file, unsigned line, const char *expression )
|
||||
{
|
||||
countFailure();
|
||||
_l->failedAssert( file, line, expression );
|
||||
}
|
||||
|
||||
void TestTracker::failedAssertEquals( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *x, const char *y )
|
||||
{
|
||||
countFailure();
|
||||
_l->failedAssertEquals( file, line, xStr, yStr, x, y );
|
||||
}
|
||||
|
||||
void TestTracker::failedAssertSameData( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *sizeStr, const void *x,
|
||||
const void *y, unsigned size )
|
||||
{
|
||||
countFailure();
|
||||
_l->failedAssertSameData( file, line, xStr, yStr, sizeStr, x, y, size );
|
||||
}
|
||||
|
||||
void TestTracker::failedAssertDelta( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr, const char *dStr,
|
||||
const char *x, const char *y, const char *d )
|
||||
{
|
||||
countFailure();
|
||||
_l->failedAssertDelta( file, line, xStr, yStr, dStr, x, y, d );
|
||||
}
|
||||
|
||||
void TestTracker::failedAssertDiffers( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *value )
|
||||
{
|
||||
countFailure();
|
||||
_l->failedAssertDiffers( file, line, xStr, yStr, value );
|
||||
}
|
||||
|
||||
void TestTracker::failedAssertLessThan( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *x, const char *y )
|
||||
{
|
||||
countFailure();
|
||||
_l->failedAssertLessThan( file, line, xStr, yStr, x, y );
|
||||
}
|
||||
|
||||
void TestTracker::failedAssertLessThanEquals( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *x, const char *y )
|
||||
{
|
||||
countFailure();
|
||||
_l->failedAssertLessThanEquals( file, line, xStr, yStr, x, y );
|
||||
}
|
||||
|
||||
void TestTracker::failedAssertPredicate( const char *file, unsigned line,
|
||||
const char *predicate, const char *xStr, const char *x )
|
||||
{
|
||||
countFailure();
|
||||
_l->failedAssertPredicate( file, line, predicate, xStr, x );
|
||||
}
|
||||
|
||||
void TestTracker::failedAssertRelation( const char *file, unsigned line,
|
||||
const char *relation, const char *xStr, const char *yStr,
|
||||
const char *x, const char *y )
|
||||
{
|
||||
countFailure();
|
||||
_l->failedAssertRelation( file, line, relation, xStr, yStr, x, y );
|
||||
}
|
||||
|
||||
void TestTracker::failedAssertThrows( const char *file, unsigned line,
|
||||
const char *expression, const char *type,
|
||||
bool otherThrown )
|
||||
{
|
||||
countFailure();
|
||||
_l->failedAssertThrows( file, line, expression, type, otherThrown );
|
||||
}
|
||||
|
||||
void TestTracker::failedAssertThrowsNot( const char *file, unsigned line, const char *expression )
|
||||
{
|
||||
countFailure();
|
||||
_l->failedAssertThrowsNot( file, line, expression );
|
||||
}
|
||||
|
||||
void TestTracker::setWorld( const WorldDescription *w )
|
||||
{
|
||||
_world = fixWorld( w );
|
||||
setSuite( 0 );
|
||||
}
|
||||
|
||||
void TestTracker::setSuite( const SuiteDescription *s )
|
||||
{
|
||||
_suite = fixSuite( s );
|
||||
setTest( 0 );
|
||||
}
|
||||
|
||||
void TestTracker::setTest( const TestDescription *t )
|
||||
{
|
||||
_test = fixTest( t );
|
||||
}
|
||||
|
||||
void TestTracker::countWarning()
|
||||
{
|
||||
++ _warnings;
|
||||
}
|
||||
|
||||
void TestTracker::countFailure()
|
||||
{
|
||||
if ( ++ _testFailedAsserts == 1 ) {
|
||||
++ _failedTests;
|
||||
if ( ++ _suiteFailedTests == 1 )
|
||||
++ _failedSuites;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __cxxtest__TestTracker_cpp__
|
||||
114
test/cxxtest/cxxtest/TestTracker.h
Normal file
114
test/cxxtest/cxxtest/TestTracker.h
Normal file
@@ -0,0 +1,114 @@
|
||||
#ifndef __cxxtest__TestTracker_h__
|
||||
#define __cxxtest__TestTracker_h__
|
||||
|
||||
//
|
||||
// The TestTracker tracks running tests
|
||||
// The actual work is done in CountingListenerProxy,
|
||||
// but this way avoids cyclic references TestListener<->CountingListenerProxy
|
||||
//
|
||||
|
||||
#include <cxxtest/TestListener.h>
|
||||
#include <cxxtest/DummyDescriptions.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class TestListener;
|
||||
|
||||
class TestTracker : public TestListener
|
||||
{
|
||||
public:
|
||||
virtual ~TestTracker();
|
||||
|
||||
static TestTracker &tracker();
|
||||
|
||||
const TestDescription *fixTest( const TestDescription *d ) const;
|
||||
const SuiteDescription *fixSuite( const SuiteDescription *d ) const;
|
||||
const WorldDescription *fixWorld( const WorldDescription *d ) const;
|
||||
|
||||
const TestDescription &test() const { return *_test; }
|
||||
const SuiteDescription &suite() const { return *_suite; }
|
||||
const WorldDescription &world() const { return *_world; }
|
||||
|
||||
bool testFailed() const { return (testFailedAsserts() > 0); }
|
||||
bool suiteFailed() const { return (suiteFailedTests() > 0); }
|
||||
bool worldFailed() const { return (failedSuites() > 0); }
|
||||
|
||||
unsigned warnings() const { return _warnings; }
|
||||
unsigned failedTests() const { return _failedTests; }
|
||||
unsigned testFailedAsserts() const { return _testFailedAsserts; }
|
||||
unsigned suiteFailedTests() const { return _suiteFailedTests; }
|
||||
unsigned failedSuites() const { return _failedSuites; }
|
||||
|
||||
void enterWorld( const WorldDescription &wd );
|
||||
void enterSuite( const SuiteDescription &sd );
|
||||
void enterTest( const TestDescription &td );
|
||||
void leaveTest( const TestDescription &td );
|
||||
void leaveSuite( const SuiteDescription &sd );
|
||||
void leaveWorld( const WorldDescription &wd );
|
||||
void trace( const char *file, unsigned line, const char *expression );
|
||||
void warning( const char *file, unsigned line, const char *expression );
|
||||
void failedTest( const char *file, unsigned line, const char *expression );
|
||||
void failedAssert( const char *file, unsigned line, const char *expression );
|
||||
void failedAssertEquals( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *x, const char *y );
|
||||
void failedAssertSameData( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *sizeStr, const void *x,
|
||||
const void *y, unsigned size );
|
||||
void failedAssertDelta( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr, const char *dStr,
|
||||
const char *x, const char *y, const char *d );
|
||||
void failedAssertDiffers( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *value );
|
||||
void failedAssertLessThan( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *x, const char *y );
|
||||
void failedAssertLessThanEquals( const char *file, unsigned line,
|
||||
const char *xStr, const char *yStr,
|
||||
const char *x, const char *y );
|
||||
void failedAssertPredicate( const char *file, unsigned line,
|
||||
const char *predicate, const char *xStr, const char *x );
|
||||
void failedAssertRelation( const char *file, unsigned line,
|
||||
const char *relation, const char *xStr, const char *yStr,
|
||||
const char *x, const char *y );
|
||||
void failedAssertThrows( const char *file, unsigned line,
|
||||
const char *expression, const char *type,
|
||||
bool otherThrown );
|
||||
void failedAssertThrowsNot( const char *file, unsigned line, const char *expression );
|
||||
|
||||
private:
|
||||
TestTracker( const TestTracker & );
|
||||
TestTracker &operator=( const TestTracker & );
|
||||
|
||||
static bool _created;
|
||||
TestListener _dummyListener;
|
||||
DummyWorldDescription _dummyWorld;
|
||||
unsigned _warnings, _failedTests, _testFailedAsserts, _suiteFailedTests, _failedSuites;
|
||||
TestListener *_l;
|
||||
const WorldDescription *_world;
|
||||
const SuiteDescription *_suite;
|
||||
const TestDescription *_test;
|
||||
|
||||
const TestDescription &dummyTest() const;
|
||||
const SuiteDescription &dummySuite() const;
|
||||
const WorldDescription &dummyWorld() const;
|
||||
|
||||
void setWorld( const WorldDescription *w );
|
||||
void setSuite( const SuiteDescription *s );
|
||||
void setTest( const TestDescription *t );
|
||||
void countWarning();
|
||||
void countFailure();
|
||||
|
||||
friend class TestRunner;
|
||||
|
||||
TestTracker();
|
||||
void initialize();
|
||||
void setListener( TestListener *l );
|
||||
};
|
||||
|
||||
inline TestTracker &tracker() { return TestTracker::tracker(); }
|
||||
}
|
||||
|
||||
#endif // __cxxtest__TestTracker_h__
|
||||
140
test/cxxtest/cxxtest/ValueTraits.cpp
Normal file
140
test/cxxtest/cxxtest/ValueTraits.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
#ifndef __cxxtest__ValueTraits_cpp__
|
||||
#define __cxxtest__ValueTraits_cpp__
|
||||
|
||||
#include <cxxtest/ValueTraits.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
//
|
||||
// Non-inline functions from ValueTraits.h
|
||||
//
|
||||
|
||||
char digitToChar( unsigned digit )
|
||||
{
|
||||
if ( digit < 10 )
|
||||
return (char)('0' + digit);
|
||||
if ( digit <= 10 + 'Z' - 'A' )
|
||||
return (char)('A' + digit - 10);
|
||||
return '?';
|
||||
}
|
||||
|
||||
const char *byteToHex( unsigned char byte )
|
||||
{
|
||||
static char asHex[3];
|
||||
asHex[0] = digitToChar( byte >> 4 );
|
||||
asHex[1] = digitToChar( byte & 0x0F );
|
||||
asHex[2] = '\0';
|
||||
return asHex;
|
||||
}
|
||||
|
||||
char *copyString( char *dst, const char *src )
|
||||
{
|
||||
while ( (*dst = *src) != '\0' ) {
|
||||
++ dst;
|
||||
++ src;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
bool stringsEqual( const char *s1, const char *s2 )
|
||||
{
|
||||
char c;
|
||||
while ( (c = *s1++) == *s2++ )
|
||||
if ( c == '\0' )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
char *charToString( unsigned long c, char *s )
|
||||
{
|
||||
switch( c ) {
|
||||
case '\\': return copyString( s, "\\\\" );
|
||||
case '\"': return copyString( s, "\\\"" );
|
||||
case '\'': return copyString( s, "\\\'" );
|
||||
case '\0': return copyString( s, "\\0" );
|
||||
case '\a': return copyString( s, "\\a" );
|
||||
case '\b': return copyString( s, "\\b" );
|
||||
case '\n': return copyString( s, "\\n" );
|
||||
case '\r': return copyString( s, "\\r" );
|
||||
case '\t': return copyString( s, "\\t" );
|
||||
}
|
||||
if ( c >= 32 && c <= 127 ) {
|
||||
s[0] = (char)c;
|
||||
s[1] = '\0';
|
||||
return s + 1;
|
||||
}
|
||||
else {
|
||||
s[0] = '\\';
|
||||
s[1] = 'x';
|
||||
if ( c < 0x10 ) {
|
||||
s[2] = '0';
|
||||
++ s;
|
||||
}
|
||||
return numberToString( c, s + 2, 16UL );
|
||||
}
|
||||
}
|
||||
|
||||
char *charToString( char c, char *s )
|
||||
{
|
||||
return charToString( (unsigned long)(unsigned char)c, s );
|
||||
}
|
||||
|
||||
char *bytesToString( const unsigned char *bytes, unsigned numBytes, unsigned maxBytes, char *s )
|
||||
{
|
||||
bool truncate = (numBytes > maxBytes);
|
||||
if ( truncate )
|
||||
numBytes = maxBytes;
|
||||
|
||||
s = copyString( s, "{ " );
|
||||
for ( unsigned i = 0; i < numBytes; ++ i, ++ bytes )
|
||||
s = copyString( copyString( s, byteToHex( *bytes ) ), " " );
|
||||
if ( truncate )
|
||||
s = copyString( s, "..." );
|
||||
return copyString( s, " }" );
|
||||
}
|
||||
|
||||
#ifndef CXXTEST_USER_VALUE_TRAITS
|
||||
unsigned ValueTraits<const double>::requiredDigitsOnLeft( double t )
|
||||
{
|
||||
unsigned digits = 1;
|
||||
for ( t = (t < 0.0) ? -t : t; t > 1.0; t /= BASE )
|
||||
++ digits;
|
||||
return digits;
|
||||
}
|
||||
|
||||
char *ValueTraits<const double>::doNegative( double &t )
|
||||
{
|
||||
if ( t >= 0 )
|
||||
return _asString;
|
||||
_asString[0] = '-';
|
||||
t = -t;
|
||||
return _asString + 1;
|
||||
}
|
||||
|
||||
void ValueTraits<const double>::hugeNumber( double t )
|
||||
{
|
||||
char *s = doNegative( t );
|
||||
s = doubleToString( t, s, 0, 1 );
|
||||
s = copyString( s, "." );
|
||||
s = doubleToString( t, s, 1, DIGITS_ON_RIGHT );
|
||||
s = copyString( s, "E" );
|
||||
s = numberToString( requiredDigitsOnLeft( t ) - 1, s );
|
||||
}
|
||||
|
||||
void ValueTraits<const double>::normalNumber( double t )
|
||||
{
|
||||
char *s = doNegative( t );
|
||||
s = doubleToString( t, s );
|
||||
s = copyString( s, "." );
|
||||
for ( unsigned i = 0; i < DIGITS_ON_RIGHT; ++ i )
|
||||
s = numberToString( (unsigned)(t *= BASE) % BASE, s );
|
||||
}
|
||||
|
||||
char *ValueTraits<const double>::doubleToString( double t, char *s, unsigned skip, unsigned max )
|
||||
{
|
||||
return numberToString<double>( t, s, BASE, skip, max );
|
||||
}
|
||||
#endif // !CXXTEST_USER_VALUE_TRAITS
|
||||
}
|
||||
|
||||
#endif // __cxxtest__ValueTraits_cpp__
|
||||
386
test/cxxtest/cxxtest/ValueTraits.h
Normal file
386
test/cxxtest/cxxtest/ValueTraits.h
Normal file
@@ -0,0 +1,386 @@
|
||||
#ifndef __cxxtest__ValueTraits_h__
|
||||
#define __cxxtest__ValueTraits_h__
|
||||
|
||||
//
|
||||
// ValueTraits are used by CxxTest to convert arbitrary
|
||||
// values used in TS_ASSERT_EQUALS() to a string representation.
|
||||
//
|
||||
// This header file contains value traits for builtin integral types.
|
||||
// To declare value traits for new types you should instantiate the class
|
||||
// ValueTraits<YourClass>.
|
||||
//
|
||||
|
||||
#include <cxxtest/Flags.h>
|
||||
|
||||
#ifdef _CXXTEST_OLD_TEMPLATE_SYNTAX
|
||||
# define CXXTEST_TEMPLATE_INSTANTIATION
|
||||
#else // !_CXXTEST_OLD_TEMPLATE_SYNTAX
|
||||
# define CXXTEST_TEMPLATE_INSTANTIATION template<>
|
||||
#endif // _CXXTEST_OLD_TEMPLATE_SYNTAX
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
/// remove_const
|
||||
template<typename T>
|
||||
struct remove_const
|
||||
{ typedef T type; };
|
||||
|
||||
template<typename T>
|
||||
struct remove_const<T const>
|
||||
{ typedef T type; };
|
||||
|
||||
//
|
||||
// This is how we use the value traits
|
||||
//
|
||||
# define TS_AS_STRING(x) CxxTest::traits(x).asString()
|
||||
|
||||
//
|
||||
// Char representation of a digit
|
||||
//
|
||||
char digitToChar( unsigned digit );
|
||||
|
||||
//
|
||||
// Convert byte value to hex digits
|
||||
// Returns pointer to internal buffer
|
||||
//
|
||||
const char *byteToHex( unsigned char byte );
|
||||
|
||||
//
|
||||
// Convert byte values to string
|
||||
// Returns one past the copied data
|
||||
//
|
||||
char *bytesToString( const unsigned char *bytes, unsigned numBytes, unsigned maxBytes, char *s );
|
||||
|
||||
//
|
||||
// Copy a string.
|
||||
// Returns one past the end of the destination string
|
||||
// Remember -- we can't use the standard library!
|
||||
//
|
||||
char *copyString( char *dst, const char *src );
|
||||
|
||||
//
|
||||
// Compare two strings.
|
||||
// Remember -- we can't use the standard library!
|
||||
//
|
||||
bool stringsEqual( const char *s1, const char *s2 );
|
||||
|
||||
//
|
||||
// Represent a character value as a string
|
||||
// Returns one past the end of the string
|
||||
// This will be the actual char if printable or '\xXXXX' otherwise
|
||||
//
|
||||
char *charToString( unsigned long c, char *s );
|
||||
|
||||
//
|
||||
// Prevent problems with negative (signed char)s
|
||||
//
|
||||
char *charToString( char c, char *s );
|
||||
|
||||
//
|
||||
// The default ValueTraits class dumps up to 8 bytes as hex values
|
||||
//
|
||||
template<class T>
|
||||
class ValueTraits
|
||||
{
|
||||
enum { MAX_BYTES = 8 };
|
||||
char _asString[sizeof("{ ") + sizeof("XX ") * MAX_BYTES + sizeof("... }")];
|
||||
|
||||
public:
|
||||
ValueTraits( const T &t ) { bytesToString( (const unsigned char *)&t, sizeof(T), MAX_BYTES, _asString ); }
|
||||
const char *asString( void ) const { return _asString; }
|
||||
};
|
||||
|
||||
//
|
||||
// traits( T t )
|
||||
// Creates an object of type ValueTraits<T>
|
||||
//
|
||||
template<class T>
|
||||
inline ValueTraits<T> traits( T t )
|
||||
{
|
||||
return ValueTraits<T>( t );
|
||||
}
|
||||
|
||||
//
|
||||
// You can duplicate the implementation of an existing ValueTraits
|
||||
//
|
||||
# define CXXTEST_COPY_TRAITS(CXXTEST_NEW_CLASS, CXXTEST_OLD_CLASS) \
|
||||
CXXTEST_TEMPLATE_INSTANTIATION \
|
||||
class ValueTraits< CXXTEST_NEW_CLASS > \
|
||||
{ \
|
||||
ValueTraits< CXXTEST_OLD_CLASS > _old; \
|
||||
public: \
|
||||
ValueTraits( CXXTEST_NEW_CLASS n ) : _old( static_cast<remove_const<CXXTEST_OLD_CLASS>::type>(n) ) {} \
|
||||
const char *asString( void ) const { return _old.asString(); } \
|
||||
}
|
||||
|
||||
//
|
||||
// Certain compilers need separate declarations for T and const T
|
||||
//
|
||||
# ifdef _CXXTEST_NO_COPY_CONST
|
||||
# define CXXTEST_COPY_CONST_TRAITS(CXXTEST_CLASS)
|
||||
# else // !_CXXTEST_NO_COPY_CONST
|
||||
# define CXXTEST_COPY_CONST_TRAITS(CXXTEST_CLASS) CXXTEST_COPY_TRAITS(CXXTEST_CLASS, const CXXTEST_CLASS)
|
||||
# endif // _CXXTEST_NO_COPY_CONST
|
||||
|
||||
//
|
||||
// Avoid compiler warnings about unsigned types always >= 0
|
||||
//
|
||||
template<class N> inline bool negative( N n ) { return n < 0; }
|
||||
template<class N> inline N abs( N n ) { return negative(n) ? -n : n; }
|
||||
|
||||
# define CXXTEST_NON_NEGATIVE(Type) \
|
||||
CXXTEST_TEMPLATE_INSTANTIATION \
|
||||
inline bool negative<Type>( Type ) { return false; } \
|
||||
CXXTEST_TEMPLATE_INSTANTIATION \
|
||||
inline Type abs<Type>( Type value ) { return value; }
|
||||
|
||||
CXXTEST_NON_NEGATIVE( bool )
|
||||
CXXTEST_NON_NEGATIVE( unsigned char )
|
||||
CXXTEST_NON_NEGATIVE( unsigned short int )
|
||||
CXXTEST_NON_NEGATIVE( unsigned int )
|
||||
CXXTEST_NON_NEGATIVE( unsigned long int )
|
||||
# ifdef _CXXTEST_LONGLONG
|
||||
CXXTEST_NON_NEGATIVE( unsigned _CXXTEST_LONGLONG )
|
||||
# endif // _CXXTEST_LONGLONG
|
||||
|
||||
//
|
||||
// Represent (integral) number as a string
|
||||
// Returns one past the end of the string
|
||||
// Remember -- we can't use the standard library!
|
||||
//
|
||||
template<class N>
|
||||
char *numberToString( N n, char *s,
|
||||
N base = 10,
|
||||
unsigned skipDigits = 0,
|
||||
unsigned maxDigits = (unsigned)-1 )
|
||||
{
|
||||
if ( negative(n) ) {
|
||||
*s++ = '-';
|
||||
n = abs(n);
|
||||
}
|
||||
|
||||
N digit = 1;
|
||||
while ( digit <= (n / base) )
|
||||
digit *= base;
|
||||
N digitValue;
|
||||
for ( ; digit >= 1 && skipDigits; n -= digit * digitValue, digit /= base, -- skipDigits )
|
||||
digitValue = (unsigned)(n / digit);
|
||||
for ( ; digit >= 1 && maxDigits; n -= digit * digitValue, digit /= base, -- maxDigits )
|
||||
*s++ = digitToChar( (unsigned)(digitValue = (unsigned)(n / digit)) );
|
||||
|
||||
*s = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
//
|
||||
// All the specific ValueTraits follow.
|
||||
// You can #define CXXTEST_USER_VALUE_TRAITS if you don't want them
|
||||
//
|
||||
|
||||
#ifndef CXXTEST_USER_VALUE_TRAITS
|
||||
//
|
||||
// ValueTraits: const char * const &
|
||||
// This is used for printing strings, as in TS_FAIL( "Message" )
|
||||
//
|
||||
CXXTEST_TEMPLATE_INSTANTIATION
|
||||
class ValueTraits<const char * const &>
|
||||
{
|
||||
ValueTraits &operator=( const ValueTraits & );
|
||||
const char *_asString;
|
||||
|
||||
public:
|
||||
ValueTraits( const char * const &value ) : _asString( value ) {}
|
||||
ValueTraits( const ValueTraits &other ) : _asString( other._asString ) {}
|
||||
const char *asString( void ) const { return _asString; }
|
||||
};
|
||||
|
||||
CXXTEST_COPY_TRAITS( const char *, const char * const & );
|
||||
CXXTEST_COPY_TRAITS( char *, const char * const & );
|
||||
|
||||
//
|
||||
// ValueTraits: bool
|
||||
//
|
||||
CXXTEST_TEMPLATE_INSTANTIATION
|
||||
class ValueTraits<const bool>
|
||||
{
|
||||
bool _value;
|
||||
|
||||
public:
|
||||
ValueTraits( const bool value ) : _value( value ) {}
|
||||
const char *asString( void ) const { return _value ? "true" : "false"; }
|
||||
};
|
||||
|
||||
CXXTEST_COPY_CONST_TRAITS( bool );
|
||||
|
||||
# ifdef _CXXTEST_LONGLONG
|
||||
//
|
||||
// ValueTraits: signed long long
|
||||
//
|
||||
CXXTEST_TEMPLATE_INSTANTIATION
|
||||
class ValueTraits<const signed _CXXTEST_LONGLONG>
|
||||
{
|
||||
typedef _CXXTEST_LONGLONG T;
|
||||
char _asString[2 + 3 * sizeof(T)];
|
||||
public:
|
||||
ValueTraits( T t ) { numberToString<T>( t, _asString ); }
|
||||
const char *asString( void ) const { return _asString; }
|
||||
};
|
||||
|
||||
CXXTEST_COPY_CONST_TRAITS( signed _CXXTEST_LONGLONG );
|
||||
|
||||
//
|
||||
// ValueTraits: unsigned long long
|
||||
//
|
||||
CXXTEST_TEMPLATE_INSTANTIATION
|
||||
class ValueTraits<const unsigned _CXXTEST_LONGLONG>
|
||||
{
|
||||
typedef unsigned _CXXTEST_LONGLONG T;
|
||||
char _asString[1 + 3 * sizeof(T)];
|
||||
public:
|
||||
ValueTraits( T t ) { numberToString<T>( t, _asString ); }
|
||||
const char *asString( void ) const { return _asString; }
|
||||
};
|
||||
|
||||
CXXTEST_COPY_CONST_TRAITS( unsigned _CXXTEST_LONGLONG );
|
||||
# endif // _CXXTEST_LONGLONG
|
||||
|
||||
//
|
||||
// ValueTraits: signed long
|
||||
//
|
||||
CXXTEST_TEMPLATE_INSTANTIATION
|
||||
class ValueTraits<const signed long int>
|
||||
{
|
||||
typedef signed long int T;
|
||||
char _asString[2 + 3 * sizeof(T)];
|
||||
public:
|
||||
ValueTraits( T t ) { numberToString<T>( t, _asString ); }
|
||||
const char *asString( void ) const { return _asString; }
|
||||
};
|
||||
|
||||
CXXTEST_COPY_CONST_TRAITS( signed long int );
|
||||
|
||||
//
|
||||
// ValueTraits: unsigned long
|
||||
//
|
||||
CXXTEST_TEMPLATE_INSTANTIATION
|
||||
class ValueTraits<const unsigned long int>
|
||||
{
|
||||
typedef unsigned long int T;
|
||||
char _asString[1 + 3 * sizeof(T)];
|
||||
public:
|
||||
ValueTraits( T t ) { numberToString<T>( t, _asString ); }
|
||||
const char *asString( void ) const { return _asString; }
|
||||
};
|
||||
|
||||
CXXTEST_COPY_CONST_TRAITS( unsigned long int );
|
||||
|
||||
//
|
||||
// All decimals are the same as the long version
|
||||
//
|
||||
|
||||
CXXTEST_COPY_TRAITS( const signed int, const signed long int );
|
||||
CXXTEST_COPY_TRAITS( const unsigned int, const unsigned long int );
|
||||
CXXTEST_COPY_TRAITS( const signed short int, const signed long int );
|
||||
CXXTEST_COPY_TRAITS( const unsigned short int, const unsigned long int );
|
||||
CXXTEST_COPY_TRAITS( const unsigned char, const unsigned long int );
|
||||
|
||||
CXXTEST_COPY_CONST_TRAITS( signed int );
|
||||
CXXTEST_COPY_CONST_TRAITS( unsigned int );
|
||||
CXXTEST_COPY_CONST_TRAITS( signed short int );
|
||||
CXXTEST_COPY_CONST_TRAITS( unsigned short int );
|
||||
CXXTEST_COPY_CONST_TRAITS( unsigned char );
|
||||
|
||||
//
|
||||
// ValueTraits: char
|
||||
// Returns 'x' for printable chars, '\x??' for others
|
||||
//
|
||||
CXXTEST_TEMPLATE_INSTANTIATION
|
||||
class ValueTraits<const char>
|
||||
{
|
||||
char _asString[sizeof("'\\xXX'")];
|
||||
public:
|
||||
ValueTraits( char c ) { copyString( charToString( c, copyString( _asString, "'" ) ), "'" ); }
|
||||
const char *asString( void ) const { return _asString; }
|
||||
};
|
||||
|
||||
CXXTEST_COPY_CONST_TRAITS( char );
|
||||
|
||||
//
|
||||
// ValueTraits: signed char
|
||||
// Same as char, some compilers need it
|
||||
//
|
||||
CXXTEST_COPY_TRAITS( const signed char, const char );
|
||||
CXXTEST_COPY_CONST_TRAITS( signed char );
|
||||
|
||||
//
|
||||
// ValueTraits: double
|
||||
//
|
||||
CXXTEST_TEMPLATE_INSTANTIATION
|
||||
class ValueTraits<const double>
|
||||
{
|
||||
public:
|
||||
ValueTraits( double t )
|
||||
{
|
||||
( requiredDigitsOnLeft( t ) > MAX_DIGITS_ON_LEFT ) ?
|
||||
hugeNumber( t ) :
|
||||
normalNumber( t );
|
||||
}
|
||||
|
||||
const char *asString( void ) const { return _asString; }
|
||||
|
||||
private:
|
||||
enum { MAX_DIGITS_ON_LEFT = 24, DIGITS_ON_RIGHT = 4, BASE = 10 };
|
||||
char _asString[1 + MAX_DIGITS_ON_LEFT + 1 + DIGITS_ON_RIGHT + 1];
|
||||
|
||||
static unsigned requiredDigitsOnLeft( double t );
|
||||
char *doNegative( double &t );
|
||||
void hugeNumber( double t );
|
||||
void normalNumber( double t );
|
||||
char *doubleToString( double t, char *s, unsigned skip = 0, unsigned max = (unsigned)-1 );
|
||||
};
|
||||
|
||||
CXXTEST_COPY_CONST_TRAITS( double );
|
||||
|
||||
//
|
||||
// ValueTraits: float
|
||||
//
|
||||
CXXTEST_COPY_TRAITS( const float, const double );
|
||||
CXXTEST_COPY_CONST_TRAITS( float );
|
||||
#endif // !CXXTEST_USER_VALUE_TRAITS
|
||||
}
|
||||
|
||||
#ifdef _CXXTEST_HAVE_STD
|
||||
# include <cxxtest/StdValueTraits.h>
|
||||
#endif // _CXXTEST_HAVE_STD
|
||||
|
||||
//
|
||||
// CXXTEST_ENUM_TRAITS
|
||||
//
|
||||
#define CXXTEST_ENUM_TRAITS( TYPE, VALUES ) \
|
||||
namespace CxxTest \
|
||||
{ \
|
||||
CXXTEST_TEMPLATE_INSTANTIATION \
|
||||
class ValueTraits<TYPE> \
|
||||
{ \
|
||||
TYPE _value; \
|
||||
char _fallback[sizeof("(" #TYPE ")") + 3 * sizeof(TYPE)]; \
|
||||
public: \
|
||||
ValueTraits( TYPE value ) { \
|
||||
_value = value; \
|
||||
numberToString<unsigned long int>( _value, copyString( _fallback, "(" #TYPE ")" ) ); \
|
||||
} \
|
||||
const char *asString( void ) const \
|
||||
{ \
|
||||
switch ( _value ) \
|
||||
{ \
|
||||
VALUES \
|
||||
default: return _fallback; \
|
||||
} \
|
||||
} \
|
||||
}; \
|
||||
}
|
||||
|
||||
#define CXXTEST_ENUM_MEMBER( MEMBER ) \
|
||||
case MEMBER: return #MEMBER;
|
||||
|
||||
#endif // __cxxtest__ValueTraits_h__
|
||||
531
test/cxxtest/cxxtest/Win32Gui.h
Normal file
531
test/cxxtest/cxxtest/Win32Gui.h
Normal file
@@ -0,0 +1,531 @@
|
||||
#ifndef __cxxtest__Win32Gui_h__
|
||||
#define __cxxtest__Win32Gui_h__
|
||||
|
||||
//
|
||||
// The Win32Gui displays a simple progress bar using the Win32 API.
|
||||
//
|
||||
// It accepts the following command line options:
|
||||
// -minimized Start minimized, pop up on error
|
||||
// -keep Don't close the window at the end
|
||||
// -title TITLE Set the window caption
|
||||
//
|
||||
// If both -minimized and -keep are specified, GUI will only keep the
|
||||
// window if it's in focus.
|
||||
//
|
||||
// N.B. If you're wondering why this class doesn't use any standard
|
||||
// library or STL (<string> would have been nice) it's because it only
|
||||
// uses "straight" Win32 API.
|
||||
//
|
||||
|
||||
#include <cxxtest/Gui.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class Win32Gui : public GuiListener
|
||||
{
|
||||
public:
|
||||
void enterGui( int &argc, char **argv )
|
||||
{
|
||||
parseCommandLine( argc, argv );
|
||||
}
|
||||
|
||||
void enterWorld( const WorldDescription &wd )
|
||||
{
|
||||
getTotalTests( wd );
|
||||
_testsDone = 0;
|
||||
startGuiThread();
|
||||
}
|
||||
|
||||
void guiEnterSuite( const char *suiteName )
|
||||
{
|
||||
showSuiteName( suiteName );
|
||||
reset( _suiteStart );
|
||||
}
|
||||
|
||||
void guiEnterTest( const char *suiteName, const char *testName )
|
||||
{
|
||||
++ _testsDone;
|
||||
setTestCaption( suiteName, testName );
|
||||
showTestName( testName );
|
||||
showTestsDone();
|
||||
progressBarMessage( PBM_STEPIT );
|
||||
reset( _testStart );
|
||||
}
|
||||
|
||||
void yellowBar()
|
||||
{
|
||||
setColor( 255, 255, 0 );
|
||||
setIcon( IDI_WARNING );
|
||||
getTotalTests();
|
||||
}
|
||||
|
||||
void redBar()
|
||||
{
|
||||
if ( _startMinimized )
|
||||
showMainWindow( SW_SHOWNORMAL );
|
||||
setColor( 255, 0, 0 );
|
||||
setIcon( IDI_ERROR );
|
||||
getTotalTests();
|
||||
}
|
||||
|
||||
void leaveGui()
|
||||
{
|
||||
if ( keep() )
|
||||
{
|
||||
showSummary();
|
||||
WaitForSingleObject( _gui, INFINITE );
|
||||
}
|
||||
DestroyWindow( _mainWindow );
|
||||
}
|
||||
|
||||
private:
|
||||
const char *_title;
|
||||
bool _startMinimized, _keep;
|
||||
HANDLE _gui;
|
||||
WNDCLASSEX _windowClass;
|
||||
HWND _mainWindow, _progressBar, _statusBar;
|
||||
HANDLE _canStartTests;
|
||||
unsigned _numTotalTests, _testsDone;
|
||||
char _strTotalTests[WorldDescription::MAX_STRLEN_TOTAL_TESTS];
|
||||
enum {
|
||||
STATUS_SUITE_NAME, STATUS_SUITE_TIME,
|
||||
STATUS_TEST_NAME, STATUS_TEST_TIME,
|
||||
STATUS_TESTS_DONE, STATUS_WORLD_TIME,
|
||||
STATUS_TOTAL_PARTS
|
||||
};
|
||||
int _statusWidths[STATUS_TOTAL_PARTS];
|
||||
unsigned _statusOffsets[STATUS_TOTAL_PARTS];
|
||||
unsigned _statusTotal;
|
||||
char _statusTestsDone[sizeof("1000000000 of (100%)") + WorldDescription::MAX_STRLEN_TOTAL_TESTS];
|
||||
DWORD _worldStart, _suiteStart, _testStart;
|
||||
char _timeString[sizeof("00:00:00")];
|
||||
|
||||
void parseCommandLine( int argc, char **argv )
|
||||
{
|
||||
_startMinimized = _keep = false;
|
||||
_title = argv[0];
|
||||
|
||||
for ( int i = 1; i < argc; ++ i )
|
||||
{
|
||||
if ( !lstrcmpA( argv[i], "-minimized" ) )
|
||||
_startMinimized = true;
|
||||
else if ( !lstrcmpA( argv[i], "-keep" ) )
|
||||
_keep = true;
|
||||
else if ( !lstrcmpA( argv[i], "-title" ) && (i + 1 < argc) )
|
||||
_title = argv[++i];
|
||||
}
|
||||
}
|
||||
|
||||
void getTotalTests()
|
||||
{
|
||||
getTotalTests( tracker().world() );
|
||||
}
|
||||
|
||||
void getTotalTests( const WorldDescription &wd )
|
||||
{
|
||||
_numTotalTests = wd.numTotalTests();
|
||||
wd.strTotalTests( _strTotalTests );
|
||||
}
|
||||
|
||||
void startGuiThread()
|
||||
{
|
||||
_canStartTests = CreateEvent( NULL, TRUE, FALSE, NULL );
|
||||
DWORD threadId;
|
||||
_gui = CreateThread( NULL, 0, &(Win32Gui::guiThread), (LPVOID)this, 0, &threadId );
|
||||
WaitForSingleObject( _canStartTests, INFINITE );
|
||||
}
|
||||
|
||||
static DWORD WINAPI guiThread( LPVOID parameter )
|
||||
{
|
||||
((Win32Gui *)parameter)->gui();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gui()
|
||||
{
|
||||
registerWindowClass();
|
||||
createMainWindow();
|
||||
initCommonControls();
|
||||
createProgressBar();
|
||||
createStatusBar();
|
||||
centerMainWindow();
|
||||
showMainWindow();
|
||||
startTimer();
|
||||
startTests();
|
||||
|
||||
messageLoop();
|
||||
}
|
||||
|
||||
void registerWindowClass()
|
||||
{
|
||||
_windowClass.cbSize = sizeof(_windowClass);
|
||||
_windowClass.style = CS_HREDRAW | CS_VREDRAW;
|
||||
_windowClass.lpfnWndProc = &(Win32Gui::windowProcedure);
|
||||
_windowClass.cbClsExtra = 0;
|
||||
_windowClass.cbWndExtra = sizeof(LONG);
|
||||
_windowClass.hInstance = (HINSTANCE)NULL;
|
||||
_windowClass.hIcon = (HICON)NULL;
|
||||
_windowClass.hCursor = (HCURSOR)NULL;
|
||||
_windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||
_windowClass.lpszMenuName = NULL;
|
||||
_windowClass.lpszClassName = TEXT("CxxTest Window Class");
|
||||
_windowClass.hIconSm = (HICON)NULL;
|
||||
|
||||
RegisterClassEx( &_windowClass );
|
||||
}
|
||||
|
||||
void createMainWindow()
|
||||
{
|
||||
_mainWindow = createWindow( _windowClass.lpszClassName, WS_OVERLAPPEDWINDOW );
|
||||
}
|
||||
|
||||
void initCommonControls()
|
||||
{
|
||||
HMODULE dll = LoadLibraryA( "comctl32.dll" );
|
||||
if ( !dll )
|
||||
return;
|
||||
|
||||
typedef void (WINAPI *FUNC)( void );
|
||||
FUNC func = (FUNC)GetProcAddress( dll, "InitCommonControls" );
|
||||
if ( !func )
|
||||
return;
|
||||
|
||||
func();
|
||||
}
|
||||
|
||||
void createProgressBar()
|
||||
{
|
||||
_progressBar = createWindow( PROGRESS_CLASS, WS_CHILD | WS_VISIBLE | PBS_SMOOTH, _mainWindow );
|
||||
|
||||
#ifdef PBM_SETRANGE32
|
||||
progressBarMessage( PBM_SETRANGE32, 0, _numTotalTests );
|
||||
#else // No PBM_SETRANGE32, use PBM_SETRANGE
|
||||
progressBarMessage( PBM_SETRANGE, 0, MAKELPARAM( 0, (WORD)_numTotalTests ) );
|
||||
#endif // PBM_SETRANGE32
|
||||
progressBarMessage( PBM_SETPOS, 0 );
|
||||
progressBarMessage( PBM_SETSTEP, 1 );
|
||||
greenBar();
|
||||
UpdateWindow( _progressBar );
|
||||
}
|
||||
|
||||
void createStatusBar()
|
||||
{
|
||||
_statusBar = createWindow( STATUSCLASSNAME, WS_CHILD | WS_VISIBLE, _mainWindow );
|
||||
setRatios( 4, 1, 3, 1, 3, 1 );
|
||||
}
|
||||
|
||||
void setRatios( unsigned suiteNameRatio, unsigned suiteTimeRatio,
|
||||
unsigned testNameRatio, unsigned testTimeRatio,
|
||||
unsigned testsDoneRatio, unsigned worldTimeRatio )
|
||||
{
|
||||
_statusTotal = 0;
|
||||
_statusOffsets[STATUS_SUITE_NAME] = (_statusTotal += suiteNameRatio);
|
||||
_statusOffsets[STATUS_SUITE_TIME] = (_statusTotal += suiteTimeRatio);
|
||||
_statusOffsets[STATUS_TEST_NAME] = (_statusTotal += testNameRatio);
|
||||
_statusOffsets[STATUS_TEST_TIME] = (_statusTotal += testTimeRatio);
|
||||
_statusOffsets[STATUS_TESTS_DONE] = (_statusTotal += testsDoneRatio);
|
||||
_statusOffsets[STATUS_WORLD_TIME] = (_statusTotal += worldTimeRatio);
|
||||
}
|
||||
|
||||
HWND createWindow( LPCTSTR className, DWORD style, HWND parent = (HWND)NULL )
|
||||
{
|
||||
return CreateWindow( className, NULL, style, 0, 0, 0, 0, parent,
|
||||
(HMENU)NULL, (HINSTANCE)NULL, (LPVOID)this );
|
||||
}
|
||||
|
||||
void progressBarMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 )
|
||||
{
|
||||
SendMessage( _progressBar, message, wParam, lParam );
|
||||
}
|
||||
|
||||
void centerMainWindow()
|
||||
{
|
||||
RECT screen;
|
||||
getScreenArea( screen );
|
||||
|
||||
LONG screenWidth = screen.right - screen.left;
|
||||
LONG screenHeight = screen.bottom - screen.top;
|
||||
|
||||
LONG xCenter = (screen.right + screen.left) / 2;
|
||||
LONG yCenter = (screen.bottom + screen.top) / 2;
|
||||
|
||||
LONG windowWidth = (screenWidth * 4) / 5;
|
||||
LONG windowHeight = screenHeight / 10;
|
||||
LONG minimumHeight = 2 * (GetSystemMetrics( SM_CYCAPTION ) + GetSystemMetrics( SM_CYFRAME ));
|
||||
if ( windowHeight < minimumHeight )
|
||||
windowHeight = minimumHeight;
|
||||
|
||||
SetWindowPos( _mainWindow, HWND_TOP,
|
||||
xCenter - (windowWidth / 2), yCenter - (windowHeight / 2),
|
||||
windowWidth, windowHeight, 0 );
|
||||
}
|
||||
|
||||
void getScreenArea( RECT &area )
|
||||
{
|
||||
if ( !getScreenAreaWithoutTaskbar( area ) )
|
||||
getWholeScreenArea( area );
|
||||
}
|
||||
|
||||
bool getScreenAreaWithoutTaskbar( RECT &area )
|
||||
{
|
||||
return (SystemParametersInfo( SPI_GETWORKAREA, sizeof(RECT), &area, 0 ) != 0);
|
||||
}
|
||||
|
||||
void getWholeScreenArea( RECT &area )
|
||||
{
|
||||
area.left = area.top = 0;
|
||||
area.right = GetSystemMetrics( SM_CXSCREEN );
|
||||
area.bottom = GetSystemMetrics( SM_CYSCREEN );
|
||||
}
|
||||
|
||||
void showMainWindow()
|
||||
{
|
||||
showMainWindow( _startMinimized ? SW_MINIMIZE : SW_SHOWNORMAL );
|
||||
UpdateWindow( _mainWindow );
|
||||
}
|
||||
|
||||
void showMainWindow( int mode )
|
||||
{
|
||||
ShowWindow( _mainWindow, mode );
|
||||
}
|
||||
|
||||
enum { TIMER_ID = 1, TIMER_DELAY = 1000 };
|
||||
|
||||
void startTimer()
|
||||
{
|
||||
reset( _worldStart );
|
||||
reset( _suiteStart );
|
||||
reset( _testStart );
|
||||
SetTimer( _mainWindow, TIMER_ID, TIMER_DELAY, 0 );
|
||||
}
|
||||
|
||||
void reset( DWORD &tick )
|
||||
{
|
||||
tick = GetTickCount();
|
||||
}
|
||||
|
||||
void startTests()
|
||||
{
|
||||
SetEvent( _canStartTests );
|
||||
}
|
||||
|
||||
void messageLoop()
|
||||
{
|
||||
MSG message;
|
||||
while ( BOOL haveMessage = GetMessage( &message, NULL, 0, 0 ) )
|
||||
if ( haveMessage != -1 )
|
||||
DispatchMessage( &message );
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK windowProcedure( HWND window, UINT message, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
if ( message == WM_CREATE )
|
||||
setUp( window, (LPCREATESTRUCT)lParam );
|
||||
|
||||
Win32Gui *that = (Win32Gui *)GetWindowLong( window, GWL_USERDATA );
|
||||
return that->handle( window, message, wParam, lParam );
|
||||
}
|
||||
|
||||
static void setUp( HWND window, LPCREATESTRUCT create )
|
||||
{
|
||||
SetWindowLong( window, GWL_USERDATA, (LONG)create->lpCreateParams );
|
||||
}
|
||||
|
||||
LRESULT handle( HWND window, UINT message, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
switch ( message )
|
||||
{
|
||||
case WM_SIZE: resizeControls(); break;
|
||||
|
||||
case WM_TIMER: updateTime(); break;
|
||||
|
||||
case WM_CLOSE:
|
||||
case WM_DESTROY:
|
||||
case WM_QUIT:
|
||||
ExitProcess( 0 );
|
||||
|
||||
default: return DefWindowProc( window, message, wParam, lParam );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void resizeControls()
|
||||
{
|
||||
RECT r;
|
||||
GetClientRect( _mainWindow, &r );
|
||||
LONG width = r.right - r.left;
|
||||
LONG height = r.bottom - r.top;
|
||||
|
||||
GetClientRect( _statusBar, &r );
|
||||
LONG statusHeight = r.bottom - r.top;
|
||||
LONG resizeGripWidth = statusHeight;
|
||||
LONG progressHeight = height - statusHeight;
|
||||
|
||||
SetWindowPos( _progressBar, HWND_TOP, 0, 0, width, progressHeight, 0 );
|
||||
SetWindowPos( _statusBar, HWND_TOP, 0, progressHeight, width, statusHeight, 0 );
|
||||
setStatusParts( width - resizeGripWidth );
|
||||
}
|
||||
|
||||
void setStatusParts( LONG width )
|
||||
{
|
||||
for ( unsigned i = 0; i < STATUS_TOTAL_PARTS; ++ i )
|
||||
_statusWidths[i] = (width * _statusOffsets[i]) / _statusTotal;
|
||||
|
||||
statusBarMessage( SB_SETPARTS, STATUS_TOTAL_PARTS, _statusWidths );
|
||||
}
|
||||
|
||||
void statusBarMessage( UINT message, WPARAM wParam = 0, const void *lParam = 0 )
|
||||
{
|
||||
SendMessage( _statusBar, message, wParam, (LPARAM)lParam );
|
||||
}
|
||||
|
||||
void greenBar()
|
||||
{
|
||||
setColor( 0, 255, 0 );
|
||||
setIcon( IDI_INFORMATION );
|
||||
}
|
||||
|
||||
#ifdef PBM_SETBARCOLOR
|
||||
void setColor( BYTE red, BYTE green, BYTE blue )
|
||||
{
|
||||
progressBarMessage( PBM_SETBARCOLOR, 0, RGB( red, green, blue ) );
|
||||
}
|
||||
#else // !PBM_SETBARCOLOR
|
||||
void setColor( BYTE, BYTE, BYTE )
|
||||
{
|
||||
}
|
||||
#endif // PBM_SETBARCOLOR
|
||||
|
||||
void setIcon( LPCTSTR icon )
|
||||
{
|
||||
SendMessage( _mainWindow, WM_SETICON, ICON_BIG, (LPARAM)loadStandardIcon( icon ) );
|
||||
}
|
||||
|
||||
HICON loadStandardIcon( LPCTSTR icon )
|
||||
{
|
||||
return LoadIcon( (HINSTANCE)NULL, icon );
|
||||
}
|
||||
|
||||
void setTestCaption( const char *suiteName, const char *testName )
|
||||
{
|
||||
setCaption( suiteName, "::", testName, "()" );
|
||||
}
|
||||
|
||||
void setCaption( const char *a = "", const char *b = "", const char *c = "", const char *d = "" )
|
||||
{
|
||||
unsigned length = lstrlenA( _title ) + sizeof( " - " ) +
|
||||
lstrlenA( a ) + lstrlenA( b ) + lstrlenA( c ) + lstrlenA( d );
|
||||
char *name = allocate( length );
|
||||
lstrcpyA( name, _title );
|
||||
lstrcatA( name, " - " );
|
||||
lstrcatA( name, a );
|
||||
lstrcatA( name, b );
|
||||
lstrcatA( name, c );
|
||||
lstrcatA( name, d );
|
||||
SetWindowTextA( _mainWindow, name );
|
||||
deallocate( name );
|
||||
}
|
||||
|
||||
void showSuiteName( const char *suiteName )
|
||||
{
|
||||
setStatusPart( STATUS_SUITE_NAME, suiteName );
|
||||
}
|
||||
|
||||
void showTestName( const char *testName )
|
||||
{
|
||||
setStatusPart( STATUS_TEST_NAME, testName );
|
||||
}
|
||||
|
||||
void showTestsDone()
|
||||
{
|
||||
wsprintfA( _statusTestsDone, "%u of %s (%u%%)",
|
||||
_testsDone, _strTotalTests,
|
||||
(_testsDone * 100) / _numTotalTests );
|
||||
setStatusPart( STATUS_TESTS_DONE, _statusTestsDone );
|
||||
}
|
||||
|
||||
void updateTime()
|
||||
{
|
||||
setStatusTime( STATUS_WORLD_TIME, _worldStart );
|
||||
setStatusTime( STATUS_SUITE_TIME, _suiteStart );
|
||||
setStatusTime( STATUS_TEST_TIME, _testStart );
|
||||
}
|
||||
|
||||
void setStatusTime( unsigned part, DWORD start )
|
||||
{
|
||||
unsigned total = (GetTickCount() - start) / 1000;
|
||||
unsigned hours = total / 3600;
|
||||
unsigned minutes = (total / 60) % 60;
|
||||
unsigned seconds = total % 60;
|
||||
|
||||
if ( hours )
|
||||
wsprintfA( _timeString, "%u:%02u:%02u", hours, minutes, seconds );
|
||||
else
|
||||
wsprintfA( _timeString, "%02u:%02u", minutes, seconds );
|
||||
|
||||
setStatusPart( part, _timeString );
|
||||
}
|
||||
|
||||
bool keep()
|
||||
{
|
||||
if ( !_keep )
|
||||
return false;
|
||||
if ( !_startMinimized )
|
||||
return true;
|
||||
return (_mainWindow == GetForegroundWindow());
|
||||
}
|
||||
|
||||
void showSummary()
|
||||
{
|
||||
stopTimer();
|
||||
setSummaryStatusBar();
|
||||
setSummaryCaption();
|
||||
}
|
||||
|
||||
void setStatusPart( unsigned part, const char *text )
|
||||
{
|
||||
statusBarMessage( SB_SETTEXTA, part, text );
|
||||
}
|
||||
|
||||
void stopTimer()
|
||||
{
|
||||
KillTimer( _mainWindow, TIMER_ID );
|
||||
setStatusTime( STATUS_WORLD_TIME, _worldStart );
|
||||
}
|
||||
|
||||
void setSummaryStatusBar()
|
||||
{
|
||||
setRatios( 0, 0, 0, 0, 1, 1 );
|
||||
resizeControls();
|
||||
|
||||
const char *tests = (_numTotalTests == 1) ? "test" : "tests";
|
||||
if ( tracker().failedTests() )
|
||||
wsprintfA( _statusTestsDone, "Failed %u of %s %s",
|
||||
tracker().failedTests(), _strTotalTests, tests );
|
||||
else
|
||||
wsprintfA( _statusTestsDone, "%s %s passed", _strTotalTests, tests );
|
||||
|
||||
setStatusPart( STATUS_TESTS_DONE, _statusTestsDone );
|
||||
}
|
||||
|
||||
void setSummaryCaption()
|
||||
{
|
||||
setCaption( _statusTestsDone );
|
||||
}
|
||||
|
||||
char *allocate( unsigned length )
|
||||
{
|
||||
return (char *)HeapAlloc( GetProcessHeap(), 0, length );
|
||||
}
|
||||
|
||||
void deallocate( char *data )
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, data );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __cxxtest__Win32Gui_h__
|
||||
327
test/cxxtest/cxxtest/X11Gui.h
Normal file
327
test/cxxtest/cxxtest/X11Gui.h
Normal file
@@ -0,0 +1,327 @@
|
||||
#ifndef __cxxtest__X11Gui_h__
|
||||
#define __cxxtest__X11Gui_h__
|
||||
|
||||
//
|
||||
// X11Gui displays a simple progress bar using X11
|
||||
//
|
||||
// It accepts the following command-line arguments:
|
||||
// -title <title> - Sets the application title
|
||||
// -fn or -font <font> - Sets the font
|
||||
// -bg or -background <color> - Sets the background color (default=Grey)
|
||||
// -fg or -foreground <color> - Sets the text color (default=Black)
|
||||
// -green/-yellow/-red <color> - Sets the colors of the bar
|
||||
//
|
||||
|
||||
#include <cxxtest/Gui.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class X11Gui : public GuiListener
|
||||
{
|
||||
public:
|
||||
void enterGui( int &argc, char **argv )
|
||||
{
|
||||
parseCommandLine( argc, argv );
|
||||
}
|
||||
|
||||
void enterWorld( const WorldDescription &wd )
|
||||
{
|
||||
openDisplay();
|
||||
if ( _display ) {
|
||||
createColors();
|
||||
createWindow();
|
||||
createGc();
|
||||
createFont();
|
||||
centerWindow();
|
||||
initializeEvents();
|
||||
initializeBar( wd );
|
||||
processEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void guiEnterTest( const char *suiteName, const char *testName )
|
||||
{
|
||||
if ( _display ) {
|
||||
++ _testsDone;
|
||||
setWindowName( suiteName, testName );
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
||||
void yellowBar()
|
||||
{
|
||||
if ( _display ) {
|
||||
_barColor = getColor( _yellowName );
|
||||
getTotalTests();
|
||||
processEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void redBar()
|
||||
{
|
||||
if ( _display ) {
|
||||
_barColor = getColor( _redName );
|
||||
getTotalTests();
|
||||
processEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void leaveGui()
|
||||
{
|
||||
if ( _display ) {
|
||||
freeFontInfo();
|
||||
destroyGc();
|
||||
destroyWindow();
|
||||
closeDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const char *_programName;
|
||||
Display *_display;
|
||||
Window _window;
|
||||
unsigned _numTotalTests, _testsDone;
|
||||
char _strTotalTests[WorldDescription::MAX_STRLEN_TOTAL_TESTS];
|
||||
const char *_foregroundName, *_backgroundName;
|
||||
const char *_greenName, *_yellowName, *_redName;
|
||||
unsigned long _foreground, _background, _barColor;
|
||||
int _width, _height;
|
||||
GC _gc;
|
||||
const char *_fontName;
|
||||
XID _fontId;
|
||||
XFontStruct *_fontInfo;
|
||||
int _textHeight, _textDescent;
|
||||
long _eventMask;
|
||||
Colormap _colormap;
|
||||
|
||||
void parseCommandLine( int &argc, char **argv )
|
||||
{
|
||||
_programName = argv[0];
|
||||
|
||||
_fontName = 0;
|
||||
_foregroundName = "Black";
|
||||
_backgroundName = "Grey";
|
||||
_greenName = "Green";
|
||||
_yellowName = "Yellow";
|
||||
_redName = "Red";
|
||||
|
||||
for ( int i = 1; i + 1 < argc; ++ i ) {
|
||||
if ( !strcmp( argv[i], "-title" ) )
|
||||
_programName = argv[++ i];
|
||||
else if ( !strcmp( argv[i], "-fn" ) || !strcmp( argv[i], "-font" ) )
|
||||
_fontName = argv[++ i];
|
||||
else if ( !strcmp( argv[i], "-fg" ) || !strcmp( argv[i], "-foreground" ) )
|
||||
_foregroundName = argv[++ i];
|
||||
else if ( !strcmp( argv[i], "-bg" ) || !strcmp( argv[i], "-background" ) )
|
||||
_backgroundName = argv[++ i];
|
||||
else if ( !strcmp( argv[i], "-green" ) )
|
||||
_greenName = argv[++ i];
|
||||
else if ( !strcmp( argv[i], "-yellow" ) )
|
||||
_yellowName = argv[++ i];
|
||||
else if ( !strcmp( argv[i], "-red" ) )
|
||||
_redName = argv[++ i];
|
||||
}
|
||||
}
|
||||
|
||||
void openDisplay()
|
||||
{
|
||||
_display = XOpenDisplay( NULL );
|
||||
}
|
||||
|
||||
void createColors()
|
||||
{
|
||||
_colormap = DefaultColormap( _display, 0 );
|
||||
_foreground = getColor( _foregroundName );
|
||||
_background = getColor( _backgroundName );
|
||||
}
|
||||
|
||||
unsigned long getColor( const char *colorName )
|
||||
{
|
||||
XColor color;
|
||||
XParseColor( _display, _colormap, colorName, &color );
|
||||
XAllocColor( _display, _colormap, &color );
|
||||
return color.pixel;
|
||||
}
|
||||
|
||||
void createWindow()
|
||||
{
|
||||
_window = XCreateSimpleWindow( _display, RootWindow( _display, 0 ), 0, 0, 1, 1, 0, 0, _background );
|
||||
}
|
||||
|
||||
void createGc()
|
||||
{
|
||||
_gc = XCreateGC( _display, _window, 0, 0 );
|
||||
}
|
||||
|
||||
void createFont()
|
||||
{
|
||||
if ( !loadFont() )
|
||||
useDefaultFont();
|
||||
getFontInfo();
|
||||
_textHeight = _fontInfo->ascent + _fontInfo->descent;
|
||||
_textDescent = _fontInfo->descent;
|
||||
}
|
||||
|
||||
bool loadFont()
|
||||
{
|
||||
if ( !_fontName )
|
||||
return false;
|
||||
_fontId = XLoadFont( _display, _fontName );
|
||||
return (XSetFont( _display, _gc, _fontId ) == Success);
|
||||
}
|
||||
|
||||
void useDefaultFont()
|
||||
{
|
||||
_fontId = XGContextFromGC( _gc );
|
||||
}
|
||||
|
||||
void getFontInfo()
|
||||
{
|
||||
_fontInfo = XQueryFont( _display, _fontId );
|
||||
}
|
||||
|
||||
void freeFontInfo()
|
||||
{
|
||||
XFreeFontInfo( NULL, _fontInfo, 1 );
|
||||
}
|
||||
|
||||
void initializeEvents()
|
||||
{
|
||||
_eventMask = ExposureMask;
|
||||
XSelectInput( _display, _window, _eventMask );
|
||||
}
|
||||
|
||||
void initializeBar( const WorldDescription &wd )
|
||||
{
|
||||
getTotalTests( wd );
|
||||
_testsDone = 0;
|
||||
_barColor = getColor( _greenName );
|
||||
}
|
||||
|
||||
void getTotalTests()
|
||||
{
|
||||
getTotalTests( tracker().world() );
|
||||
}
|
||||
|
||||
void getTotalTests( const WorldDescription &wd )
|
||||
{
|
||||
_numTotalTests = wd.numTotalTests();
|
||||
wd.strTotalTests( _strTotalTests );
|
||||
}
|
||||
|
||||
void centerWindow()
|
||||
{
|
||||
XMapWindow( _display, _window );
|
||||
|
||||
Screen *screen = XDefaultScreenOfDisplay( _display );
|
||||
int screenWidth = WidthOfScreen( screen );
|
||||
int screenHeight = HeightOfScreen( screen );
|
||||
int xCenter = screenWidth / 2;
|
||||
int yCenter = screenHeight / 2;
|
||||
|
||||
_width = (screenWidth * 4) / 5;
|
||||
_height = screenHeight / 14;
|
||||
|
||||
XMoveResizeWindow( _display, _window, xCenter - (_width / 2), yCenter - (_height / 2), _width, _height );
|
||||
}
|
||||
|
||||
void processEvents()
|
||||
{
|
||||
redraw();
|
||||
|
||||
XEvent event;
|
||||
while( XCheckMaskEvent( _display, _eventMask, &event ) )
|
||||
redraw();
|
||||
}
|
||||
|
||||
void setWindowName( const char *suiteName, const char *testName )
|
||||
{
|
||||
unsigned length = strlen( _programName ) + strlen( suiteName ) + strlen( testName ) + sizeof( " - ::()" );
|
||||
char *name = (char *)malloc( length );
|
||||
sprintf( name, "%s - %s::%s()", _programName, suiteName, testName );
|
||||
XSetStandardProperties( _display, _window, name, 0, 0, 0, 0, 0 );
|
||||
free( name );
|
||||
}
|
||||
|
||||
void redraw()
|
||||
{
|
||||
getWindowSize();
|
||||
drawSolidBar();
|
||||
drawDividers();
|
||||
drawPercentage();
|
||||
flush();
|
||||
}
|
||||
|
||||
void getWindowSize()
|
||||
{
|
||||
XWindowAttributes attributes;
|
||||
XGetWindowAttributes( _display, _window, &attributes );
|
||||
_width = attributes.width;
|
||||
_height = attributes.height;
|
||||
}
|
||||
|
||||
void drawSolidBar()
|
||||
{
|
||||
unsigned barWidth = (_width * _testsDone) / _numTotalTests;
|
||||
|
||||
XSetForeground( _display, _gc, _barColor );
|
||||
XFillRectangle( _display, _window, _gc, 0, 0, barWidth, _height );
|
||||
|
||||
XSetForeground( _display, _gc, _background );
|
||||
XFillRectangle( _display, _window, _gc, barWidth, 0, _width + 1 - barWidth, _height );
|
||||
}
|
||||
|
||||
void drawDividers()
|
||||
{
|
||||
if(_width / _numTotalTests < 5)
|
||||
return;
|
||||
for ( unsigned i = 1; i < _testsDone; ++ i ) {
|
||||
int x = (_width * i) / _numTotalTests;
|
||||
XDrawLine( _display, _window, _gc, x, 0, x, _height);
|
||||
}
|
||||
}
|
||||
|
||||
void drawPercentage()
|
||||
{
|
||||
XSetForeground( _display, _gc, _foreground );
|
||||
|
||||
char str[sizeof("1000000000 of ") + sizeof(_strTotalTests) + sizeof(" (100%)")];
|
||||
sprintf( str, "%u of %s (%u%%)", _testsDone, _strTotalTests, (_testsDone * 100) / _numTotalTests );
|
||||
unsigned len = strlen( str );
|
||||
|
||||
int textWidth = XTextWidth( _fontInfo, str, len );
|
||||
|
||||
XDrawString( _display, _window, _gc,
|
||||
(_width - textWidth) / 2, ((_height + _textHeight) / 2) - _textDescent,
|
||||
str, len );
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
XFlush( _display );
|
||||
}
|
||||
|
||||
void destroyGc()
|
||||
{
|
||||
XFreeGC( _display, _gc );
|
||||
}
|
||||
|
||||
void destroyWindow()
|
||||
{
|
||||
XDestroyWindow( _display, _window );
|
||||
}
|
||||
|
||||
void closeDisplay()
|
||||
{
|
||||
XCloseDisplay( _display );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif //__cxxtest__X11Gui_h__
|
||||
29
test/cxxtest/cxxtest/YesNoRunner.h
Normal file
29
test/cxxtest/cxxtest/YesNoRunner.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef __cxxtest__YesNoRunner_h__
|
||||
#define __cxxtest__YesNoRunner_h__
|
||||
|
||||
//
|
||||
// The YesNoRunner is a simple TestListener that
|
||||
// just returns true iff all tests passed.
|
||||
//
|
||||
|
||||
#include <cxxtest/TestRunner.h>
|
||||
#include <cxxtest/TestListener.h>
|
||||
|
||||
namespace CxxTest
|
||||
{
|
||||
class YesNoRunner : public TestListener
|
||||
{
|
||||
public:
|
||||
YesNoRunner()
|
||||
{
|
||||
}
|
||||
|
||||
int run()
|
||||
{
|
||||
TestRunner::runAllTests( *this );
|
||||
return tracker().failedTests();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __cxxtest__YesNoRunner_h__
|
||||
551
test/cxxtest/cxxtestgen.pl
Normal file
551
test/cxxtest/cxxtestgen.pl
Normal file
@@ -0,0 +1,551 @@
|
||||
#!/usr/bin/perl -w
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
||||
sub usage() {
|
||||
print STDERR "Usage: $0 [OPTIONS] <input file(s)>\n";
|
||||
print STDERR "Generate test source file for CxxTest.\n";
|
||||
print STDERR "\n";
|
||||
print STDERR " -v, --version Write CxxTest version\n";
|
||||
print STDERR " -o, --output=NAME Write output to file NAME\n";
|
||||
print STDERR " --runner=CLASS Create a main() function that runs CxxTest::CLASS\n";
|
||||
print STDERR " --gui=CLASS Like --runner, with GUI component\n";
|
||||
print STDERR " --error-printer Same as --runner=ErrorPrinter\n";
|
||||
print STDERR " --abort-on-fail Abort tests on failed asserts (like xUnit)\n";
|
||||
print STDERR " --have-std Use standard library (even if not found in tests)\n";
|
||||
print STDERR " --no-std Don't use standard library (even if found in tests)\n";
|
||||
print STDERR " --have-eh Use exception handling (even if not found in tests)\n";
|
||||
print STDERR " --no-eh Don't use exception handling (even if found in tests)\n";
|
||||
print STDERR " --longlong=[TYPE] Use TYPE as `long long' (defaut = long long)\n";
|
||||
print STDERR " --template=TEMPLATE Use TEMPLATE file to generate the test runner\n";
|
||||
print STDERR " --include=HEADER Include \"HEADER\" in test runner before other headers\n";
|
||||
print STDERR " --root Write CxxTest globals\n";
|
||||
print STDERR " --part Don't write CxxTest globals\n";
|
||||
print STDERR " --no-static-init Don't rely on static initialization\n";
|
||||
exit -1;
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
sub main {
|
||||
parseCommandline();
|
||||
scanInputFiles();
|
||||
writeOutput();
|
||||
}
|
||||
|
||||
#
|
||||
# Handling the command line
|
||||
#
|
||||
|
||||
my ($output, $runner, $gui, $template, $abortOnFail, $haveEh, $noEh, $haveStd, $noStd);
|
||||
my ($root, $part, $noStaticInit, $longlong, $factor);
|
||||
my @headers = ();
|
||||
|
||||
sub parseCommandline() {
|
||||
@ARGV = expandWildcards(@ARGV);
|
||||
GetOptions( 'version' => \&printVersion,
|
||||
'output=s' => \$output,
|
||||
'template=s' => \$template,
|
||||
'runner=s' => \$runner,
|
||||
'gui=s', => \$gui,
|
||||
'error-printer' => sub { $runner = 'ErrorPrinter'; $haveStd = 1; },
|
||||
'abort-on-fail' => \$abortOnFail,
|
||||
'have-eh' => \$haveEh,
|
||||
'no-eh' => \$noEh,
|
||||
'have-std' => \$haveStd,
|
||||
'no-std' => \$noStd,
|
||||
'include=s' => \@headers,
|
||||
'root' => \$root,
|
||||
'part' => \$part,
|
||||
'no-static-init' => \$noStaticInit,
|
||||
'factor' => \$factor,
|
||||
'longlong:s' => \$longlong
|
||||
) or usage();
|
||||
scalar @ARGV or $root or usage();
|
||||
|
||||
if ( defined($noStaticInit) && (defined($root) || defined($part)) ) {
|
||||
die "--no-static-init cannot be used with --root/--part\n";
|
||||
}
|
||||
|
||||
if ( $gui && !$runner ) {
|
||||
$runner = 'StdioPrinter';
|
||||
}
|
||||
|
||||
if ( defined($longlong) && !$longlong ) {
|
||||
$longlong = 'long long';
|
||||
}
|
||||
|
||||
foreach my $header (@headers) {
|
||||
if ( !($header =~ m/^["<].*[>"]$/) ) {
|
||||
$header = "\"$header\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub printVersion() {
|
||||
print "This is CxxTest version 3.10.1.\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
sub expandWildcards() {
|
||||
my @result = ();
|
||||
while( my $fn = shift @_ ) {
|
||||
push @result, glob($fn);
|
||||
}
|
||||
return @result;
|
||||
}
|
||||
|
||||
#
|
||||
# Reading the input files and scanning for test cases
|
||||
#
|
||||
|
||||
my (@suites, $suite, $test, $inBlock);
|
||||
my $numTotalTests = 0;
|
||||
|
||||
sub scanInputFiles() {
|
||||
foreach my $file (@ARGV) {
|
||||
scanInputFile( $file );
|
||||
}
|
||||
scalar @suites or $root or die("No tests defined\n");
|
||||
}
|
||||
|
||||
sub scanInputFile($) {
|
||||
my ($file) = @_;
|
||||
open FILE, "<$file" or die("Cannot open input file \"$file\"\n");
|
||||
|
||||
my $line;
|
||||
while (defined($line = <FILE>)) {
|
||||
scanLineForExceptionHandling( $line );
|
||||
scanLineForStandardLibrary( $line );
|
||||
|
||||
scanLineForSuiteStart( $file, $., $line );
|
||||
|
||||
if ( $suite ) {
|
||||
if ( lineBelongsToSuite( $suite, $., $line ) ) {
|
||||
scanLineForTest( $., $line );
|
||||
scanLineForCreate( $., $line );
|
||||
scanLineForDestroy( $., $line );
|
||||
}
|
||||
}
|
||||
}
|
||||
closeSuite();
|
||||
close FILE;
|
||||
}
|
||||
|
||||
sub lineBelongsToSuite($$$) {
|
||||
my ($suite, $lineNo, $line) = @_;
|
||||
if ( !$suite->{'generated'} ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( !$inBlock ) {
|
||||
$inBlock = lineStartsBlock( $line );
|
||||
}
|
||||
if ( $inBlock ) {
|
||||
addLineToBlock( $suite->{'file'}, $lineNo, $line );
|
||||
}
|
||||
return $inBlock;
|
||||
}
|
||||
|
||||
sub scanLineForExceptionHandling($) {
|
||||
my ($line) = @_;
|
||||
if ( $line =~ m/\b(try|throw|catch|TSM?_ASSERT_THROWS[A-Z_]*)\b/ ) {
|
||||
addExceptionHandling();
|
||||
}
|
||||
}
|
||||
|
||||
sub scanLineForStandardLibrary($) {
|
||||
my ($line) = @_;
|
||||
if ( $line =~ m/\b(std\s*::|CXXTEST_STD|using\s+namespace\s+std\b|^\s*\#\s*include\s+<[a-z0-9]+>)/ ) {
|
||||
addStandardLibrary();
|
||||
}
|
||||
}
|
||||
|
||||
sub scanLineForSuiteStart($$$) {
|
||||
my ($fileName, $lineNo, $line) = @_;
|
||||
if ( $line =~ m/\bclass\s+(\w+)\s*:\s*public\s+((::)?\s*CxxTest\s*::\s*)?TestSuite\b/ ) {
|
||||
startSuite( $1, $fileName, $lineNo, 0 );
|
||||
}
|
||||
if ( $line =~ m/\bCXXTEST_SUITE\s*\(\s*(\w*)\s*\)/ ) {
|
||||
print "$fileName:$lineNo: Warning: Inline test suites are deprecated.\n";
|
||||
startSuite( $1, $fileName, $lineNo, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
sub startSuite($$$$) {
|
||||
my ($name, $file, $line, $generated) = @_;
|
||||
closeSuite();
|
||||
$suite = { 'name' => $name,
|
||||
'file' => $file,
|
||||
'line' => $line,
|
||||
'generated' => $generated,
|
||||
'create' => 0,
|
||||
'destroy' => 0,
|
||||
'tests' => [],
|
||||
'lines' => [] };
|
||||
}
|
||||
|
||||
sub lineStartsBlock($) {
|
||||
my ($line) = @_;
|
||||
return $line =~ m/\bCXXTEST_CODE\s*\(/;
|
||||
}
|
||||
|
||||
sub scanLineForTest($$) {
|
||||
my ($lineNo, $line) = @_;
|
||||
if ( $line =~ m/^([^\/]|\/[^\/])*\bvoid\s+([Tt]est\w+)\s*\(\s*(void)?\s*\)/ ) {
|
||||
addTest( $2, $lineNo );
|
||||
}
|
||||
}
|
||||
|
||||
sub addTest($$$) {
|
||||
my ($name, $line) = @_;
|
||||
$test = { 'name' => $name,
|
||||
'line' => $line };
|
||||
push @{suiteTests()}, $test;
|
||||
}
|
||||
|
||||
sub addLineToBlock($$$) {
|
||||
my ($fileName, $lineNo, $line) = @_;
|
||||
$line = fixBlockLine( $fileName, $lineNo, $line );
|
||||
$line =~ s/^.*\{\{//;
|
||||
my $end = ($line =~ s/\}\}.*//s);
|
||||
push @{$suite->{'lines'}}, $line;
|
||||
if ( $end ) {
|
||||
$inBlock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sub fixBlockLine($$$) {
|
||||
my ($fileName, $lineNo, $line) = @_;
|
||||
my $fileLine = cstr($fileName) . "," . $lineNo;
|
||||
$line =~ s/\b(E?TSM?_(ASSERT[A-Z_]*|FAIL))\s*\(/_$1($fileLine,/g;
|
||||
return $line;
|
||||
}
|
||||
|
||||
sub scanLineForCreate($$) {
|
||||
my ($lineNo, $line) = @_;
|
||||
if ( $line =~ m/\bstatic\s+\w+\s*\*\s*createSuite\s*\(\s*(void)?\s*\)/ ) {
|
||||
addCreateSuite( $lineNo );
|
||||
}
|
||||
}
|
||||
|
||||
sub scanLineForDestroy($$) {
|
||||
my ($lineNo, $line) = @_;
|
||||
if ( $line =~ m/\bstatic\s+void\s+destroySuite\s*\(\s*\w+\s*\*\s*\w*\s*\)/ ) {
|
||||
addDestroySuite( $lineNo );
|
||||
}
|
||||
}
|
||||
|
||||
sub closeSuite() {
|
||||
if ( $suite && scalar @{suiteTests()} ) {
|
||||
verifySuite();
|
||||
rememberSuite();
|
||||
}
|
||||
undef $suite;
|
||||
}
|
||||
|
||||
sub addCreateSuite($) {
|
||||
$suite->{'createSuite'} = $_[0];
|
||||
}
|
||||
|
||||
sub addDestroySuite($) {
|
||||
$suite->{'destroySuite'} = $_[0];
|
||||
}
|
||||
|
||||
sub addExceptionHandling() {
|
||||
$haveEh = 1 unless defined($noEh);
|
||||
}
|
||||
|
||||
sub addStandardLibrary() {
|
||||
$haveStd = 1 unless defined($noStd);
|
||||
}
|
||||
|
||||
sub verifySuite() {
|
||||
if (suiteCreateLine() || suiteDestroyLine()) {
|
||||
die("Suite ", suiteName(), " must have both createSuite() and destroySuite()\n")
|
||||
unless (suiteCreateLine() && suiteDestroyLine());
|
||||
}
|
||||
}
|
||||
|
||||
sub rememberSuite() {
|
||||
push @suites, $suite;
|
||||
$numTotalTests += scalar @{$suite->{'tests'}};
|
||||
}
|
||||
|
||||
sub suiteName() { return $suite->{'name'}; }
|
||||
sub suiteTests() { return $suite->{'tests'}; }
|
||||
sub suiteCreateLine() { return $suite->{'createSuite'}; }
|
||||
sub suiteDestroyLine() { return $suite->{'destroySuite'}; }
|
||||
sub fileName() { return $suite->{'file'}; }
|
||||
sub fileString() { return cstr(fileName()); }
|
||||
sub testName() { return $test->{'name'}; }
|
||||
sub testLine() { return $test->{'line'}; }
|
||||
|
||||
sub suiteObject() { return "suite_".suiteName(); }
|
||||
|
||||
sub cstr($) {
|
||||
my $file = $_[0];
|
||||
$file =~ s/\\/\\\\/g;
|
||||
return "\"".$file."\"";
|
||||
}
|
||||
|
||||
#
|
||||
# Writing the test source file
|
||||
#
|
||||
|
||||
sub writeOutput() {
|
||||
$template ? writeTemplateOutput() : writeSimpleOutput();
|
||||
}
|
||||
|
||||
sub startOutputFile() {
|
||||
if ( !standardOutput() ) {
|
||||
open OUTPUT_FILE,">$output" or die("Cannot create output file \"$output\"\n");
|
||||
select OUTPUT_FILE;
|
||||
}
|
||||
print "/* Generated file, do not edit */\n\n";
|
||||
}
|
||||
|
||||
sub standardOutput() {
|
||||
return !$output;
|
||||
}
|
||||
|
||||
sub writeSimpleOutput() {
|
||||
startOutputFile();
|
||||
writePreamble();
|
||||
writeMain();
|
||||
writeWorld();
|
||||
}
|
||||
|
||||
my ($didPreamble, $didWorld);
|
||||
|
||||
sub writeTemplateOutput() {
|
||||
openTemplateFile();
|
||||
startOutputFile();
|
||||
my $line;
|
||||
while (defined($line = <TEMPLATE_FILE>)) {
|
||||
if ( $line =~ m/^\s*\#\s*include\s*<cxxtest\// ) {
|
||||
writePreamble();
|
||||
print $line;
|
||||
} elsif ( $line =~ m/^\s*<CxxTest\s+preamble>\s*$/ ) {
|
||||
writePreamble();
|
||||
} elsif ( $line =~ m/^\s*<CxxTest\s+world>\s*$/ ) {
|
||||
writeWorld();
|
||||
} else {
|
||||
print $line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub openTemplateFile() {
|
||||
open TEMPLATE_FILE, "<$template" or die("Cannot open template file \"$template\"\n");
|
||||
}
|
||||
|
||||
sub writePreamble() {
|
||||
return if $didPreamble;
|
||||
print "#ifndef CXXTEST_RUNNING\n";
|
||||
print "#define CXXTEST_RUNNING\n";
|
||||
print "#endif\n";
|
||||
print "\n";
|
||||
if ( $haveStd ) {
|
||||
print "#define _CXXTEST_HAVE_STD\n";
|
||||
}
|
||||
if ( $haveEh ) {
|
||||
print "#define _CXXTEST_HAVE_EH\n";
|
||||
}
|
||||
if ( $abortOnFail ) {
|
||||
print "#define _CXXTEST_ABORT_TEST_ON_FAIL\n";
|
||||
}
|
||||
if ( $longlong ) {
|
||||
print "#define _CXXTEST_LONGLONG $longlong\n";
|
||||
}
|
||||
if ( $factor ) {
|
||||
print "#define _CXXTEST_FACTOR\n";
|
||||
}
|
||||
foreach my $header (@headers) {
|
||||
print "#include $header\n";
|
||||
}
|
||||
print "#include <cxxtest/TestListener.h>\n";
|
||||
print "#include <cxxtest/TestTracker.h>\n";
|
||||
print "#include <cxxtest/TestRunner.h>\n";
|
||||
print "#include <cxxtest/RealDescriptions.h>\n";
|
||||
print "#include <cxxtest/$runner.h>\n" if $runner;
|
||||
print "#include <cxxtest/$gui.h>\n" if $gui;
|
||||
print "\n";
|
||||
$didPreamble = 1;
|
||||
}
|
||||
|
||||
sub writeWorld() {
|
||||
return if $didWorld;
|
||||
writePreamble();
|
||||
writeSuites();
|
||||
($root or !$part) and writeRoot();
|
||||
$noStaticInit and writeInitialize();
|
||||
$didWorld = 1;
|
||||
}
|
||||
|
||||
sub writeSuites() {
|
||||
foreach (@suites) {
|
||||
$suite = $_;
|
||||
writeInclude(fileName());
|
||||
if ( $suite->{'generated'} ) { generateSuite(); }
|
||||
dynamicSuite() ? writeSuitePointer() : writeSuiteObject();
|
||||
writeTestList();
|
||||
writeSuiteDescription();
|
||||
writeTestDescriptions();
|
||||
}
|
||||
}
|
||||
|
||||
sub dynamicSuite() {
|
||||
return suiteCreateLine();
|
||||
}
|
||||
|
||||
my $lastIncluded;
|
||||
|
||||
sub writeInclude($) {
|
||||
my $file = $_[0];
|
||||
return if $lastIncluded && ($file eq $lastIncluded);
|
||||
print "#include \"$file\"\n\n";
|
||||
$lastIncluded = $file;
|
||||
}
|
||||
|
||||
sub generateSuite() {
|
||||
print "class ", suiteName(), " : public CxxTest::TestSuite {\n";
|
||||
print "public:\n";
|
||||
foreach my $line (@{$suite->{'lines'}}) {
|
||||
print $line;
|
||||
}
|
||||
print "};\n\n";
|
||||
}
|
||||
|
||||
sub writeTestDescriptionsBase() {
|
||||
my $class = "TestDescriptionBase_" . suiteName();
|
||||
print "class $class : public CxxTest::TestDescription {\n";
|
||||
print "public:\n";
|
||||
print " const char *file() const { return ", fileString(), "; }\n";
|
||||
print " const char *suiteName() const { return \"", suiteName(), "\"; }\n";
|
||||
print "};\n\n";
|
||||
}
|
||||
|
||||
sub writeSuitePointer() {
|
||||
if ( $noStaticInit ) {
|
||||
print "static ", suiteName(), " *", suiteObject(), ";\n\n";
|
||||
} else {
|
||||
print "static ", suiteName(), " *", suiteObject(), " = 0;\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub writeSuiteObject() {
|
||||
print "static ", suiteName(), " ", suiteObject(), ";\n\n";
|
||||
}
|
||||
|
||||
sub testList() {
|
||||
return "Tests_" . suiteName();
|
||||
}
|
||||
|
||||
sub writeTestList() {
|
||||
if ( $noStaticInit ) {
|
||||
printf "static CxxTest::List %s;\n", testList();
|
||||
} else {
|
||||
printf "static CxxTest::List %s = { 0, 0 };\n", testList();
|
||||
}
|
||||
}
|
||||
|
||||
sub writeTestDescriptions() {
|
||||
foreach (@{suiteTests()}) {
|
||||
$test = $_;
|
||||
writeTestDescription();
|
||||
}
|
||||
}
|
||||
|
||||
sub suiteDescription() {
|
||||
return "suiteDescription_" . suiteName();
|
||||
}
|
||||
|
||||
sub writeTestDescription() {
|
||||
my $class = "TestDescription_" . suiteName() . "_" . testName();
|
||||
printf "static class $class : public CxxTest::RealTestDescription {\n";
|
||||
printf "public:\n";
|
||||
$noStaticInit or
|
||||
printf " $class() : CxxTest::RealTestDescription( %s, %s, %s, \"%s\" ) {}\n",
|
||||
testList(), suiteDescription(), testLine(), testName();
|
||||
printf " void runTest() { %s }\n", dynamicSuite() ? dynamicRun() : staticRun();
|
||||
printf "} testDescription_%s_%s;\n\n", suiteName(), testName();
|
||||
}
|
||||
|
||||
sub dynamicRun() {
|
||||
return sprintf( "if ( %s ) %s->%s();", suiteObject(), suiteObject(), testName() );
|
||||
}
|
||||
|
||||
sub staticRun() {
|
||||
return sprintf( "%s.%s();", suiteObject(), testName() );
|
||||
}
|
||||
|
||||
sub writeSuiteDescription() {
|
||||
dynamicSuite() ? writeDynamicDescription() : writeStaticDescription();
|
||||
}
|
||||
|
||||
sub writeDynamicDescription() {
|
||||
printf "CxxTest::DynamicSuiteDescription<%s> %s", suiteName(), suiteDescription();
|
||||
if ( !$noStaticInit ) {
|
||||
printf "( %s, %s, \"%s\", %s, %s, %s, %s )",
|
||||
fileString(), $suite->{'line'}, suiteName(), testList(),
|
||||
suiteObject(), suiteCreateLine(), suiteDestroyLine();
|
||||
}
|
||||
print ";\n\n";
|
||||
}
|
||||
|
||||
sub writeStaticDescription() {
|
||||
printf "CxxTest::StaticSuiteDescription %s", suiteDescription();
|
||||
if ( !$noStaticInit ) {
|
||||
printf "( %s, %s, \"%s\", %s, %s )", fileString(), $suite->{'line'}, suiteName(), suiteObject(), testList();
|
||||
}
|
||||
print ";\n\n";
|
||||
}
|
||||
|
||||
sub writeRoot() {
|
||||
print "#include <cxxtest/Root.cpp>\n";
|
||||
}
|
||||
|
||||
sub writeInitialize() {
|
||||
print "namespace CxxTest {\n";
|
||||
print " void initialize()\n";
|
||||
print " {\n";
|
||||
foreach (@suites) {
|
||||
$suite = $_;
|
||||
printf " %s.initialize();\n", testList();
|
||||
if ( dynamicSuite() ) {
|
||||
printf " %s = 0;\n", suiteObject();
|
||||
printf " %s.initialize( %s, %s, \"%s\", %s, %s, %s, %s );\n",
|
||||
suiteDescription(), fileString(), $suite->{'line'}, suiteName(), testList(),
|
||||
suiteObject(), suiteCreateLine(), suiteDestroyLine();
|
||||
} else {
|
||||
printf " %s.initialize( %s, %s, \"%s\", %s, %s );\n",
|
||||
suiteDescription(), fileString(), $suite->{'line'}, suiteName(), suiteObject(), testList();
|
||||
}
|
||||
|
||||
foreach (@{suiteTests()}) {
|
||||
$test = $_;
|
||||
printf " testDescription_%s_%s.initialize( %s, %s, %s, \"%s\" );\n",
|
||||
suiteName(), testName(), testList(), suiteDescription(), testLine(), testName();
|
||||
}
|
||||
}
|
||||
print " }\n";
|
||||
print "}\n";
|
||||
}
|
||||
|
||||
sub writeMain() {
|
||||
if ( $gui ) {
|
||||
print "int main( int argc, char *argv[] ) {\n";
|
||||
$noStaticInit &&
|
||||
print " CxxTest::initialize();\n";
|
||||
print " return CxxTest::GuiTuiRunner<CxxTest::$gui, CxxTest::$runner>( argc, argv ).run();\n";
|
||||
print "}\n";
|
||||
}
|
||||
elsif ( $runner ) {
|
||||
print "int main() {\n";
|
||||
$noStaticInit &&
|
||||
print " CxxTest::initialize();\n";
|
||||
print " return CxxTest::$runner().run();\n";
|
||||
print "}\n";
|
||||
}
|
||||
}
|
||||
597
test/cxxtest/cxxtestgen.py
Normal file
597
test/cxxtest/cxxtestgen.py
Normal file
@@ -0,0 +1,597 @@
|
||||
#!/usr/bin/env python
|
||||
'''Usage: %s [OPTIONS] <input file(s)>
|
||||
Generate test source file for CxxTest.
|
||||
|
||||
-v, --version Write CxxTest version
|
||||
-o, --output=NAME Write output to file NAME
|
||||
--runner=CLASS Create a main() function that runs CxxTest::CLASS
|
||||
--gui=CLASS Like --runner, with GUI component
|
||||
--error-printer Same as --runner=ErrorPrinter
|
||||
--abort-on-fail Abort tests on failed asserts (like xUnit)
|
||||
--have-std Use standard library (even if not found in tests)
|
||||
--no-std Don\'t use standard library (even if found in tests)
|
||||
--have-eh Use exception handling (even if not found in tests)
|
||||
--no-eh Don\'t use exception handling (even if found in tests)
|
||||
--longlong=[TYPE] Use TYPE (default: long long) as long long
|
||||
--template=TEMPLATE Use TEMPLATE file to generate the test runner
|
||||
--include=HEADER Include HEADER in test runner before other headers
|
||||
--root Write CxxTest globals
|
||||
--part Don\'t write CxxTest globals
|
||||
--no-static-init Don\'t rely on static initialization
|
||||
'''
|
||||
|
||||
import re
|
||||
import sys
|
||||
import getopt
|
||||
import glob
|
||||
import string
|
||||
|
||||
# Global variables
|
||||
suites = []
|
||||
suite = None
|
||||
inBlock = 0
|
||||
|
||||
outputFileName = None
|
||||
runner = None
|
||||
gui = None
|
||||
root = None
|
||||
part = None
|
||||
noStaticInit = None
|
||||
templateFileName = None
|
||||
headers = []
|
||||
|
||||
haveExceptionHandling = 0
|
||||
noExceptionHandling = 0
|
||||
haveStandardLibrary = 0
|
||||
noStandardLibrary = 0
|
||||
abortOnFail = 0
|
||||
factor = 0
|
||||
longlong = 0
|
||||
|
||||
def main():
|
||||
'''The main program'''
|
||||
files = parseCommandline()
|
||||
scanInputFiles( files )
|
||||
writeOutput()
|
||||
|
||||
def usage( problem = None ):
|
||||
'''Print usage info and exit'''
|
||||
if problem is None:
|
||||
print( usageString() )
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.stderr.write( usageString() )
|
||||
abort( problem )
|
||||
|
||||
def usageString():
|
||||
'''Construct program usage string'''
|
||||
return __doc__ % sys.argv[0]
|
||||
|
||||
def abort( problem ):
|
||||
'''Print error message and exit'''
|
||||
sys.stderr.write( '\n' )
|
||||
sys.stderr.write( problem )
|
||||
sys.stderr.write( '\n\n' )
|
||||
sys.exit(2)
|
||||
|
||||
def parseCommandline():
|
||||
'''Analyze command line arguments'''
|
||||
try:
|
||||
options, patterns = getopt.getopt( sys.argv[1:], 'o:r:',
|
||||
['version', 'output=', 'runner=', 'gui=',
|
||||
'error-printer', 'abort-on-fail', 'have-std', 'no-std',
|
||||
'have-eh', 'no-eh', 'template=', 'include=',
|
||||
'root', 'part', 'no-static-init', 'factor', 'longlong='] )
|
||||
except getopt.error as problem:
|
||||
usage( problem )
|
||||
setOptions( options )
|
||||
return setFiles( patterns )
|
||||
|
||||
def setOptions( options ):
|
||||
'''Set options specified on command line'''
|
||||
global outputFileName, templateFileName, runner, gui, haveStandardLibrary, factor, longlong
|
||||
global haveExceptionHandling, noExceptionHandling, abortOnFail, headers, root, part, noStaticInit
|
||||
for o, a in options:
|
||||
if o in ('-v', '--version'):
|
||||
printVersion()
|
||||
elif o in ('-o', '--output'):
|
||||
outputFileName = a
|
||||
elif o == '--template':
|
||||
templateFileName = a
|
||||
elif o == '--runner':
|
||||
runner = a
|
||||
elif o == '--gui':
|
||||
gui = a
|
||||
elif o == '--include':
|
||||
if not re.match( r'^["<].*[>"]$', a ):
|
||||
a = ('"%s"' % a)
|
||||
headers.append( a )
|
||||
elif o == '--error-printer':
|
||||
runner = 'ErrorPrinter'
|
||||
haveStandardLibrary = 1
|
||||
elif o == '--abort-on-fail':
|
||||
abortOnFail = 1
|
||||
elif o == '--have-std':
|
||||
haveStandardLibrary = 1
|
||||
elif o == '--no-std':
|
||||
noStandardLibrary = 1
|
||||
elif o == '--have-eh':
|
||||
haveExceptionHandling = 1
|
||||
elif o == '--no-eh':
|
||||
noExceptionHandling = 1
|
||||
elif o == '--root':
|
||||
root = 1
|
||||
elif o == '--part':
|
||||
part = 1
|
||||
elif o == '--no-static-init':
|
||||
noStaticInit = 1
|
||||
elif o == '--factor':
|
||||
factor = 1
|
||||
elif o == '--longlong':
|
||||
if a:
|
||||
longlong = a
|
||||
else:
|
||||
longlong = 'long long'
|
||||
|
||||
if noStaticInit and (root or part):
|
||||
abort( '--no-static-init cannot be used with --root/--part' )
|
||||
|
||||
if gui and not runner:
|
||||
runner = 'StdioPrinter'
|
||||
|
||||
def printVersion():
|
||||
'''Print CxxTest version and exit'''
|
||||
sys.stdout.write( "This is CxxTest version 3.10.1.\n" )
|
||||
sys.exit(0)
|
||||
|
||||
def setFiles( patterns ):
|
||||
'''Set input files specified on command line'''
|
||||
files = expandWildcards( patterns )
|
||||
if len(files) == 0 and not root:
|
||||
usage( "No input files found" )
|
||||
return files
|
||||
|
||||
def expandWildcards( patterns ):
|
||||
'''Expand all wildcards in an array (glob)'''
|
||||
fileNames = []
|
||||
for pathName in patterns:
|
||||
patternFiles = glob.glob( pathName )
|
||||
for fileName in patternFiles:
|
||||
fileNames.append( fixBackslashes( fileName ) )
|
||||
return fileNames
|
||||
|
||||
def fixBackslashes( fileName ):
|
||||
'''Convert backslashes to slashes in file name'''
|
||||
return re.sub( r'\\', '/', fileName )
|
||||
|
||||
def scanInputFiles(files):
|
||||
'''Scan all input files for test suites'''
|
||||
for file in files:
|
||||
scanInputFile(file)
|
||||
global suites
|
||||
if len(suites) == 0 and not root:
|
||||
abort( 'No tests defined' )
|
||||
|
||||
def scanInputFile(fileName):
|
||||
'''Scan single input file for test suites'''
|
||||
if sys.version_info.major >= 3:
|
||||
file = open(fileName, encoding='utf-8')
|
||||
else:
|
||||
file = open(fileName)
|
||||
|
||||
lineNo = 0
|
||||
while 1:
|
||||
line = file.readline()
|
||||
if not line:
|
||||
break
|
||||
lineNo = lineNo + 1
|
||||
|
||||
scanInputLine( fileName, lineNo, line )
|
||||
closeSuite()
|
||||
file.close()
|
||||
|
||||
def scanInputLine( fileName, lineNo, line ):
|
||||
'''Scan single input line for interesting stuff'''
|
||||
scanLineForExceptionHandling( line )
|
||||
scanLineForStandardLibrary( line )
|
||||
|
||||
scanLineForSuiteStart( fileName, lineNo, line )
|
||||
|
||||
global suite
|
||||
if suite:
|
||||
scanLineInsideSuite( suite, lineNo, line )
|
||||
|
||||
def scanLineInsideSuite( suite, lineNo, line ):
|
||||
'''Analyze line which is part of a suite'''
|
||||
global inBlock
|
||||
if lineBelongsToSuite( suite, lineNo, line ):
|
||||
scanLineForTest( suite, lineNo, line )
|
||||
scanLineForCreate( suite, lineNo, line )
|
||||
scanLineForDestroy( suite, lineNo, line )
|
||||
|
||||
def lineBelongsToSuite( suite, lineNo, line ):
|
||||
'''Returns whether current line is part of the current suite.
|
||||
This can be false when we are in a generated suite outside of CXXTEST_CODE() blocks
|
||||
If the suite is generated, adds the line to the list of lines'''
|
||||
if not suite['generated']:
|
||||
return 1
|
||||
|
||||
global inBlock
|
||||
if not inBlock:
|
||||
inBlock = lineStartsBlock( line )
|
||||
if inBlock:
|
||||
inBlock = addLineToBlock( suite, lineNo, line )
|
||||
return inBlock
|
||||
|
||||
|
||||
std_re = re.compile( r"\b(std\s*::|CXXTEST_STD|using\s+namespace\s+std\b|^\s*\#\s*include\s+<[a-z0-9]+>)" )
|
||||
def scanLineForStandardLibrary( line ):
|
||||
'''Check if current line uses standard library'''
|
||||
global haveStandardLibrary, noStandardLibrary
|
||||
if not haveStandardLibrary and std_re.search(line):
|
||||
if not noStandardLibrary:
|
||||
haveStandardLibrary = 1
|
||||
|
||||
exception_re = re.compile( r"\b(throw|try|catch|TSM?_ASSERT_THROWS[A-Z_]*)\b" )
|
||||
def scanLineForExceptionHandling( line ):
|
||||
'''Check if current line uses exception handling'''
|
||||
global haveExceptionHandling, noExceptionHandling
|
||||
if not haveExceptionHandling and exception_re.search(line):
|
||||
if not noExceptionHandling:
|
||||
haveExceptionHandling = 1
|
||||
|
||||
suite_re = re.compile( r'\bclass\s+(\w+)\s*:\s*public\s+((::)?\s*CxxTest\s*::\s*)?TestSuite\b' )
|
||||
generatedSuite_re = re.compile( r'\bCXXTEST_SUITE\s*\(\s*(\w*)\s*\)' )
|
||||
def scanLineForSuiteStart( fileName, lineNo, line ):
|
||||
'''Check if current line starts a new test suite'''
|
||||
m = suite_re.search( line )
|
||||
if m:
|
||||
startSuite( m.group(1), fileName, lineNo, 0 )
|
||||
m = generatedSuite_re.search( line )
|
||||
if m:
|
||||
sys.stdout.write( "%s:%s: Warning: Inline test suites are deprecated.\n" % (fileName, lineNo) )
|
||||
startSuite( m.group(1), fileName, lineNo, 1 )
|
||||
|
||||
def startSuite( name, file, line, generated ):
|
||||
'''Start scanning a new suite'''
|
||||
global suite
|
||||
closeSuite()
|
||||
suite = { 'name' : name,
|
||||
'file' : file,
|
||||
'cfile' : cstr(file),
|
||||
'line' : line,
|
||||
'generated' : generated,
|
||||
'object' : 'suite_%s' % name,
|
||||
'dobject' : 'suiteDescription_%s' % name,
|
||||
'tlist' : 'Tests_%s' % name,
|
||||
'tests' : [],
|
||||
'lines' : [] }
|
||||
|
||||
def lineStartsBlock( line ):
|
||||
'''Check if current line starts a new CXXTEST_CODE() block'''
|
||||
return re.search( r'\bCXXTEST_CODE\s*\(', line ) is not None
|
||||
|
||||
test_re = re.compile( r'^([^/]|/[^/])*\bvoid\s+([Tt]est\w+)\s*\(\s*(void)?\s*\)' )
|
||||
def scanLineForTest( suite, lineNo, line ):
|
||||
'''Check if current line starts a test'''
|
||||
m = test_re.search( line )
|
||||
if m:
|
||||
addTest( suite, m.group(2), lineNo )
|
||||
|
||||
def addTest( suite, name, line ):
|
||||
'''Add a test function to the current suite'''
|
||||
test = { 'name' : name,
|
||||
'suite' : suite,
|
||||
'class' : 'TestDescription_%s_%s' % (suite['name'], name),
|
||||
'object' : 'testDescription_%s_%s' % (suite['name'], name),
|
||||
'line' : line,
|
||||
}
|
||||
suite['tests'].append( test )
|
||||
|
||||
def addLineToBlock( suite, lineNo, line ):
|
||||
'''Append the line to the current CXXTEST_CODE() block'''
|
||||
line = fixBlockLine( suite, lineNo, line )
|
||||
line = re.sub( r'^.*\{\{', '', line )
|
||||
|
||||
e = re.search( r'\}\}', line )
|
||||
if e:
|
||||
line = line[:e.start()]
|
||||
suite['lines'].append( line )
|
||||
return e is None
|
||||
|
||||
def fixBlockLine( suite, lineNo, line):
|
||||
'''Change all [E]TS_ macros used in a line to _[E]TS_ macros with the correct file/line'''
|
||||
return re.sub( r'\b(E?TSM?_(ASSERT[A-Z_]*|FAIL))\s*\(',
|
||||
r'_\1(%s,%s,' % (suite['cfile'], lineNo),
|
||||
line, 0 )
|
||||
|
||||
create_re = re.compile( r'\bstatic\s+\w+\s*\*\s*createSuite\s*\(\s*(void)?\s*\)' )
|
||||
def scanLineForCreate( suite, lineNo, line ):
|
||||
'''Check if current line defines a createSuite() function'''
|
||||
if create_re.search( line ):
|
||||
addSuiteCreateDestroy( suite, 'create', lineNo )
|
||||
|
||||
destroy_re = re.compile( r'\bstatic\s+void\s+destroySuite\s*\(\s*\w+\s*\*\s*\w*\s*\)' )
|
||||
def scanLineForDestroy( suite, lineNo, line ):
|
||||
'''Check if current line defines a destroySuite() function'''
|
||||
if destroy_re.search( line ):
|
||||
addSuiteCreateDestroy( suite, 'destroy', lineNo )
|
||||
|
||||
def cstr( str ):
|
||||
'''Convert a string to its C representation'''
|
||||
return '"' + str.replace( '\\', '\\\\' ) + '"'
|
||||
|
||||
|
||||
def addSuiteCreateDestroy( suite, which, line ):
|
||||
'''Add createSuite()/destroySuite() to current suite'''
|
||||
if suite.has_key(which):
|
||||
abort( '%s:%s: %sSuite() already declared' % ( suite['file'], str(line), which ) )
|
||||
suite[which] = line
|
||||
|
||||
def closeSuite():
|
||||
'''Close current suite and add it to the list if valid'''
|
||||
global suite
|
||||
if suite is not None:
|
||||
if len(suite['tests']) != 0:
|
||||
verifySuite(suite)
|
||||
rememberSuite(suite)
|
||||
suite = None
|
||||
|
||||
def verifySuite(suite):
|
||||
'''Verify current suite is legal'''
|
||||
if 'create' in suite and not 'destroy' in suite:
|
||||
abort( '%s:%s: Suite %s has createSuite() but no destroySuite()' %
|
||||
(suite['file'], suite['create'], suite['name']) )
|
||||
if 'destroy' in suite and not 'create' in suite:
|
||||
abort( '%s:%s: Suite %s has destroySuite() but no createSuite()' %
|
||||
(suite['file'], suite['destroy'], suite['name']) )
|
||||
|
||||
def rememberSuite(suite):
|
||||
'''Add current suite to list'''
|
||||
global suites
|
||||
suites.append( suite )
|
||||
|
||||
def writeOutput():
|
||||
'''Create output file'''
|
||||
if templateFileName:
|
||||
writeTemplateOutput()
|
||||
else:
|
||||
writeSimpleOutput()
|
||||
|
||||
def writeSimpleOutput():
|
||||
'''Create output not based on template'''
|
||||
output = startOutputFile()
|
||||
writePreamble( output )
|
||||
writeMain( output )
|
||||
writeWorld( output )
|
||||
output.close()
|
||||
|
||||
include_re = re.compile( r"\s*\#\s*include\s+<cxxtest/" )
|
||||
preamble_re = re.compile( r"^\s*<CxxTest\s+preamble>\s*$" )
|
||||
world_re = re.compile( r"^\s*<CxxTest\s+world>\s*$" )
|
||||
def writeTemplateOutput():
|
||||
'''Create output based on template file'''
|
||||
template = open(templateFileName)
|
||||
output = startOutputFile()
|
||||
while 1:
|
||||
line = template.readline()
|
||||
if not line:
|
||||
break;
|
||||
if include_re.search( line ):
|
||||
writePreamble( output )
|
||||
output.write( line )
|
||||
elif preamble_re.search( line ):
|
||||
writePreamble( output )
|
||||
elif world_re.search( line ):
|
||||
writeWorld( output )
|
||||
else:
|
||||
output.write( line )
|
||||
template.close()
|
||||
output.close()
|
||||
|
||||
def startOutputFile():
|
||||
'''Create output file and write header'''
|
||||
if outputFileName is not None:
|
||||
output = open( outputFileName, 'w' )
|
||||
else:
|
||||
output = sys.stdout
|
||||
output.write( "/* Generated file, do not edit */\n\n" )
|
||||
return output
|
||||
|
||||
wrotePreamble = 0
|
||||
def writePreamble( output ):
|
||||
'''Write the CxxTest header (#includes and #defines)'''
|
||||
global wrotePreamble, headers, longlong
|
||||
if wrotePreamble: return
|
||||
output.write( "#ifndef CXXTEST_RUNNING\n" )
|
||||
output.write( "#define CXXTEST_RUNNING\n" )
|
||||
output.write( "#endif\n" )
|
||||
output.write( "\n" )
|
||||
if haveStandardLibrary:
|
||||
output.write( "#define _CXXTEST_HAVE_STD\n" )
|
||||
if haveExceptionHandling:
|
||||
output.write( "#define _CXXTEST_HAVE_EH\n" )
|
||||
if abortOnFail:
|
||||
output.write( "#define _CXXTEST_ABORT_TEST_ON_FAIL\n" )
|
||||
if longlong:
|
||||
output.write( "#define _CXXTEST_LONGLONG %s\n" % longlong )
|
||||
if factor:
|
||||
output.write( "#define _CXXTEST_FACTOR\n" )
|
||||
for header in headers:
|
||||
output.write( "#include %s\n" % header )
|
||||
output.write( "#include <cxxtest/TestListener.h>\n" )
|
||||
output.write( "#include <cxxtest/TestTracker.h>\n" )
|
||||
output.write( "#include <cxxtest/TestRunner.h>\n" )
|
||||
output.write( "#include <cxxtest/RealDescriptions.h>\n" )
|
||||
if runner:
|
||||
output.write( "#include <cxxtest/%s.h>\n" % runner )
|
||||
if gui:
|
||||
output.write( "#include <cxxtest/%s.h>\n" % gui )
|
||||
output.write( "\n" )
|
||||
wrotePreamble = 1
|
||||
|
||||
def writeMain( output ):
|
||||
'''Write the main() function for the test runner'''
|
||||
if gui:
|
||||
output.write( 'int main( int argc, char *argv[] ) {\n' )
|
||||
if noStaticInit:
|
||||
output.write( ' CxxTest::initialize();\n' )
|
||||
output.write( ' return CxxTest::GuiTuiRunner<CxxTest::%s, CxxTest::%s>( argc, argv ).run();\n' % (gui, runner) )
|
||||
output.write( '}\n' )
|
||||
elif runner:
|
||||
output.write( 'int main() {\n' )
|
||||
if noStaticInit:
|
||||
output.write( ' CxxTest::initialize();\n' )
|
||||
output.write( ' return CxxTest::%s().run();\n' % runner )
|
||||
output.write( '}\n' )
|
||||
|
||||
wroteWorld = 0
|
||||
def writeWorld( output ):
|
||||
'''Write the world definitions'''
|
||||
global wroteWorld, part
|
||||
if wroteWorld: return
|
||||
writePreamble( output )
|
||||
writeSuites( output )
|
||||
if root or not part:
|
||||
writeRoot( output )
|
||||
if noStaticInit:
|
||||
writeInitialize( output )
|
||||
wroteWorld = 1
|
||||
|
||||
def writeSuites(output):
|
||||
'''Write all TestDescriptions and SuiteDescriptions'''
|
||||
for suite in suites:
|
||||
writeInclude( output, suite['file'] )
|
||||
if isGenerated(suite):
|
||||
generateSuite( output, suite )
|
||||
if isDynamic(suite):
|
||||
writeSuitePointer( output, suite )
|
||||
else:
|
||||
writeSuiteObject( output, suite )
|
||||
writeTestList( output, suite )
|
||||
writeSuiteDescription( output, suite )
|
||||
writeTestDescriptions( output, suite )
|
||||
|
||||
def isGenerated(suite):
|
||||
'''Checks whether a suite class should be created'''
|
||||
return suite['generated']
|
||||
|
||||
def isDynamic(suite):
|
||||
'''Checks whether a suite is dynamic'''
|
||||
return 'create' in suite
|
||||
|
||||
lastIncluded = ''
|
||||
def writeInclude(output, file):
|
||||
'''Add #include "file" statement'''
|
||||
global lastIncluded
|
||||
if file == lastIncluded: return
|
||||
output.writelines( [ '#include "', file, '"\n\n' ] )
|
||||
lastIncluded = file
|
||||
|
||||
def generateSuite( output, suite ):
|
||||
'''Write a suite declared with CXXTEST_SUITE()'''
|
||||
output.write( 'class %s : public CxxTest::TestSuite {\n' % suite['name'] )
|
||||
output.write( 'public:\n' )
|
||||
for line in suite['lines']:
|
||||
output.write(line)
|
||||
output.write( '};\n\n' )
|
||||
|
||||
def writeSuitePointer( output, suite ):
|
||||
'''Create static suite pointer object for dynamic suites'''
|
||||
if noStaticInit:
|
||||
output.write( 'static %s *%s;\n\n' % (suite['name'], suite['object']) )
|
||||
else:
|
||||
output.write( 'static %s *%s = 0;\n\n' % (suite['name'], suite['object']) )
|
||||
|
||||
def writeSuiteObject( output, suite ):
|
||||
'''Create static suite object for non-dynamic suites'''
|
||||
output.writelines( [ "static ", suite['name'], " ", suite['object'], ";\n\n" ] )
|
||||
|
||||
def writeTestList( output, suite ):
|
||||
'''Write the head of the test linked list for a suite'''
|
||||
if noStaticInit:
|
||||
output.write( 'static CxxTest::List %s;\n' % suite['tlist'] )
|
||||
else:
|
||||
output.write( 'static CxxTest::List %s = { 0, 0 };\n' % suite['tlist'] )
|
||||
|
||||
def writeTestDescriptions( output, suite ):
|
||||
'''Write all test descriptions for a suite'''
|
||||
for test in suite['tests']:
|
||||
writeTestDescription( output, suite, test )
|
||||
|
||||
def writeTestDescription( output, suite, test ):
|
||||
'''Write test description object'''
|
||||
output.write( 'static class %s : public CxxTest::RealTestDescription {\n' % test['class'] )
|
||||
output.write( 'public:\n' )
|
||||
if not noStaticInit:
|
||||
output.write( ' %s() : CxxTest::RealTestDescription( %s, %s, %s, "%s" ) {}\n' %
|
||||
(test['class'], suite['tlist'], suite['dobject'], test['line'], test['name']) )
|
||||
output.write( ' void runTest() { %s }\n' % runBody( suite, test ) )
|
||||
output.write( '} %s;\n\n' % test['object'] )
|
||||
|
||||
def runBody( suite, test ):
|
||||
'''Body of TestDescription::run()'''
|
||||
if isDynamic(suite): return dynamicRun( suite, test )
|
||||
else: return staticRun( suite, test )
|
||||
|
||||
def dynamicRun( suite, test ):
|
||||
'''Body of TestDescription::run() for test in a dynamic suite'''
|
||||
return 'if ( ' + suite['object'] + ' ) ' + suite['object'] + '->' + test['name'] + '();'
|
||||
|
||||
def staticRun( suite, test ):
|
||||
'''Body of TestDescription::run() for test in a non-dynamic suite'''
|
||||
return suite['object'] + '.' + test['name'] + '();'
|
||||
|
||||
def writeSuiteDescription( output, suite ):
|
||||
'''Write SuiteDescription object'''
|
||||
if isDynamic( suite ):
|
||||
writeDynamicDescription( output, suite )
|
||||
else:
|
||||
writeStaticDescription( output, suite )
|
||||
|
||||
def writeDynamicDescription( output, suite ):
|
||||
'''Write SuiteDescription for a dynamic suite'''
|
||||
output.write( 'CxxTest::DynamicSuiteDescription<%s> %s' % (suite['name'], suite['dobject']) )
|
||||
if not noStaticInit:
|
||||
output.write( '( %s, %s, "%s", %s, %s, %s, %s )' %
|
||||
(suite['cfile'], suite['line'], suite['name'], suite['tlist'],
|
||||
suite['object'], suite['create'], suite['destroy']) )
|
||||
output.write( ';\n\n' )
|
||||
|
||||
def writeStaticDescription( output, suite ):
|
||||
'''Write SuiteDescription for a static suite'''
|
||||
output.write( 'CxxTest::StaticSuiteDescription %s' % suite['dobject'] )
|
||||
if not noStaticInit:
|
||||
output.write( '( %s, %s, "%s", %s, %s )' %
|
||||
(suite['cfile'], suite['line'], suite['name'], suite['object'], suite['tlist']) )
|
||||
output.write( ';\n\n' )
|
||||
|
||||
def writeRoot(output):
|
||||
'''Write static members of CxxTest classes'''
|
||||
output.write( '#include <cxxtest/Root.cpp>\n' )
|
||||
|
||||
def writeInitialize(output):
|
||||
'''Write CxxTest::initialize(), which replaces static initialization'''
|
||||
output.write( 'namespace CxxTest {\n' )
|
||||
output.write( ' void initialize()\n' )
|
||||
output.write( ' {\n' )
|
||||
for suite in suites:
|
||||
output.write( ' %s.initialize();\n' % suite['tlist'] )
|
||||
if isDynamic(suite):
|
||||
output.write( ' %s = 0;\n' % suite['object'] )
|
||||
output.write( ' %s.initialize( %s, %s, "%s", %s, %s, %s, %s );\n' %
|
||||
(suite['dobject'], suite['cfile'], suite['line'], suite['name'],
|
||||
suite['tlist'], suite['object'], suite['create'], suite['destroy']) )
|
||||
else:
|
||||
output.write( ' %s.initialize( %s, %s, "%s", %s, %s );\n' %
|
||||
(suite['dobject'], suite['cfile'], suite['line'], suite['name'],
|
||||
suite['object'], suite['tlist']) )
|
||||
|
||||
for test in suite['tests']:
|
||||
output.write( ' %s.initialize( %s, %s, %s, "%s" );\n' %
|
||||
(test['object'], suite['tlist'], suite['dobject'], test['line'], test['name']) )
|
||||
|
||||
output.write( ' }\n' )
|
||||
output.write( '}\n' )
|
||||
|
||||
main()
|
||||
83
test/cxxtest/docs/convert.pl
Normal file
83
test/cxxtest/docs/convert.pl
Normal file
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
die "Usage: $0 <text file> <html file> <TexInfo file>\n"
|
||||
unless scalar @ARGV == 3;
|
||||
|
||||
my ($text, $html, $texi) = @ARGV;
|
||||
|
||||
open TEXT, "<$text" or die "Cannot open text file \"$text\"\n";
|
||||
open HTML, ">$html" or die "Cannot create html file \"$html\"\n";
|
||||
open TEXI, ">$texi" or die "Cannot create TexInfo file \"$texi\"\n";
|
||||
|
||||
print HTML "<html>";
|
||||
|
||||
sub analyze($) {
|
||||
my ($line) = @_;
|
||||
my ($htmlLine, $texiLine) = ($line, $line);
|
||||
|
||||
# command line options
|
||||
$texiLine =~ s/ (--?[a-z-]*)/ \@option{$1}/g;
|
||||
$htmlLine =~ s/ (--?[a-z-]*)/ <tt>$1<\/tt>/g;
|
||||
|
||||
# [Class::]function()
|
||||
$texiLine =~ s/([^A-Za-z])(([A-Z][A-Za-z0-9]*::)?[A-Za-z0-9]+\(\))/$1\@code{$2}/g;
|
||||
$htmlLine =~ s/([^A-Za-z])(([A-Z][A-Za-z0-9]*::)?[A-Za-z0-9]+\(\))/$1<code>$2<\/code>/g;
|
||||
|
||||
# `file'
|
||||
$texiLine =~ s/`([A-Za-z.\/]*)'/\@file{$1}/g;
|
||||
$htmlLine =~ s/`([A-Za-z.\/]*)'/<tt>`$1'<\/tt>/g;
|
||||
|
||||
# TS...
|
||||
$texiLine =~ s/(^|[^A-Z])(TS[A-Za-z_*()]*)/$1\@code{$2}/g;
|
||||
$htmlLine =~ s/(^|[^A-Z])(TS[A-Za-z_*()]*)/$1<code>$2<\/code>/g;
|
||||
|
||||
# CXXTEST_
|
||||
$texiLine =~ s/(CXXTEST_[A-Z_]*)/\@code{$1}/g;
|
||||
$htmlLine =~ s/(CXXTEST_[A-Z_]*)/<tt>$1<\/tt>/g;
|
||||
|
||||
return ($htmlLine, $texiLine);
|
||||
}
|
||||
|
||||
my $line;
|
||||
my $inRelease = 0;
|
||||
while ( defined( $line = <TEXT> ) ) {
|
||||
chomp $line;
|
||||
if ( $line =~ m/^CxxTest Releases/ ) {
|
||||
print HTML "<title>CxxTest Releases</title>\n";
|
||||
print HTML "<h1>CxxTest Releases</h1>\n\n";
|
||||
|
||||
print TEXI "\@appendix Version history\n";
|
||||
print TEXI "\@itemize \@bullet\n";
|
||||
}
|
||||
elsif ( $line =~ m/^(.*):$/ ) {
|
||||
if ( $inRelease ) {
|
||||
print HTML "</ul>\n\n";
|
||||
print TEXI "\@end itemize\n";
|
||||
}
|
||||
|
||||
print HTML "<h2>$1</h2>\n";
|
||||
print HTML "<ul>\n";
|
||||
|
||||
print TEXI "\@item\n\@strong{$1}\n";
|
||||
print TEXI "\@itemize \@minus\n";
|
||||
|
||||
$inRelease = 1;
|
||||
}
|
||||
elsif ( $line =~ m/^ - (.*)$/ ) {
|
||||
my ($htmlLine, $texiLine) = analyze($1);
|
||||
print HTML "<li>$htmlLine</li>\n";
|
||||
print TEXI "\@item\n$texiLine\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ( $inRelease ) {
|
||||
print HTML "</ul>\n\n";
|
||||
print TEXI "\@end itemize\n\n";
|
||||
}
|
||||
|
||||
print HTML "</html>\n";
|
||||
print TEXI "\@end itemize\n";
|
||||
|
||||
close TEXT or die "Error closing text file \"$text\"\n";
|
||||
close HTML or die "Error closing html file \"$html\"\n";
|
||||
close TEXI or die "Error closing TexInfo file \"$texi\"\n";
|
||||
1959
test/cxxtest/docs/guide.html
Normal file
1959
test/cxxtest/docs/guide.html
Normal file
File diff suppressed because it is too large
Load Diff
56
test/cxxtest/docs/index.html
Normal file
56
test/cxxtest/docs/index.html
Normal file
@@ -0,0 +1,56 @@
|
||||
<html>
|
||||
<title>CxxTest</title>
|
||||
<h1>Introduction</h1>
|
||||
|
||||
<p>CxxTest is a JUnit/CppUnit/xUnit-like framework for C++.
|
||||
|
||||
<p>Its advantages over existing alternatives are that it:
|
||||
<ul>
|
||||
<li>Doesn't require RTTI
|
||||
<li>Doesn't require member template functions
|
||||
<li>Doesn't require exception handling
|
||||
<li>Doesn't require any external libraries (including memory management,
|
||||
file/console I/O, graphics libraries)
|
||||
<li>Is distributed entirely as a set of header files
|
||||
</ul>
|
||||
|
||||
<p>This makes it extremely portable and usable.
|
||||
|
||||
<p>CxxTest is available under the <a href="http://www.gnu.org/copyleft/lesser.html">GNU
|
||||
Lesser General Public License</a>.
|
||||
|
||||
<p>See <a href="guide.html">the user's guide</a> for information.
|
||||
It is also available as <a href="http://cxxtest.sourceforge.net/guide.pdf">a PDF file</a>.
|
||||
|
||||
<p>The version history is available <a href="http://cxxtest.sourceforge.net/Versions.html">here</a>.
|
||||
|
||||
<h1>Getting CxxTest</h1>
|
||||
You can always get the latest release from
|
||||
<a href="http://sourceforge.net/project/showfiles.php?group_id=52834">here</a> or
|
||||
<a href="http://dl.sourceforge.net/cxxtest">here</a>.
|
||||
|
||||
<p>There are several files you can download:
|
||||
<ul>
|
||||
<li><code>cxxtest-<i>version</i>-1.noarch.rpm</code>
|
||||
<li><code>cxxtest-<i>version</i>.tar.gz</code>
|
||||
<li><code>cxxtest-<i>version</i>.zip</code>
|
||||
<li><code>cxxtest-guide-<i>version</i>.pdf</code> (the user's guide)
|
||||
</ul>
|
||||
Note that, since CxxTest consists entirely of header files,
|
||||
there is no distinction between source and binary distribution.
|
||||
|
||||
<p>There are also files called <code>cxxtest-selftest-*</code>: these
|
||||
are used (usually by me) to test the portability of CxxTest, so you
|
||||
can probably do without them.
|
||||
|
||||
<p>If you just can't wait for the next release, I sometimes upload betas
|
||||
to <a href="http://cxxtest.sourceforge.net/beta">here</a>.
|
||||
|
||||
<h1>Getting started</h1>
|
||||
Get the sources and build the samples in the sample subdirectory.
|
||||
|
||||
<br>
|
||||
<p>
|
||||
<A href="http://sourceforge.net"> <IMG src="http://sourceforge.net/sflogo.php?group_id=52834&type=4" border="0" alt="SourceForge Logo"></A>
|
||||
|
||||
</html>
|
||||
BIN
test/cxxtest/docs/qt.png
Normal file
BIN
test/cxxtest/docs/qt.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
test/cxxtest/docs/qt2.png
Normal file
BIN
test/cxxtest/docs/qt2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
test/cxxtest/docs/win32.png
Normal file
BIN
test/cxxtest/docs/win32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
test/cxxtest/docs/x11.png
Normal file
BIN
test/cxxtest/docs/x11.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
62
test/cxxtest/sample/Construct
Normal file
62
test/cxxtest/sample/Construct
Normal file
@@ -0,0 +1,62 @@
|
||||
# -*- Perl -*-
|
||||
|
||||
#
|
||||
# This file shows how to use CxxTest with Cons
|
||||
#
|
||||
|
||||
$env = new cons( CXX => ("$^O" eq 'MSWin32') ? 'cl -nologo -GX' : 'c++',
|
||||
CPPPATH => '..',
|
||||
CXXTESTGEN => 'perl -w ../cxxtestgen.pl' );
|
||||
|
||||
@tests = <*.h>;
|
||||
|
||||
# The error printer is the most basic runner
|
||||
CxxTestErrorPrinter $env 'error_printer', @tests;
|
||||
|
||||
# You can also specify which runner you want to use
|
||||
CxxTestRunner $env 'stdio_printer', 'StdioPrinter', @tests;
|
||||
|
||||
# For more control, use template files
|
||||
CxxTestTemplate $env 'file_printer', 'file_printer.tpl', @tests;
|
||||
|
||||
# Or, you can always separate the tests from the runner
|
||||
CxxTest $env 'tests.cpp', '', @tests;
|
||||
Program $env 'yes_no_runner', ('yes_no_runner.cpp', 'tests.cpp');
|
||||
|
||||
|
||||
#
|
||||
# Here is the code used to build these files
|
||||
# You can use this in your own Construct files
|
||||
#
|
||||
|
||||
# cons::CxxTest $env $dst, $options, @srcs
|
||||
# Generates a CxxTest source file, passing the specified options to cxxtestgen
|
||||
sub cons::CxxTest($$$@) {
|
||||
my ($env, $dst, $options, @srcs) = @_;
|
||||
Command $env $dst, @srcs, "%CXXTESTGEN -o %> ${options} %<";
|
||||
}
|
||||
|
||||
# cons::CxxTestTemplate $env $dst, $template, @srcs
|
||||
# Generates and builds a CxxTest runner using a template file
|
||||
sub cons::CxxTestTemplate($$$@) {
|
||||
my ($env, $dst, $template, @srcs) = @_;
|
||||
my $source = "${dst}.cpp";
|
||||
CxxTest $env $source, "--template=${template}", ($template, @srcs);
|
||||
Program $env $dst, $source;
|
||||
}
|
||||
|
||||
# cons::CxxTestRunner $env $dst, $runner, @srcs
|
||||
# Generates and builds a CxxTest runner using the --runner option
|
||||
sub cons::CxxTestRunner($$$@) {
|
||||
my ($env, $dst, $runner, @srcs) = @_;
|
||||
my $source = "${dst}.cpp";
|
||||
CxxTest $env $source, "--runner=${runner}", @srcs;
|
||||
Program $env $dst, $source;
|
||||
}
|
||||
|
||||
# cons::CxxTestErrorPrinter $env $dst, @srcs
|
||||
# Generates and builds a CxxTest ErrorPrinter
|
||||
sub cons::CxxTestErrorPrinter($$@) {
|
||||
my ($env, $dst, @srcs) = @_;
|
||||
CxxTestRunner $env $dst, 'ErrorPrinter', @srcs;
|
||||
}
|
||||
31
test/cxxtest/sample/CreatedTest.h
Normal file
31
test/cxxtest/sample/CreatedTest.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef __CREATEDTEST_H
|
||||
#define __CREATEDTEST_H
|
||||
|
||||
#include <cxxtest/TestSuite.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
|
||||
//
|
||||
// This test suite shows what to do when your test case
|
||||
// class cannot be instantiated statically.
|
||||
// As an example, this test suite requires a non-default constructor.
|
||||
//
|
||||
|
||||
class CreatedTest : public CxxTest::TestSuite
|
||||
{
|
||||
char *_buffer;
|
||||
public:
|
||||
CreatedTest( unsigned size ) : _buffer( new char[size] ) {}
|
||||
virtual ~CreatedTest() { delete[] _buffer; }
|
||||
|
||||
static CreatedTest *createSuite() { return new CreatedTest( 16 ); }
|
||||
static void destroySuite( CreatedTest *suite ) { delete suite; }
|
||||
|
||||
void test_nothing()
|
||||
{
|
||||
TS_FAIL( "Nothing to test" );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // __CREATEDTEST_H
|
||||
27
test/cxxtest/sample/DeltaTest.h
Normal file
27
test/cxxtest/sample/DeltaTest.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef __DELTATEST_H
|
||||
#define __DELTATEST_H
|
||||
|
||||
#include <cxxtest/TestSuite.h>
|
||||
#include <math.h>
|
||||
|
||||
class DeltaTest : public CxxTest::TestSuite
|
||||
{
|
||||
double _pi, _delta;
|
||||
|
||||
public:
|
||||
void setUp()
|
||||
{
|
||||
_pi = 3.1415926535;
|
||||
_delta = 0.0001;
|
||||
}
|
||||
|
||||
void testSine()
|
||||
{
|
||||
TS_ASSERT_DELTA( sin(0.0), 0.0, _delta );
|
||||
TS_ASSERT_DELTA( sin(_pi / 6), 0.5, _delta );
|
||||
TS_ASSERT_DELTA( sin(_pi / 2), 1.0, _delta );
|
||||
TS_ASSERT_DELTA( sin(_pi), 0.0, _delta );
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __DELTATEST_H
|
||||
39
test/cxxtest/sample/EnumTraits.h
Normal file
39
test/cxxtest/sample/EnumTraits.h
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// This is a test of CxxTest's ValueTraits for enumerations.
|
||||
//
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
//
|
||||
// First define your enumeration
|
||||
//
|
||||
enum Answer {
|
||||
Yes,
|
||||
No,
|
||||
Maybe,
|
||||
DontKnow,
|
||||
DontCare
|
||||
};
|
||||
|
||||
//
|
||||
// Now make CxxTest aware of it
|
||||
//
|
||||
CXXTEST_ENUM_TRAITS( Answer,
|
||||
CXXTEST_ENUM_MEMBER( Yes )
|
||||
CXXTEST_ENUM_MEMBER( No )
|
||||
CXXTEST_ENUM_MEMBER( Maybe )
|
||||
CXXTEST_ENUM_MEMBER( DontKnow )
|
||||
CXXTEST_ENUM_MEMBER( DontCare ) );
|
||||
|
||||
class EnumTraits : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_Enum_traits()
|
||||
{
|
||||
TS_FAIL( Yes );
|
||||
TS_FAIL( No );
|
||||
TS_FAIL( Maybe );
|
||||
TS_FAIL( DontKnow );
|
||||
TS_FAIL( DontCare );
|
||||
TS_FAIL( (Answer)1000 );
|
||||
}
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user