diff options
Diffstat (limited to 'test/common/testcommon.cpp')
-rw-r--r-- | test/common/testcommon.cpp | 306 |
1 files changed, 176 insertions, 130 deletions
diff --git a/test/common/testcommon.cpp b/test/common/testcommon.cpp index f47a0dba..cba40fe7 100644 --- a/test/common/testcommon.cpp +++ b/test/common/testcommon.cpp @@ -160,8 +160,9 @@ class TestLogger : public Logger bool IsTriggered() { return mTriggered; } void Reset() { mTriggered = false; } - virtual bool Log(Log::Level level, const std::string& rFile, - int line, std::string& rMessage) + virtual bool Log(Log::Level level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message) { if (level == mTargetLevel) { @@ -261,6 +262,18 @@ int test(int argc, const char *argv[]) TEST_THAT(!TestFileExists(tempfile.c_str())); } + // Test that named locks work as expected + { + NamedLock lock1; + TEST_THAT(lock1.TryAndGetLock("testfiles/locktest")); + // With a lock held, we should not be able to acquire another. + TEST_THAT(!NamedLock().TryAndGetLock("testfiles/locktest")); + } + { + // But with the lock released, we should be able to. + TEST_THAT(NamedLock().TryAndGetLock("testfiles/locktest")); + } + // Test that memory leak detection doesn't crash { char *test = new char[1024]; @@ -273,21 +286,21 @@ int test(int argc, const char *argv[]) { Timers::Cleanup(); - TEST_THAT(memleakfinder_numleaks() == 0); + TEST_EQUAL(0, memleakfinder_numleaks()); void *block = ::malloc(12); - TEST_THAT(memleakfinder_numleaks() == 1); + TEST_EQUAL(1, memleakfinder_numleaks()); void *b2 = ::realloc(block, 128*1024); - TEST_THAT(memleakfinder_numleaks() == 1); + TEST_EQUAL(1, memleakfinder_numleaks()); ::free(b2); - TEST_THAT(memleakfinder_numleaks() == 0); + TEST_EQUAL(0, memleakfinder_numleaks()); char *test = new char[1024]; - TEST_THAT(memleakfinder_numleaks() == 1); + TEST_EQUAL(1, memleakfinder_numleaks()); MemBlockStream *s = new MemBlockStream(test,12); - TEST_THAT(memleakfinder_numleaks() == 2); + TEST_EQUAL(3, memleakfinder_numleaks()); delete s; - TEST_THAT(memleakfinder_numleaks() == 1); + TEST_EQUAL(1, memleakfinder_numleaks()); delete [] test; - TEST_THAT(memleakfinder_numleaks() == 0); + TEST_EQUAL(0, memleakfinder_numleaks()); Timers::Init(); } @@ -299,16 +312,19 @@ int test(int argc, const char *argv[]) // Check that using timer methods without initialisation // throws an assertion failure. Can only do this in debug mode #ifndef BOX_RELEASE_BUILD - TEST_CHECK_THROWS(Timers::Add(*(Timer*)NULL), - CommonException, AssertFailed); - TEST_CHECK_THROWS(Timers::Remove(*(Timer*)NULL), - CommonException, AssertFailed); - #endif - - // TEST_CHECK_THROWS(Timers::Signal(), CommonException, AssertFailed); - #ifndef BOX_RELEASE_BUILD + { TEST_CHECK_THROWS(Timers::Cleanup(), CommonException, AssertFailed); + + Timer tim(0, "tim"); + TEST_CHECK_THROWS(Timers::Add(tim), CommonException, AssertFailed); + Timers::Remove(tim); + + TEST_CHECK_THROWS(Timer t1(900, "t1"), CommonException, + AssertFailed); + + // TEST_CHECK_THROWS(Timers::Signal(), CommonException, AssertFailed); + } #endif // Check that we can initialise the timers @@ -331,47 +347,60 @@ int test(int argc, const char *argv[]) Timers::Init(); - Timer t0(0, "t0"); // should never expire - Timer t1(1000, "t1"); - Timer t2(2000, "t2"); - Timer t3(3000, "t3"); - - TEST_THAT(!t0.HasExpired()); - TEST_THAT(!t1.HasExpired()); - TEST_THAT(!t2.HasExpired()); - TEST_THAT(!t3.HasExpired()); - - safe_sleep(1); - TEST_THAT(!t0.HasExpired()); - TEST_THAT(t1.HasExpired()); - TEST_THAT(!t2.HasExpired()); - TEST_THAT(!t3.HasExpired()); - - safe_sleep(1); - TEST_THAT(!t0.HasExpired()); - TEST_THAT(t1.HasExpired()); - TEST_THAT(t2.HasExpired()); - TEST_THAT(!t3.HasExpired()); - - // Try both ways of resetting an existing timer. - t1 = Timer(1000, "t1a"); - t2.Reset(2000); - TEST_THAT(!t0.HasExpired()); - TEST_THAT(!t1.HasExpired()); - TEST_THAT(!t2.HasExpired()); - TEST_THAT(!t3.HasExpired()); - - safe_sleep(1); - TEST_THAT(!t0.HasExpired()); - TEST_THAT(t1.HasExpired()); - TEST_THAT(!t2.HasExpired()); - TEST_THAT(t3.HasExpired()); - - safe_sleep(1); - TEST_THAT(!t0.HasExpired()); - TEST_THAT(t1.HasExpired()); - TEST_THAT(t2.HasExpired()); - TEST_THAT(t3.HasExpired()); + // Ideally timers would be perfectly accurate and we could sleep for 1.0 seconds, but + // on OSX in particular they could fire 50-100 ms late (I've seen 4 ms in practice) + // and we don't want the tests to fail because of this, because we don't really need + // that kind of precision in practice. So we reduce the timer intervals by 100ms to + // be safe. + + { + Logger::LevelGuard temporary_verbosity(Logging::GetConsole(), Log::TRACE); + Console::SettingsGuard save_old_settings; + Console::SetShowTime(true); + Console::SetShowTimeMicros(true); + + Timer t0(0, "t0"); // should never expire + Timer t1(900, "t1"); + Timer t2(1900, "t2"); + Timer t3(2900, "t3"); + + TEST_THAT(!t0.HasExpired()); + TEST_THAT(!t1.HasExpired()); + TEST_THAT(!t2.HasExpired()); + TEST_THAT(!t3.HasExpired()); + safe_sleep(1); + + TEST_THAT(!t0.HasExpired()); + TEST_THAT(t1.HasExpired()); + TEST_THAT(!t2.HasExpired()); + TEST_THAT(!t3.HasExpired()); + + safe_sleep(1); + TEST_THAT(!t0.HasExpired()); + TEST_THAT(t1.HasExpired()); + TEST_THAT(t2.HasExpired()); + TEST_THAT(!t3.HasExpired()); + + // Try both ways of resetting an existing timer. + t1 = Timer(900, "t1a"); + t2.Reset(1900); + TEST_THAT(!t0.HasExpired()); + TEST_THAT(!t1.HasExpired()); + TEST_THAT(!t2.HasExpired()); + TEST_THAT(!t3.HasExpired()); + + safe_sleep(1); + TEST_THAT(!t0.HasExpired()); + TEST_THAT(t1.HasExpired()); + TEST_THAT(!t2.HasExpired()); + TEST_THAT(t3.HasExpired()); + + safe_sleep(1); + TEST_THAT(!t0.HasExpired()); + TEST_THAT(t1.HasExpired()); + TEST_THAT(t2.HasExpired()); + TEST_THAT(t3.HasExpired()); + } // Leave timers initialised for rest of test. // Test main() will cleanup after test finishes. @@ -407,20 +436,18 @@ int test(int argc, const char *argv[]) DIRECTORY_SEPARATOR "fdgetlinetest.txt"); FdGetLine getline(file); - int l = 0; - while(testfilelines[l] != 0) - { - TEST_THAT(!getline.IsEOF()); - std::string line = getline.GetLine(true); - printf("expected |%s| got |%s|\n", testfilelines[l], - line.c_str()); - TEST_LINE(strcmp(testfilelines[l], line.c_str()) == 0, - line); - l++; - } - TEST_THAT(getline.IsEOF()); - TEST_CHECK_THROWS(getline.GetLine(true), CommonException, GetLineEOF); + int l = 0; + while(testfilelines[l] != 0) + { + TEST_THAT(!getline.IsEOF()); + std::string line = getline.GetLine(true); + TEST_EQUAL(testfilelines[l], line); + l++; + } + TEST_THAT(getline.IsEOF()); + TEST_CHECK_THROWS(getline.GetLine(true), CommonException, GetLineEOF); } + // and again without pre-processing { FileHandleGuard<O_RDONLY> file("testfiles" @@ -430,7 +457,7 @@ int test(int argc, const char *argv[]) TEST_THAT_ABORTONFAIL(file2 != 0); FdGetLine getline(file); char ll[512]; - + while(!feof(file2)) { fgets(ll, sizeof(ll), file2); @@ -440,40 +467,38 @@ int test(int argc, const char *argv[]) e--; } ll[e] = '\0'; - - TEST_THAT(!getline.IsEOF()); - std::string line = getline.GetLine(false); - //printf("expected |%s| got |%s|\n", ll, line.c_str()); - TEST_THAT(strcmp(ll, line.c_str()) == 0); + + TEST_THAT(!getline.IsEOF()); + std::string line = getline.GetLine(false); + TEST_EQUAL(ll, line); } - TEST_THAT(getline.IsEOF()); - TEST_CHECK_THROWS(getline.GetLine(true), CommonException, GetLineEOF); + TEST_THAT(getline.IsEOF()); + TEST_CHECK_THROWS(getline.GetLine(true), CommonException, GetLineEOF); fclose(file2); } - + // Then the IOStream version of get line, seeing as we're here... { FileStream file("testfiles" DIRECTORY_SEPARATOR "fdgetlinetest.txt", O_RDONLY); IOStreamGetLine getline(file); - int l = 0; - while(testfilelines[l] != 0) - { - TEST_THAT(!getline.IsEOF()); - std::string line; - while(!getline.GetLine(line, true)) - ; - printf("expected |%s| got |%s|\n", testfilelines[l], - line.c_str()); - TEST_LINE(strcmp(testfilelines[l], line.c_str()) == 0, - line); - l++; - } - TEST_THAT(getline.IsEOF()); - std::string dummy; - TEST_CHECK_THROWS(getline.GetLine(dummy, true), CommonException, GetLineEOF); + int l = 0; + while(testfilelines[l] != 0) + { + TEST_THAT(!getline.IsEOF()); + std::string line; + while(!getline.GetLine(line, true)) + { + // skip line + } + TEST_EQUAL(testfilelines[l], line); + l++; + } + TEST_THAT(getline.IsEOF()); + std::string dummy; + TEST_CHECK_THROWS(getline.GetLine(dummy, true), CommonException, GetLineEOF); } // and again without pre-processing { @@ -495,21 +520,20 @@ int test(int argc, const char *argv[]) e--; } ll[e] = '\0'; - - TEST_THAT(!getline.IsEOF()); - std::string line; - while(!getline.GetLine(line, false)) - ; - //printf("expected |%s| got |%s|\n", ll, line.c_str()); - TEST_THAT(strcmp(ll, line.c_str()) == 0); + + TEST_THAT(!getline.IsEOF()); + std::string line; + while(!getline.GetLine(line, false)) + ; + TEST_EQUAL(ll, line); } - TEST_THAT(getline.IsEOF()); - std::string dummy; - TEST_CHECK_THROWS(getline.GetLine(dummy, true), CommonException, GetLineEOF); + TEST_THAT(getline.IsEOF()); + std::string dummy; + TEST_CHECK_THROWS(getline.GetLine(dummy, true), CommonException, GetLineEOF); fclose(file2); } - + // Doesn't exist { std::string errMsg; @@ -569,50 +593,69 @@ int test(int argc, const char *argv[]) TEST_THAT(sub1_3.GetKeyValue("terrible") == "absolutely"); } - static const char *file[] = + static const char *file[][2] = { - "testfiles" DIRECTORY_SEPARATOR "config2.txt", + {"testfiles" DIRECTORY_SEPARATOR "config2.txt", + "<root>.TOPlevel (key) is missing."}, // Value missing from root - "testfiles" DIRECTORY_SEPARATOR "config3.txt", + {"testfiles" DIRECTORY_SEPARATOR "config3.txt", + "Unexpected start block in test1"}, // Unexpected { - "testfiles" DIRECTORY_SEPARATOR "config4.txt", + {"testfiles" DIRECTORY_SEPARATOR "config4.txt", + "Root level has close block -- forgot to terminate subblock?"}, // Missing } - "testfiles" DIRECTORY_SEPARATOR "config5.txt", + {"testfiles" DIRECTORY_SEPARATOR "config5.txt", + "Block subconfig2 wasn't started correctly (no '{' on line of it's own)\n" + "Root level has close block -- forgot to terminate subblock?"}, // { expected, but wasn't there - "testfiles" DIRECTORY_SEPARATOR "config6.txt", + {"testfiles" DIRECTORY_SEPARATOR "config6.txt", + "test1.subconfig2.bing (key) multi value not allowed (duplicated key?)."}, // Duplicate key - "testfiles" DIRECTORY_SEPARATOR "config7.txt", + {"testfiles" DIRECTORY_SEPARATOR "config7.txt", + "Invalid configuration key: = invalid thing here!"}, // Invalid key (no name) - "testfiles" DIRECTORY_SEPARATOR "config8.txt", + {"testfiles" DIRECTORY_SEPARATOR "config8.txt", + "File ended without terminating all subblocks"}, // Not all sub blocks terminated - "testfiles" DIRECTORY_SEPARATOR "config9.txt", + {"testfiles" DIRECTORY_SEPARATOR "config9.txt", + "test1.subconfig3.carrots (key) is not a valid integer."}, // Not valid integer - "testfiles" DIRECTORY_SEPARATOR "config9b.txt", + {"testfiles" DIRECTORY_SEPARATOR "config9b.txt", + "test1.subconfig2.carrots (key) is not a valid integer."}, // Not valid integer - "testfiles" DIRECTORY_SEPARATOR "config9c.txt", + {"testfiles" DIRECTORY_SEPARATOR "config9c.txt", + "test1.subconfig2.carrots (key) is not a valid integer."}, // Not valid integer - "testfiles" DIRECTORY_SEPARATOR "config9d.txt", + {"testfiles" DIRECTORY_SEPARATOR "config9d.txt", + "test1.subconfig3.carrots (key) is not a valid integer."}, // Not valid integer - "testfiles" DIRECTORY_SEPARATOR "config10.txt", + {"testfiles" DIRECTORY_SEPARATOR "config10.txt", + "test1.subconfig.carrots (key) is missing."}, // Missing key (in subblock) - "testfiles" DIRECTORY_SEPARATOR "config11.txt", + {"testfiles" DIRECTORY_SEPARATOR "config11.txt", + "test1.subconfig3.NOTEXPECTED (key) is not a known key. Check spelling and placement."}, // Unknown key - "testfiles" DIRECTORY_SEPARATOR "config12.txt", + {"testfiles" DIRECTORY_SEPARATOR "config12.txt", + "<root>.test1.otherthing (block) is missing."}, // Missing block - "testfiles" DIRECTORY_SEPARATOR "config13.txt", + {"testfiles" DIRECTORY_SEPARATOR "config13.txt", + "<root>.test1.* (block) is missing (a block must be present).\n" + "<root>.test1.otherthing (block) is missing."}, // Subconfig (wildcarded) should exist, but missing (ie nothing present) - "testfiles" DIRECTORY_SEPARATOR "config16.txt", + {"testfiles" DIRECTORY_SEPARATOR "config16.txt", + "<root>.BoolTrue1 (key) is not a valid boolean value."}, // bad boolean value - 0 + {NULL, NULL}, }; - for(int l = 0; file[l] != 0; ++l) + for(int l = 0; file[l][0] != 0; ++l) { + HideCategoryGuard hide(ConfigurationVerify::VERIFY_ERROR); std::string errMsg; - std::auto_ptr<Configuration> pconfig(Configuration::LoadAndVerify(file[l], &verify, errMsg)); + std::auto_ptr<Configuration> pconfig(Configuration::LoadAndVerify(file[l][0], &verify, errMsg)); TEST_THAT(pconfig.get() == 0); - TEST_THAT(!errMsg.empty()); - printf("(%s) Error msg is:\n------\n%s------\n", file[l], errMsg.c_str()); + errMsg = errMsg.substr(0, errMsg.size() > 0 ? errMsg.size() - 1 : 0); + TEST_EQUAL_LINE(file[l][1], errMsg, file[l][0]); } // Check that multivalues happen as expected @@ -764,10 +807,13 @@ int test(int argc, const char *argv[]) // Add regex entries #ifdef HAVE_REGEX_SUPPORT + { + HideCategoryGuard hide(ConfigurationVerify::VERIFY_ERROR); elist.AddRegexEntries(std::string("[a-d]+\\.reg$" "\x01" "EXCLUDE" "\x01" "^exclude$")); elist.AddRegexEntries(std::string("")); TEST_CHECK_THROWS(elist.AddRegexEntries(std::string("[:not_valid")), CommonException, BadRegularExpression); TEST_THAT(elist.SizeOfRegexList() == 3); + } #else TEST_CHECK_THROWS(elist.AddRegexEntries(std::string("[a-d]+\\.reg$" "\x01" "EXCLUDE" "\x01" "^exclude$")), CommonException, RegexNotSupportedOnThisPlatform); TEST_THAT(elist.SizeOfRegexList() == 0); |