PageRenderTime 114ms CodeModel.GetById 20ms app.highlight 63ms RepoModel.GetById 27ms app.codeStats 1ms

/mordor/test/test.cpp

http://github.com/mozy/mordor
C++ | 344 lines | 306 code | 37 blank | 1 comment | 51 complexity | 261e20046dbfe93662abec34628b1d6f MD5 | raw file
  1// Copyright (c) 2009 - Mozy, Inc.
  2
  3#include "mordor/predef.h"
  4
  5#include "test.h"
  6
  7#include <iostream>
  8
  9#include <boost/regex.hpp>
 10
 11#include "mordor/config.h"
 12#include "mordor/sleep.h"
 13#include "mordor/timer.h"
 14
 15#ifdef WINDOWS
 16#include <windows.h>
 17#elif defined (LINUX)
 18#include <fcntl.h>
 19#include <stdlib.h>
 20#include <string.h>
 21#elif defined (OSX)
 22#include <sys/sysctl.h>
 23#endif
 24
 25namespace Mordor {
 26namespace Test {
 27
 28static ConfigVar<bool>::ptr g_protect = Config::lookup(
 29    "test.protect", false,
 30    "Protect test while running under a debugger");
 31static ConfigVar<bool>::ptr g_wait = Config::lookup(
 32    "test.waitfordebugger", false,
 33    "Wait for a debugger to attach before running tests");
 34
 35TestSuites &allTests()
 36{
 37    static TestSuites s_allTests;
 38    return s_allTests;
 39}
 40
 41void
 42registerTest(const std::string &suite, const std::string &testName,
 43             TestDg test)
 44{
 45    allTests()[suite].second[testName] = test;
 46}
 47
 48void
 49registerSuiteInvariant(const std::string &suite, TestDg invariant)
 50{
 51    MORDOR_ASSERT(allTests()[suite].first == NULL);
 52    allTests()[suite].first = invariant;
 53}
 54
 55TimeConstraint::TimeConstraint(unsigned long long us)
 56    : m_end(TimerManager::now() + us)
 57{}
 58
 59TimeConstraint::~TimeConstraint()
 60{
 61    MORDOR_TEST_ASSERT_LESS_THAN_OR_EQUAL(TimerManager::now(), m_end);
 62}
 63
 64TakesAtLeast::TakesAtLeast(unsigned long long us)
 65: m_until(TimerManager::now() + us)
 66{}
 67
 68TakesAtLeast::~TakesAtLeast()
 69{
 70    MORDOR_TEST_ASSERT_GREATER_THAN(TimerManager::now(), m_until);
 71}
 72
 73void
 74assertion(const char *file, int line, const char *function,
 75                const std::string &expr)
 76{
 77    throw boost::enable_current_exception(Assertion(expr))
 78        << boost::throw_file(file) << boost::throw_line(line)
 79        << boost::throw_function(function)
 80        << errinfo_backtrace(backtrace());
 81}
 82
 83static bool
 84runTest(TestListener *listener, const std::string &suite,
 85             const std::string &testName, TestDg test)
 86{
 87    if (listener)
 88        listener->testStarted(suite, testName);
 89
 90    bool protect = !isDebuggerAttached();
 91    protect = protect || g_protect->val();
 92    if (protect) {
 93        try {
 94            test();
 95            if (listener)
 96                listener->testComplete(suite, testName);
 97        } catch (const TestSkippedException &) {
 98            if (listener)
 99                listener->testSkipped(suite, testName);
100        } catch (const Assertion &assertion) {
101            if (listener)
102                listener->testAsserted(suite, testName, assertion);
103            return false;
104        } catch (...) {
105            if (listener)
106                listener->testException(suite, testName);
107            return false;
108        }
109    } else {
110        try {
111            test();
112            if (listener)
113                listener->testComplete(suite, testName);
114        } catch (const TestSkippedException &) {
115            if (listener)
116                listener->testSkipped(suite, testName);
117        }
118    }
119    return true;
120}
121
122static bool
123runTests(const TestSuites *suites, TestListener *listener)
124{
125    Assertion::throwOnAssertion = true;
126    if (g_wait->val()) {
127        while (!isDebuggerAttached())
128            sleep(10000ull);
129        debugBreak();
130    }
131    bool result = true;
132    if (!suites) suites = &allTests();
133    if (suites) {
134        for (TestSuites::const_iterator it(suites->begin());
135            it != suites->end();
136            ++it) {
137            for (TestSuite::second_type::const_iterator
138                    it2(it->second.second.begin());
139                it2 != it->second.second.end();
140                ++it2) {
141                if (it->second.first) {
142                    result = result && runTest(listener, it->first,
143                        "<invariant>", it->second.first);
144                }
145                result = runTest(listener, it->first, it2->first,
146                    it2->second) && result;
147            }
148            if (it->second.first) {
149                result = runTest(listener, it->first,
150                    "<invariant>", it->second.first) && result;
151            }
152        }
153    }
154    if (listener)
155        listener->testsComplete();
156    return result;
157}
158
159TestSuites
160testsForArguments(int argc, char **argv)
161{
162    TestSuites tests;
163    const TestSuites &all = allTests();
164    for (int i = 0; i < argc; ++i) {
165        boost::regex regex("^" + std::string(argv[i]) + "$");
166        for (TestSuites::const_iterator j(all.begin());
167            j != all.end();
168            ++j) {
169            if (boost::regex_match(j->first, regex)) {
170                tests[j->first] = j->second;
171            } else {
172                for (std::map<std::string, TestDg>::const_iterator k(j->second.second.begin());
173                    k != j->second.second.end();
174                    ++k) {
175                    if (boost::regex_match(j->first + "::" + k->first, regex)) {
176                        tests[j->first].first = j->second.first;
177                        tests[j->first].second[k->first] = k->second;
178                    }
179                }
180            }
181        }
182    }
183    return tests;
184}
185
186bool
187runTests()
188{
189    return runTests(&allTests(), NULL);
190}
191
192bool
193runTests(const TestSuites &suites)
194{
195    return runTests(&suites, NULL);
196}
197
198bool
199runTests(TestListener &listener)
200{
201    return runTests(&allTests(), &listener);
202}
203
204bool
205runTests(const TestSuites &suites, TestListener &listener)
206{
207    return runTests(&suites, &listener);
208}
209
210template <>
211void assertEqual<const char *, const char *>(const char *file,
212    int line, const char *function, const char *lhs, const char *rhs,
213    const char *lhsExpr, const char *rhsExpr)
214{
215    if (!(strcmp(lhs, rhs) == 0)) {
216        assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
217            "==");
218    }
219}
220
221template <>
222void assertNotEqual<const char *, const char *>(const char *file,
223    int line, const char *function, const char *lhs, const char *rhs,
224    const char *lhsExpr, const char *rhsExpr)
225{
226    if (!(strcmp(lhs, rhs) != 0)) {
227        assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
228            "!=");
229    }
230}
231
232template <>
233void assertLessThan<const char *, const char *>(const char *file,
234    int line, const char *function, const char *lhs, const char *rhs,
235    const char *lhsExpr, const char *rhsExpr)
236{
237    if (!(strcmp(lhs, rhs) < 0)) {
238        assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
239            "<");
240    }
241}
242
243template <>
244void assertLessThanOrEqual<const char *, const char *>(const char *file,
245    int line, const char *function, const char *lhs, const char *rhs,
246    const char *lhsExpr, const char *rhsExpr)
247{
248    if (!(strcmp(lhs, rhs) <= 0)) {
249        assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
250            "<=");
251    }
252}
253
254template <>
255void assertGreaterThan<const char *, const char *>(const char *file,
256    int line, const char *function, const char *lhs, const char *rhs,
257    const char *lhsExpr, const char *rhsExpr)
258{
259    if (!(strcmp(lhs, rhs) > 0)) {
260        assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
261            ">");
262    }
263}
264
265template <>
266void assertGreaterThanOrEqual<const char *, const char *>(const char *file,
267    int line, const char *function, const char *lhs, const char *rhs,
268    const char *lhsExpr, const char *rhsExpr)
269{
270    if (!(strcmp(lhs, rhs) == 0)) {
271        assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
272            ">=");
273    }
274}
275
276#ifdef WINDOWS
277template <>
278void assertEqual<const wchar_t *, const wchar_t *>(const char *file,
279    int line, const char *function, const wchar_t *lhs, const wchar_t *rhs,
280    const char *lhsExpr, const char *rhsExpr)
281{
282    if (!(wcscmp(lhs, rhs) == 0)) {
283        assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
284            "==");
285    }
286}
287
288template <>
289void assertNotEqual<const wchar_t *, const wchar_t *>(const char *file,
290    int line, const char *function, const wchar_t *lhs, const wchar_t *rhs,
291    const char *lhsExpr, const char *rhsExpr)
292{
293    if (!(wcscmp(lhs, rhs) != 0)) {
294        assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
295            "!=");
296    }
297}
298
299template <>
300void assertLessThan<const wchar_t *, const wchar_t *>(const char *file,
301    int line, const char *function, const wchar_t *lhs, const wchar_t *rhs,
302    const char *lhsExpr, const char *rhsExpr)
303{
304    if (!(wcscmp(lhs, rhs) < 0)) {
305        assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
306            "<");
307    }
308}
309
310template <>
311void assertLessThanOrEqual<const wchar_t *, const wchar_t *>(const char *file,
312    int line, const char *function, const wchar_t *lhs, const wchar_t *rhs,
313    const char *lhsExpr, const char *rhsExpr)
314{
315    if (!(wcscmp(lhs, rhs) <= 0)) {
316        assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
317            "<=");
318    }
319}
320
321template <>
322void assertGreaterThan<const wchar_t *, const wchar_t *>(const char *file,
323    int line, const char *function, const wchar_t *lhs, const wchar_t *rhs,
324    const char *lhsExpr, const char *rhsExpr)
325{
326    if (!(wcscmp(lhs, rhs) > 0)) {
327        assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
328            ">");
329    }
330}
331
332template <>
333void assertGreaterThanOrEqual<const wchar_t *, const wchar_t *>(const char *file,
334    int line, const char *function, const wchar_t *lhs, const wchar_t *rhs,
335    const char *lhsExpr, const char *rhsExpr)
336{
337    if (!(wcscmp(lhs, rhs) == 0)) {
338        assertComparison(file, line, function, lhs, rhs, lhsExpr, rhsExpr,
339            ">=");
340    }
341}
342#endif
343
344}}