1 // test.h
2 // this file is part of Context Free
3 // ---------------------
4 // Copyright (C) 2003 Mark Lentczner - markl@glyphic.com
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 //
20 // Mark Lentczner can be contacted at markl@glyphic.com or at
21 // Mark Lentczner, 1209 Villa St., Mountain View, CA 94041-1123, USA
22 //
23 //
24 
25 // A small test framework
26 
27 #ifndef INCLUDED_TEST_H
28 #define INCLUDED_TEST_H
29 
30 #include <iosfwd>
31 #include <string>
32 
33 namespace Test {
34 	class testlocation {
35 	public:
36 		testlocation(const char* f, long l, int = 0);
37 		testlocation(const char* f, long l, const testlocation& t);
38 		testlocation(const testlocation& o);
39 
40 		operator std::string() const;
41 		void put(std::ostream&) const;
42 
43 	private:
44 		testlocation& operator=(const testlocation& o);
45 
46 		const char*         file;
47 		int                 line;
48 		const testlocation* from;
49 	};
50 
51 
52 	class test {
53 	public:
54 		test(const char* group, const char* name,
55 			const char* built = __DATE__ " " __TIME__);
56 		virtual void run() = 0;
57 		std::string name;
58 	protected:
59 		static const int _called_from = 0;
60 	};
61 
62 
63 
64 	void pass(const testlocation& loc);
65 
66 	void fail(const testlocation& loc,
67 				const std::string& message);
68 
69 	void failsame(const testlocation& loc,
70 				const char* expectExpr, const char* actualExpr);
71 
72 	void skip(const testlocation& loc);
73 
74 
75 	void failsame(const testlocation& loc,
76 				 const char* expectExpr, const std::string& expected,
77 				 const char* actualExpr, const std::string& actual);
78 
79 	void fail_contains(const testlocation& loc,
80 				const std::string& needle,
81 				const std::string& haystack);
82 
83 	template <typename T>
tostring(T)84 	std::string tostring(T)						{ return ""; }
85 	std::string tostring(const std::string& s);
86 	std::string tostring(int i);
87 	std::string tostring(bool b);
88 
89 	template <typename TE, typename TA>
check_same(const testlocation & loc,const char * expectExpr,TE expected,const char * actualExpr,TA actual)90 	void check_same(const testlocation& loc,
91 				 const char* expectExpr, TE expected,
92 				 const char* actualExpr, TA actual)
93 	{
94 		if (actual != (TA)expected)
95 			failsame(loc,
96 				expectExpr, tostring((TA)expected),
97 				actualExpr, tostring(actual));
98 		else
99 			pass(loc);
100 	}
101 
102 	void check_contains(const testlocation& loc,
103 		const char* needleExpr, const std::string& needle,
104 		const char* haystackExpr, const std::string& haystack);
105 
106 	void check(const testlocation& loc,
107 					const char* expr, bool actual);
108 
109 
110 	bool runAll(
111 		bool reportPerGroup = false,
112 		bool stopOnFailingGroup = false);
113 		// returns true if passes all tests
114 }
115 
116 
117 #define TEST(group, name) \
118     struct Test_##group##_##name : public ::Test::test { \
119         Test_##group##_##name() : ::Test::test(#group, #name) { } \
120         void run(); \
121     } test_##group##_##name; \
122     void Test_##group##_##name::run()
123 
124 
125 #define HERE    ::Test::testlocation(__FILE__, __LINE__, _called_from)
126 #define WHERE   const ::Test::testlocation& _called_from
127 #define THERE   _called_from
128 
129 
130 #define PASS() \
131     ::Test::pass(HERE)
132 
133 #define FAIL(message) \
134     ::Test::fail(HERE, message)
135 
136 #define SKIP() \
137     ::Test::skip(HERE)
138 
139 #define CHECK(cond) \
140     ::Test::check(HERE, #cond, cond)
141 
142 #define CHECK_MSG(cond, message) \
143     ::Test::check(HERE, message, cond)
144 
145 #define CHECK_SAME(v, e) \
146     ::Test::check_same(HERE, #v, v, #e, e)
147 
148 #define CHECK_CONTAINS(needle, haystack) \
149     ::Test::check_contains(HERE, #needle, needle, #haystack, haystack)
150 
151 #define CHECK_VALID(ptr) \
152     CHECK((ptr) != 0)
153 
154 
155 #endif // INCLUDED_TEST_H
156