1 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
3 #pragma once
4
5 #include <iostream>
6 #include <iomanip>
7 #include <exception>
8 #include <sstream>
9 #include <utility>
10 #include <memory>
11 #include <cstddef>
12
nameempty_testcase13 struct empty_testcase{ void run(){} const char* name(){return 0;} };
14
15 template <std::size_t offset>
16 struct testcase : empty_testcase{};
17
18
19 template <std::size_t begin, std::size_t end>
20 struct testrange {
runtestrange21 void run(std::size_t& pass, std::size_t& fail)
22 {
23 using namespace std;
24 { testcase<begin> a_case;
25 if (a_case.name()) {
26 std::size_t p=0, f=0;
27 cout << "TEST: Running " << a_case.name() << endl;
28 try {
29 a_case.run();
30 ++p;
31 } catch (logic_error& e) {
32 cerr << "ERRORS:" << endl;
33 cerr << " " << e.what() << endl;
34 ++f;
35 }
36 pass += p; fail += f;
37 }
38 }
39 const std::size_t rem = (end-begin-1);
40 testrange<begin+1, begin+1+rem/2>().run(pass, fail);
41 testrange<begin+1+rem/2, end>().run(pass, fail);
42 }
43 };
44
45 template <std::size_t begin>
46 struct testrange<begin,begin> {
runtestrange47 void run(std::size_t& pass, std::size_t& fail) {};
48 };
49
50 #define TEST(fun_name) \
51 void fun_name (); \
52 template <> \
53 struct testcase<__LINE__> { \
54 const char* name() { return(#fun_name); } \
55 void run() { fun_name(); } \
56 }; \
57 void fun_name()
58
59 #define Q_(e) #e
60 #define Q(e) Q_(e)
61 #define TASSERT(expr) \
62 { auto e = (expr); if (!e) { throw std::logic_error(__FILE__ "(" Q(__LINE__) "): TASSERT("#expr")"); } }
63
64 struct errmsg
65 {
66 std::shared_ptr<std::stringstream> msg;
errmsgerrmsg67 errmsg() : msg(new std::stringstream)
68 {}
69
70 template <class T>
operator <<errmsg71 errmsg& operator<<(T value)
72 {
73 (*msg) << value;
74 return *this;
75 }
strerrmsg76 std::string str() { return msg->str(); }
77 };
78
79 #define TEST_WHERE __FILE__ "(" Q(__LINE__) "): "
80 #define VERIFY(expr) \
81 { auto e = (expr); if (!e) { throw std::logic_error(TEST_WHERE "VERIFY("#expr")"); } }
82 #define VERIFY_EQ(expected, actual) \
83 { auto e = (expected); auto a = (actual); \
84 if (!(e == a)) { \
85 throw std::logic_error( \
86 (errmsg() << TEST_WHERE << "(" << e << ")!=(" << a << ") in VERIFY_EQ("#expected","#actual")").str() );}}
87
88
89