OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
Mads Ager (google)
2012/01/16 10:20:05
2012
Søren Gjesse
2012/01/16 11:56:44
Done.
| |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #ifndef PLATFORM_ASSERT_H_ | |
6 #define PLATFORM_ASSERT_H_ | |
7 | |
8 // TODO(5411406): include sstream for now, once we have a Utils::toString() | |
9 // implemented for all the primitive types we can replace the usage of | |
10 // sstream by Utils::toString() | |
11 #if defined(TESTING) | |
12 #include <sstream> | |
13 #include <string> | |
14 #endif | |
15 | |
16 #include "platform/globals.h" | |
17 | |
18 #if !defined(DEBUG) && !defined(NDEBUG) | |
19 #error neither DEBUG nor NDEBUG defined | |
20 #elif defined(DEBUG) && defined(NDEBUG) | |
21 #error both DEBUG and NDEBUG defined | |
22 #endif | |
23 | |
24 namespace dart { | |
25 | |
26 class DynamicAssertionHelper { | |
27 public: | |
28 enum Kind { | |
29 ASSERT, | |
30 EXPECT | |
31 }; | |
32 | |
33 DynamicAssertionHelper(const char* file, int line, Kind kind) | |
34 : file_(file), line_(line), kind_(kind) { } | |
35 | |
36 void Fail(const char* format, ...); | |
37 | |
38 #if defined(TESTING) | |
39 template<typename E, typename A> | |
40 void Equals(const E& expected, const A& actual); | |
41 | |
42 template<typename E, typename A> | |
43 void NotEquals(const E& not_expected, const A& actual); | |
44 | |
45 template<typename E, typename A, typename T> | |
46 void FloatEquals(const E& expected, const A& actual, const T& tol); | |
47 | |
48 template<typename E, typename A> | |
49 void StringEquals(const E& expected, const A& actual); | |
50 | |
51 template<typename E, typename A> | |
52 void IsSubstring(const E& needle, const A& haystack); | |
53 | |
54 template<typename E, typename A> | |
55 void LessThan(const E& left, const A& right); | |
56 | |
57 template<typename E, typename A> | |
58 void LessEqual(const E& left, const A& right); | |
59 | |
60 template<typename E, typename A> | |
61 void GreaterThan(const E& left, const A& right); | |
62 | |
63 template<typename E, typename A> | |
64 void GreaterEqual(const E& left, const A& right); | |
65 #endif | |
66 | |
67 private: | |
68 const char* const file_; | |
69 const int line_; | |
70 const Kind kind_; | |
71 | |
72 DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicAssertionHelper); | |
73 }; | |
74 | |
75 | |
76 class Assert: public DynamicAssertionHelper { | |
77 public: | |
78 Assert(const char* file, int line) | |
79 : DynamicAssertionHelper(file, line, ASSERT) { } | |
80 }; | |
81 | |
82 | |
83 class Expect: public DynamicAssertionHelper { | |
84 public: | |
85 Expect(const char* file, int line) | |
86 : DynamicAssertionHelper(file, line, EXPECT) { } | |
87 }; | |
88 | |
89 | |
90 #if defined(TESTING) | |
91 // Only allow the expensive (with respect to code size) assertions | |
92 // in testing code. | |
93 template<typename E, typename A> | |
94 void DynamicAssertionHelper::Equals(const E& expected, const A& actual) { | |
95 if (actual == expected) return; | |
96 std::stringstream ess, ass; | |
97 ess << expected; | |
98 ass << actual; | |
99 std::string es = ess.str(), as = ass.str(); | |
100 Fail("expected: <%s> but was: <%s>", es.c_str(), as.c_str()); | |
101 } | |
102 | |
103 | |
104 template<typename E, typename A> | |
105 void DynamicAssertionHelper::NotEquals(const E& not_expected, | |
106 const A& actual) { | |
107 if (actual != not_expected) return; | |
108 std::stringstream ness; | |
109 ness << not_expected; | |
110 std::string nes = ness.str(); | |
111 Fail("did not expect: <%s>", nes.c_str()); | |
112 } | |
113 | |
114 | |
115 template<typename E, typename A, typename T> | |
116 void DynamicAssertionHelper::FloatEquals(const E& expected, | |
117 const A& actual, | |
118 const T& tol) { | |
119 if (((expected - tol) <= actual) && (actual <= (expected + tol))) { | |
120 return; | |
121 } | |
122 std::stringstream ess, ass, tolss; | |
123 ess << expected; | |
124 ass << actual; | |
125 tolss << tol; | |
126 std::string es = ess.str(), as = ass.str(), tols = tolss.str(); | |
127 Fail("expected: <%s> but was: <%s> (tolerance: <%s>)", | |
128 es.c_str(), | |
129 as.c_str(), | |
130 tols.c_str()); | |
131 } | |
132 | |
133 | |
134 template<typename E, typename A> | |
135 void DynamicAssertionHelper::StringEquals(const E& expected, const A& actual) { | |
136 std::stringstream ess, ass; | |
137 ess << expected; | |
138 ass << actual; | |
139 std::string es = ess.str(), as = ass.str(); | |
140 if (as == es) return; | |
141 Fail("expected: <\"%s\"> but was: <\"%s\">", es.c_str(), as.c_str()); | |
142 } | |
143 | |
144 | |
145 template<typename E, typename A> | |
146 void DynamicAssertionHelper::IsSubstring(const E& needle, const A& haystack) { | |
147 std::stringstream ess, ass; | |
148 ess << needle; | |
149 ass << haystack; | |
150 std::string es = ess.str(), as = ass.str(); | |
151 if (as.find(es) != std::string::npos) return; | |
152 Fail("expected <\"%s\"> to be a substring of <\"%s\">", | |
153 es.c_str(), as.c_str()); | |
154 } | |
155 | |
156 | |
157 template<typename E, typename A> | |
158 void DynamicAssertionHelper::LessThan(const E& left, const A& right) { | |
159 if (left < right) return; | |
160 std::stringstream ess, ass; | |
161 ess << left; | |
162 ass << right; | |
163 std::string es = ess.str(), as = ass.str(); | |
164 Fail("expected: %s < %s", es.c_str(), as.c_str()); | |
165 } | |
166 | |
167 | |
168 template<typename E, typename A> | |
169 void DynamicAssertionHelper::LessEqual(const E& left, const A& right) { | |
170 if (left <= right) return; | |
171 std::stringstream ess, ass; | |
172 ess << left; | |
173 ass << right; | |
174 std::string es = ess.str(), as = ass.str(); | |
175 Fail("expected: %s <= %s", es.c_str(), as.c_str()); | |
176 } | |
177 | |
178 | |
179 template<typename E, typename A> | |
180 void DynamicAssertionHelper::GreaterThan(const E& left, const A& right) { | |
181 if (left > right) return; | |
182 std::stringstream ess, ass; | |
183 ess << left; | |
184 ass << right; | |
185 std::string es = ess.str(), as = ass.str(); | |
186 Fail("expected: %s > %s", es.c_str(), as.c_str()); | |
187 } | |
188 | |
189 | |
190 template<typename E, typename A> | |
191 void DynamicAssertionHelper::GreaterEqual(const E& left, const A& right) { | |
192 if (left >= right) return; | |
193 std::stringstream ess, ass; | |
194 ess << left; | |
195 ass << right; | |
196 std::string es = ess.str(), as = ass.str(); | |
197 Fail("expected: %s >= %s", es.c_str(), as.c_str()); | |
198 } | |
199 #endif | |
200 | |
201 } // namespace dart | |
202 | |
203 | |
204 #define FATAL(error) \ | |
205 dart::Assert(__FILE__, __LINE__).Fail("%s", error) | |
206 | |
207 #define FATAL1(format, p1) \ | |
208 dart::Assert(__FILE__, __LINE__).Fail(format, (p1)) | |
209 | |
210 #define FATAL2(format, p1, p2) \ | |
211 dart::Assert(__FILE__, __LINE__).Fail(format, (p1), (p2)) | |
212 | |
213 #define UNIMPLEMENTED() \ | |
214 FATAL("unimplemented code") | |
215 | |
216 #define UNREACHABLE() \ | |
217 FATAL("unreachable code") | |
218 | |
219 | |
220 #if defined(DEBUG) | |
221 // DEBUG binaries use assertions in the code. | |
222 // Note: We wrap the if statement in a do-while so that we get a compile | |
223 // error if there is no semicolon after ASSERT(condition). This | |
224 // ensures that we get the same behavior on DEBUG and RELEASE builds. | |
225 | |
226 #define ASSERT(cond) \ | |
227 do { \ | |
228 if (!(cond)) dart::Assert(__FILE__, __LINE__).Fail("expected: %s", #cond); \ | |
229 } while (false) | |
230 | |
231 // DEBUG_ASSERT allows identifiers in condition to be undeclared in release | |
232 // mode. | |
233 #define DEBUG_ASSERT(cond) \ | |
234 if (!(cond)) dart::Assert(__FILE__, __LINE__).Fail("expected: %s", #cond); | |
235 | |
236 #else // if defined(DEBUG) | |
237 | |
238 // In order to avoid variable unused warnings for code that only uses | |
239 // a variable in an ASSERT or EXPECT, we make sure to use the macro | |
240 // argument. | |
241 #define ASSERT(condition) do {} while (false && (condition)) | |
242 | |
243 #define DEBUG_ASSERT(cond) | |
244 | |
245 #endif // if defined(DEBUG) | |
246 | |
247 | |
248 #if defined(TESTING) | |
249 #define EXPECT(condition) \ | |
250 if (!(condition)) { \ | |
251 dart::Expect(__FILE__, __LINE__).Fail("expected: %s", #condition); \ | |
252 } | |
253 | |
254 #define EXPECT_EQ(expected, actual) \ | |
255 dart::Expect(__FILE__, __LINE__).Equals((expected), (actual)) | |
256 | |
257 #define EXPECT_NE(not_expected, actual) \ | |
258 dart::Expect(__FILE__, __LINE__).NotEquals((not_expected), (actual)) | |
259 | |
260 #define EXPECT_FLOAT_EQ(expected, actual, tol) \ | |
261 dart::Expect(__FILE__, __LINE__).FloatEquals((expected), (actual), (tol)) | |
262 | |
263 #define EXPECT_STREQ(expected, actual) \ | |
264 dart::Expect(__FILE__, __LINE__).StringEquals((expected), (actual)) | |
265 | |
266 #define EXPECT_SUBSTRING(needle, haystack) \ | |
267 dart::Expect(__FILE__, __LINE__).IsSubstring((needle), (haystack)) | |
268 | |
269 #define EXPECT_LT(left, right) \ | |
270 dart::Expect(__FILE__, __LINE__).LessThan((left), (right)) | |
271 | |
272 #define EXPECT_LE(left, right) \ | |
273 dart::Expect(__FILE__, __LINE__).LessEqual((left), (right)) | |
274 | |
275 #define EXPECT_GT(left, right) \ | |
276 dart::Expect(__FILE__, __LINE__).GreaterThan((left), (right)) | |
277 | |
278 #define EXPECT_GE(left, right) \ | |
279 dart::Expect(__FILE__, __LINE__).GreaterEqual((left), (right)) | |
280 #endif | |
281 | |
282 // TODO(iposva): provide a better way to get extra info on an EXPECT | |
283 // fail - you suggested EXPECT_EQ(expected, actual, msg_format, | |
284 // parameters_for_msg...), I quite like the google3 method | |
285 // EXPECT_EQ(a, b) << "more stuff here...". (benl). | |
286 | |
287 #define WARN(error) \ | |
288 dart::Expect(__FILE__, __LINE__).Fail("%s", error) | |
289 | |
290 #define WARN1(format, p1) \ | |
291 dart::Expect(__FILE__, __LINE__).Fail(format, (p1)) | |
292 | |
293 #define WARN2(format, p1, p2) \ | |
294 dart::Expect(__FILE__, __LINE__).Fail(format, (p1), (p2)) | |
295 | |
296 #endif // PLATFORM_ASSERT_H_ | |
OLD | NEW |