Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Zolotarev <deathbaba@gmail.com>2010-12-05 19:24:16 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-22 22:33:57 +0300
commitd6e12b7ce4bcbf0ccd1c07eb25de143422913c34 (patch)
treea7e910c330ce4da9b4f2d8be76067adece2561c4 /testing
One Month In Minsk. Made in Belarus.
Diffstat (limited to 'testing')
-rw-r--r--testing/benchmark.hpp56
-rw-r--r--testing/on_test_fail.hpp13
-rw-r--r--testing/testing.config1
-rw-r--r--testing/testing.creator1
-rw-r--r--testing/testing.files4
-rw-r--r--testing/testing.hpp60
-rw-r--r--testing/testing.includes0
-rw-r--r--testing/testingmain.cpp98
-rw-r--r--testing/testregister.hpp36
9 files changed, 269 insertions, 0 deletions
diff --git a/testing/benchmark.hpp b/testing/benchmark.hpp
new file mode 100644
index 0000000000..b7c8972967
--- /dev/null
+++ b/testing/benchmark.hpp
@@ -0,0 +1,56 @@
+#pragma once
+#include "testing.hpp"
+#include "testregister.hpp"
+#include "../base/timer.hpp"
+#include "../std/iostream.hpp"
+
+namespace my
+{
+ class BenchmarkNTimes
+ {
+ public:
+ BenchmarkNTimes(int repeatCount, double maxSecondsToSucceed)
+ : m_RepeatCount(repeatCount), m_MaxSecondsToSucceed(maxSecondsToSucceed), m_Iteration(0)
+ {
+ }
+
+ ~BenchmarkNTimes()
+ {
+ double const secondsElapsed = m_Timer.ElapsedSeconds();
+ TEST_GREATER(m_RepeatCount, 0, ());
+ TEST_LESS_OR_EQUAL(secondsElapsed, m_MaxSecondsToSucceed, (m_RepeatCount));
+ cout << secondsElapsed << "s total";
+ if (secondsElapsed > 0)
+ {
+ cout << ", " << static_cast<int>(m_RepeatCount / secondsElapsed) << "/s, ";
+ /*
+ if (secondsElapsed / m_RepeatCount * 1000 >= 10)
+ cout << static_cast<int>(secondsElapsed / m_RepeatCount * 1000) << "ms each";
+ else */ if (secondsElapsed / m_RepeatCount * 1000000 >= 10)
+ cout << static_cast<int>(secondsElapsed / m_RepeatCount * 1000000) << "us each";
+ else
+ cout << static_cast<int>(secondsElapsed / m_RepeatCount * 1000000000) << "ns each";
+ }
+ cout << " ...";
+ }
+
+ inline int Iteration() const { return m_Iteration; }
+ inline bool ContinueIterating() const { return m_Iteration < m_RepeatCount; }
+ inline void NextIteration() { ++m_Iteration; }
+
+ private:
+ int const m_RepeatCount;
+ double const m_MaxSecondsToSucceed;
+ int m_Iteration;
+ Timer m_Timer;
+ };
+}
+
+#define BENCHMARK_TEST(name) \
+ void Benchmark_##name(); \
+ TestRegister g_BenchmarkRegister_##name("Benchmark::"#name, __FILE__, &Benchmark_##name); \
+ void Benchmark_##name()
+
+#define BENCHMARK_N_TIMES(times, maxTimeToSucceed) \
+ for (::my::BenchmarkNTimes benchmark(times, maxTimeToSucceed); \
+ benchmark.ContinueIterating(); benchmark.NextIteration())
diff --git a/testing/on_test_fail.hpp b/testing/on_test_fail.hpp
new file mode 100644
index 0000000000..1854e2c95f
--- /dev/null
+++ b/testing/on_test_fail.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <string>
+
+class OnTestFailImpl;
+
+class OnTestFail
+{
+ OnTestFailImpl * m_pImpl;
+public:
+ OnTestFail(bool ok, char const * check, char const * file, int line);
+ void operator () (std::wstring const & s) const;
+};
diff --git a/testing/testing.config b/testing/testing.config
new file mode 100644
index 0000000000..8cec188b38
--- /dev/null
+++ b/testing/testing.config
@@ -0,0 +1 @@
+// ADD PREDEFINED MACROS HERE!
diff --git a/testing/testing.creator b/testing/testing.creator
new file mode 100644
index 0000000000..e94cbbd302
--- /dev/null
+++ b/testing/testing.creator
@@ -0,0 +1 @@
+[General]
diff --git a/testing/testing.files b/testing/testing.files
new file mode 100644
index 0000000000..283ba17402
--- /dev/null
+++ b/testing/testing.files
@@ -0,0 +1,4 @@
+on_test_fail.hpp
+testing.hpp
+testingmain.cpp
+testregister.hpp \ No newline at end of file
diff --git a/testing/testing.hpp b/testing/testing.hpp
new file mode 100644
index 0000000000..9289840beb
--- /dev/null
+++ b/testing/testing.hpp
@@ -0,0 +1,60 @@
+#pragma once
+#include "testregister.hpp"
+#include "../base/assert.hpp"
+#include "../base/base.hpp"
+#include "../base/exception.hpp"
+#include "../base/math.hpp"
+#include "../base/src_point.hpp"
+#include "../std/iostream.hpp"
+#include "../std/string.hpp"
+
+#define UNIT_TEST(name) \
+ void UnitTest_##name(); \
+ TestRegister g_TestRegister_##name(#name, __FILE__, &UnitTest_##name); \
+ void UnitTest_##name()
+
+DECLARE_EXCEPTION(TestFailureException, RootException);
+
+namespace my
+{
+ inline void OnTestFailed(SrcPoint const & srcPoint, string const & msg)
+ {
+ cerr << "FAILED" << endl << srcPoint.FileName() << ":" << srcPoint.Line() << " " << msg;
+ MYTHROW(TestFailureException, (srcPoint.FileName(), srcPoint.Line(), msg));
+ }
+}
+
+#define TEST(X, msg) if (X) {} else { \
+ ::my::OnTestFailed(SRC(), ::my::impl::MergeMsg("TEST("#X")", ::my::impl::Message msg));}
+#define TEST_EQUAL(X, Y, msg) if ((X) == (Y)) {} else { \
+ ::my::OnTestFailed(SRC(), ::my::impl::MergeMsg("TEST("#X" == "#Y")", \
+ ::my::impl::Message(X, Y), \
+ ::my::impl::Message msg));}
+#define TEST_NOT_EQUAL(X, Y, msg) if ((X) != (Y)) {} else { \
+ ::my::OnTestFailed(SRC(), ::my::impl::MergeMsg("TEST("#X" != "#Y")", \
+ ::my::impl::Message(X, Y), \
+ ::my::impl::Message msg));}
+#define TEST_LESS(X, Y, msg) if ((X) < (Y)) {} else { \
+ ::my::OnTestFailed(SRC(), ::my::impl::MergeMsg("TEST("#X" < "#Y")", \
+ ::my::impl::Message(X, Y), \
+ ::my::impl::Message msg));}
+#define TEST_LESS_OR_EQUAL(X, Y, msg) if ((X) <= (Y)) {} else { \
+ ::my::OnTestFailed(SRC(), ::my::impl::MergeMsg("TEST("#X" <= "#Y")", \
+ ::my::impl::Message(X, Y), \
+ ::my::impl::Message msg));}
+#define TEST_GREATER(X, Y, msg) if ((X) > (Y)) {} else { \
+ ::my::OnTestFailed(SRC(), ::my::impl::MergeMsg("TEST("#X" > "#Y")", \
+ ::my::impl::Message(X, Y), \
+ ::my::impl::Message msg));}
+#define TEST_GREATER_OR_EQUAL(X, Y, msg) if ((X) >= (Y)) {} else { \
+ ::my::OnTestFailed(SRC(), ::my::impl::MergeMsg("TEST("#X" >= "#Y")", \
+ ::my::impl::Message(X, Y), \
+ ::my::impl::Message msg));}
+#define TEST_ALMOST_EQUAL(X, Y, msg) if (::my::AlmostEqual(X, Y)) {} else { \
+ ::my::OnTestFailed(SRC(), ::my::impl::MergeMsg("TEST(my::AlmostEqual("#X", "#Y")", \
+ ::my::impl::Message(X, Y), \
+ ::my::impl::Message msg));}
+#define TEST_NOT_ALMOST_EQUAL(X, Y, msg) if (!::my::AlmostEqual(X, Y)) {} else { \
+ ::my::OnTestFailed(SRC(), ::my::impl::MergeMsg("TEST(!my::AlmostEqual("#X", "#Y")", \
+ ::my::impl::Message(X, Y), \
+ ::my::impl::Message msg));}
diff --git a/testing/testing.includes b/testing/testing.includes
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/testing.includes
diff --git a/testing/testingmain.cpp b/testing/testingmain.cpp
new file mode 100644
index 0000000000..934da91019
--- /dev/null
+++ b/testing/testingmain.cpp
@@ -0,0 +1,98 @@
+#include "../base/SRC_FIRST.hpp"
+#include "testregister.hpp"
+#include "testing.hpp"
+#include "../base/logging.hpp"
+#include "../std/algorithm.hpp"
+#include "../std/iostream.hpp"
+#include "../std/string.hpp"
+#include "../std/vector.hpp"
+
+static bool g_bLastTestOK = true;
+
+int main()
+{
+ my::g_LogLevel = LINFO;
+
+ vector<string> testNames;
+ vector<bool> testResults;
+ int numFailedTests = 0;
+
+ for (TestRegister * pTest = TestRegister::FirstRegister(); pTest; pTest = pTest->m_pNext)
+ {
+ string fileName(pTest->m_FileName);
+ string testName(pTest->m_TestName);
+ // Retrieve fine file name
+ {
+ int iFirstSlash = static_cast<int>(fileName.size()) - 1;
+ while (iFirstSlash >= 0 && fileName[iFirstSlash] != '\\' && fileName[iFirstSlash] != '/')
+ --iFirstSlash;
+ if (iFirstSlash >= 0)
+ fileName.erase(0, iFirstSlash + 1);
+ }
+
+ testNames.push_back(fileName + "::" + testName);
+ testResults.push_back(true);
+ }
+
+ int iTest = 0;
+ for (TestRegister * pTest = TestRegister::FirstRegister(); pTest; ++iTest, pTest = pTest->m_pNext)
+ {
+ cerr << "Running " << testNames[iTest] << endl << flush;
+ if (!g_bLastTestOK)
+ {
+ // Somewhere else global variables have been reset.
+ cerr << "\n\nSOMETHING IS REALLY WRONG IN THE UNIT TEST FRAMEWORK!!!" << endl;
+ return 5;
+ }
+ try
+ {
+ // Run the test.
+ pTest->m_Fn();
+
+ if (g_bLastTestOK)
+ {
+ cerr << "OK" << endl;
+ }
+ else
+ {
+ // You can set Break here if test failed,
+ // but it is already set in OnTestFail - to fail immediately.
+ testResults[iTest] = false;
+ ++numFailedTests;
+ }
+
+ } catch (TestFailureException const & ex)
+ {
+ testResults[iTest] = false;
+ ++numFailedTests;
+ } catch (std::exception const & ex)
+ {
+ cerr << "FAILED" << endl << "<<<Exception thrown [" << ex.what() << "].>>>" << endl;
+ testResults[iTest] = false;
+ ++numFailedTests;
+ } catch (...)
+ {
+ cerr << "FAILED" << endl << "<<<Unknown exception thrown.>>>" << endl;
+ testResults[iTest] = false;
+ ++numFailedTests;
+ }
+ g_bLastTestOK = true;
+ }
+
+ if (numFailedTests == 0)
+ {
+ cerr << endl << "All tests passed." << endl << flush;
+ return 0;
+ }
+ else
+ {
+ cerr << endl << numFailedTests << " tests failed:" << endl;
+ for (size_t i = 0; i < testNames.size(); ++i)
+ {
+ if (!testResults[i])
+ cerr << testNames[i] << endl;
+ }
+ cerr << "Some tests FAILED." << endl << flush;
+ return 1;
+ }
+}
diff --git a/testing/testregister.hpp b/testing/testregister.hpp
new file mode 100644
index 0000000000..803413473a
--- /dev/null
+++ b/testing/testregister.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "../base/base.hpp"
+
+class TestRegister
+{
+public:
+ TestRegister(char const * testName, char const * fileName, void (* fnTest)())
+ : m_TestName(testName), m_FileName(fileName), m_Fn(fnTest), m_pNext(NULL)
+ {
+ if (FirstRegister() == NULL)
+ FirstRegister() = this;
+ else
+ {
+ TestRegister * pLast = FirstRegister();
+ while (pLast->m_pNext)
+ pLast = pLast->m_pNext;
+ pLast->m_pNext = this;
+ }
+ }
+
+ // Test name.
+ char const * m_TestName;
+ // File name.
+ char const * m_FileName;
+ // Function to run test.
+ void (* m_Fn)();
+ // Next test in chain.
+ TestRegister * m_pNext;
+
+ static TestRegister * & FirstRegister()
+ {
+ static TestRegister * s_pRegister = 0;
+ return s_pRegister;
+ }
+};