diff options
author | 2015-01-10 13:53:11 +0100 | |
---|---|---|
committer | 2015-01-10 13:53:11 +0100 | |
commit | 02d37b6915e453fbc40afc80830d9a2cbb459d1f (patch) | |
tree | 87d7a4c5a93f9ecca1d955cfdac6fe25399a9b69 /3rdparty/jsoncpp/src/test_lib_json/jsontest.cpp | |
parent | 950a428641808b5d083dcfddebbed06367f15a15 (diff) |
Added integral version of jsoncpp source (nw)
Diffstat (limited to '3rdparty/jsoncpp/src/test_lib_json/jsontest.cpp')
-rw-r--r-- | 3rdparty/jsoncpp/src/test_lib_json/jsontest.cpp | 443 |
1 files changed, 443 insertions, 0 deletions
diff --git a/3rdparty/jsoncpp/src/test_lib_json/jsontest.cpp b/3rdparty/jsoncpp/src/test_lib_json/jsontest.cpp new file mode 100644 index 00000000000..ef9c543fa47 --- /dev/null +++ b/3rdparty/jsoncpp/src/test_lib_json/jsontest.cpp @@ -0,0 +1,443 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#define _CRT_SECURE_NO_WARNINGS 1 // Prevents deprecation warning with MSVC +#include "jsontest.h" +#include <stdio.h> +#include <string> + +#if defined(_MSC_VER) +// Used to install a report hook that prevent dialog on assertion and error. +#include <crtdbg.h> +#endif // if defined(_MSC_VER) + +#if defined(_WIN32) +// Used to prevent dialog on memory fault. +// Limits headers included by Windows.h +#define WIN32_LEAN_AND_MEAN +#define NOSERVICE +#define NOMCX +#define NOIME +#define NOSOUND +#define NOCOMM +#define NORPC +#define NOGDI +#define NOUSER +#define NODRIVERS +#define NOLOGERROR +#define NOPROFILER +#define NOMEMMGR +#define NOLFILEIO +#define NOOPENFILE +#define NORESOURCE +#define NOATOM +#define NOLANGUAGE +#define NOLSTRING +#define NODBCS +#define NOKEYBOARDINFO +#define NOGDICAPMASKS +#define NOCOLOR +#define NOGDIOBJ +#define NODRAWTEXT +#define NOTEXTMETRIC +#define NOSCALABLEFONT +#define NOBITMAP +#define NORASTEROPS +#define NOMETAFILE +#define NOSYSMETRICS +#define NOSYSTEMPARAMSINFO +#define NOMSG +#define NOWINSTYLES +#define NOWINOFFSETS +#define NOSHOWWINDOW +#define NODEFERWINDOWPOS +#define NOVIRTUALKEYCODES +#define NOKEYSTATES +#define NOWH +#define NOMENUS +#define NOSCROLL +#define NOCLIPBOARD +#define NOICONS +#define NOMB +#define NOSYSCOMMANDS +#define NOMDI +#define NOCTLMGR +#define NOWINMESSAGES +#include <windows.h> +#endif // if defined(_WIN32) + +namespace JsonTest { + +// class TestResult +// ////////////////////////////////////////////////////////////////// + +TestResult::TestResult() + : predicateId_(1), lastUsedPredicateId_(0), messageTarget_(0) { + // The root predicate has id 0 + rootPredicateNode_.id_ = 0; + rootPredicateNode_.next_ = 0; + predicateStackTail_ = &rootPredicateNode_; +} + +void TestResult::setTestName(const std::string& name) { name_ = name; } + +TestResult& +TestResult::addFailure(const char* file, unsigned int line, const char* expr) { + /// Walks the PredicateContext stack adding them to failures_ if not already + /// added. + unsigned int nestingLevel = 0; + PredicateContext* lastNode = rootPredicateNode_.next_; + for (; lastNode != 0; lastNode = lastNode->next_) { + if (lastNode->id_ > lastUsedPredicateId_) // new PredicateContext + { + lastUsedPredicateId_ = lastNode->id_; + addFailureInfo( + lastNode->file_, lastNode->line_, lastNode->expr_, nestingLevel); + // Link the PredicateContext to the failure for message target when + // popping the PredicateContext. + lastNode->failure_ = &(failures_.back()); + } + ++nestingLevel; + } + + // Adds the failed assertion + addFailureInfo(file, line, expr, nestingLevel); + messageTarget_ = &(failures_.back()); + return *this; +} + +void TestResult::addFailureInfo(const char* file, + unsigned int line, + const char* expr, + unsigned int nestingLevel) { + Failure failure; + failure.file_ = file; + failure.line_ = line; + if (expr) { + failure.expr_ = expr; + } + failure.nestingLevel_ = nestingLevel; + failures_.push_back(failure); +} + +TestResult& TestResult::popPredicateContext() { + PredicateContext* lastNode = &rootPredicateNode_; + while (lastNode->next_ != 0 && lastNode->next_->next_ != 0) { + lastNode = lastNode->next_; + } + // Set message target to popped failure + PredicateContext* tail = lastNode->next_; + if (tail != 0 && tail->failure_ != 0) { + messageTarget_ = tail->failure_; + } + // Remove tail from list + predicateStackTail_ = lastNode; + lastNode->next_ = 0; + return *this; +} + +bool TestResult::failed() const { return !failures_.empty(); } + +unsigned int TestResult::getAssertionNestingLevel() const { + unsigned int level = 0; + const PredicateContext* lastNode = &rootPredicateNode_; + while (lastNode->next_ != 0) { + lastNode = lastNode->next_; + ++level; + } + return level; +} + +void TestResult::printFailure(bool printTestName) const { + if (failures_.empty()) { + return; + } + + if (printTestName) { + printf("* Detail of %s test failure:\n", name_.c_str()); + } + + // Print in reverse to display the callstack in the right order + Failures::const_iterator itEnd = failures_.end(); + for (Failures::const_iterator it = failures_.begin(); it != itEnd; ++it) { + const Failure& failure = *it; + std::string indent(failure.nestingLevel_ * 2, ' '); + if (failure.file_) { + printf("%s%s(%d): ", indent.c_str(), failure.file_, failure.line_); + } + if (!failure.expr_.empty()) { + printf("%s\n", failure.expr_.c_str()); + } else if (failure.file_) { + printf("\n"); + } + if (!failure.message_.empty()) { + std::string reindented = indentText(failure.message_, indent + " "); + printf("%s\n", reindented.c_str()); + } + } +} + +std::string TestResult::indentText(const std::string& text, + const std::string& indent) { + std::string reindented; + std::string::size_type lastIndex = 0; + while (lastIndex < text.size()) { + std::string::size_type nextIndex = text.find('\n', lastIndex); + if (nextIndex == std::string::npos) { + nextIndex = text.size() - 1; + } + reindented += indent; + reindented += text.substr(lastIndex, nextIndex - lastIndex + 1); + lastIndex = nextIndex + 1; + } + return reindented; +} + +TestResult& TestResult::addToLastFailure(const std::string& message) { + if (messageTarget_ != 0) { + messageTarget_->message_ += message; + } + return *this; +} + +TestResult& TestResult::operator<<(Json::Int64 value) { + return addToLastFailure(Json::valueToString(value)); +} + +TestResult& TestResult::operator<<(Json::UInt64 value) { + return addToLastFailure(Json::valueToString(value)); +} + +TestResult& TestResult::operator<<(bool value) { + return addToLastFailure(value ? "true" : "false"); +} + +// class TestCase +// ////////////////////////////////////////////////////////////////// + +TestCase::TestCase() : result_(0) {} + +TestCase::~TestCase() {} + +void TestCase::run(TestResult& result) { + result_ = &result; + runTestCase(); +} + +// class Runner +// ////////////////////////////////////////////////////////////////// + +Runner::Runner() {} + +Runner& Runner::add(TestCaseFactory factory) { + tests_.push_back(factory); + return *this; +} + +unsigned int Runner::testCount() const { + return static_cast<unsigned int>(tests_.size()); +} + +std::string Runner::testNameAt(unsigned int index) const { + TestCase* test = tests_[index](); + std::string name = test->testName(); + delete test; + return name; +} + +void Runner::runTestAt(unsigned int index, TestResult& result) const { + TestCase* test = tests_[index](); + result.setTestName(test->testName()); + printf("Testing %s: ", test->testName()); + fflush(stdout); +#if JSON_USE_EXCEPTION + try { +#endif // if JSON_USE_EXCEPTION + test->run(result); +#if JSON_USE_EXCEPTION + } + catch (const std::exception& e) { + result.addFailure(__FILE__, __LINE__, "Unexpected exception caught:") + << e.what(); + } +#endif // if JSON_USE_EXCEPTION + delete test; + const char* status = result.failed() ? "FAILED" : "OK"; + printf("%s\n", status); + fflush(stdout); +} + +bool Runner::runAllTest(bool printSummary) const { + unsigned int count = testCount(); + std::deque<TestResult> failures; + for (unsigned int index = 0; index < count; ++index) { + TestResult result; + runTestAt(index, result); + if (result.failed()) { + failures.push_back(result); + } + } + + if (failures.empty()) { + if (printSummary) { + printf("All %d tests passed\n", count); + } + return true; + } else { + for (unsigned int index = 0; index < failures.size(); ++index) { + TestResult& result = failures[index]; + result.printFailure(count > 1); + } + + if (printSummary) { + unsigned int failedCount = static_cast<unsigned int>(failures.size()); + unsigned int passedCount = count - failedCount; + printf("%d/%d tests passed (%d failure(s))\n", + passedCount, + count, + failedCount); + } + return false; + } +} + +bool Runner::testIndex(const std::string& testName, + unsigned int& indexOut) const { + unsigned int count = testCount(); + for (unsigned int index = 0; index < count; ++index) { + if (testNameAt(index) == testName) { + indexOut = index; + return true; + } + } + return false; +} + +void Runner::listTests() const { + unsigned int count = testCount(); + for (unsigned int index = 0; index < count; ++index) { + printf("%s\n", testNameAt(index).c_str()); + } +} + +int Runner::runCommandLine(int argc, const char* argv[]) const { + typedef std::deque<std::string> TestNames; + Runner subrunner; + for (int index = 1; index < argc; ++index) { + std::string opt = argv[index]; + if (opt == "--list-tests") { + listTests(); + return 0; + } else if (opt == "--test-auto") { + preventDialogOnCrash(); + } else if (opt == "--test") { + ++index; + if (index < argc) { + unsigned int testNameIndex; + if (testIndex(argv[index], testNameIndex)) { + subrunner.add(tests_[testNameIndex]); + } else { + fprintf(stderr, "Test '%s' does not exist!\n", argv[index]); + return 2; + } + } else { + printUsage(argv[0]); + return 2; + } + } else { + printUsage(argv[0]); + return 2; + } + } + bool succeeded; + if (subrunner.testCount() > 0) { + succeeded = subrunner.runAllTest(subrunner.testCount() > 1); + } else { + succeeded = runAllTest(true); + } + return succeeded ? 0 : 1; +} + +#if defined(_MSC_VER) && defined(_DEBUG) +// Hook MSVCRT assertions to prevent dialog from appearing +static int +msvcrtSilentReportHook(int reportType, char* message, int* /*returnValue*/) { + // The default CRT handling of error and assertion is to display + // an error dialog to the user. + // Instead, when an error or an assertion occurs, we force the + // application to terminate using abort() after display + // the message on stderr. + if (reportType == _CRT_ERROR || reportType == _CRT_ASSERT) { + // calling abort() cause the ReportHook to be called + // The following is used to detect this case and let's the + // error handler fallback on its default behaviour ( + // display a warning message) + static volatile bool isAborting = false; + if (isAborting) { + return TRUE; + } + isAborting = true; + + fprintf(stderr, "CRT Error/Assert:\n%s\n", message); + fflush(stderr); + abort(); + } + // Let's other reportType (_CRT_WARNING) be handled as they would by default + return FALSE; +} +#endif // if defined(_MSC_VER) + +void Runner::preventDialogOnCrash() { +#if defined(_MSC_VER) && defined(_DEBUG) + // Install a hook to prevent MSVCRT error and assertion from + // popping a dialog + // This function a NO-OP in release configuration + // (which cause warning since msvcrtSilentReportHook is not referenced) + _CrtSetReportHook(&msvcrtSilentReportHook); +#endif // if defined(_MSC_VER) + +// @todo investiguate this handler (for buffer overflow) +// _set_security_error_handler + +#if defined(_WIN32) + // Prevents the system from popping a dialog for debugging if the + // application fails due to invalid memory access. + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | + SEM_NOOPENFILEERRORBOX); +#endif // if defined(_WIN32) +} + +void Runner::printUsage(const char* appName) { + printf("Usage: %s [options]\n" + "\n" + "If --test is not specified, then all the test cases be run.\n" + "\n" + "Valid options:\n" + "--list-tests: print the name of all test cases on the standard\n" + " output and exit.\n" + "--test TESTNAME: executes the test case with the specified name.\n" + " May be repeated.\n" + "--test-auto: prevent dialog prompting for debugging on crash.\n", + appName); +} + +// Assertion functions +// ////////////////////////////////////////////////////////////////// + +TestResult& checkStringEqual(TestResult& result, + const std::string& expected, + const std::string& actual, + const char* file, + unsigned int line, + const char* expr) { + if (expected != actual) { + result.addFailure(file, line, expr); + result << "Expected: '" << expected << "'\n"; + result << "Actual : '" << actual << "'"; + } + return result; +} + +} // namespace JsonTest |