Turi Create  4.0
assertions.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 // Copyright (c) 2005, Google Inc.
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are
11 // met:
12 //
13 // * Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 // * Redistributions in binary form must reproduce the above
16 // copyright notice, this list of conditions and the following disclaimer
17 // in the documentation and/or other materials provided with the
18 // distribution.
19 // * Neither the name of Google Inc. nor the names of its
20 // contributors may be used to endorse or promote products derived from
21 // this software without specific prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 
35 // ---
36 // This file contains #include information about logging-related stuff.
37 // Pretty much everybody needs to #include this file so that they can
38 // log various happenings.
39 //
40 #ifndef _ASSERTIONS_H_
41 #define _ASSERTIONS_H_
42 
43 #ifndef TURI_LOGGER_THROW_ON_FAILURE
44 #define TURI_LOGGER_THROW_ON_FAILURE
45 #endif
46 
47 #include <stdarg.h>
48 #include <stdlib.h>
49 #include <stdio.h>
50 #ifdef HAVE_UNISTD_H
51 #include <unistd.h> // for write()
52 #endif
53 #include <string.h> // for strlen(), strcmp()
54 #include <assert.h>
55 #include <errno.h> // for errno
56 #include <sstream>
57 #include <cassert>
58 #include <cmath>
59 #include <sstream>
60 #include <core/logging/logger.hpp>
61 #include <core/logging/fail_method.hpp>
62 #include <core/logging/backtrace.hpp>
63 
64 #include <boost/typeof/typeof.hpp>
65 
66 #include <core/util/code_optimization.hpp>
67 #include <core/util/sys_util.hpp>
68 
69 extern void __print_back_trace();
70 
71 /*
72  * I am not too happy about this. But this seems to be the only practical way
73  * to disable the null conversion error in the check_op below, thus allow
74  * ASSERT_NE(someptr, NULL);
75  */
76 #ifdef __clang__
77 #pragma clang diagnostic push
78 #pragma clang diagnostic ignored "-Wconversion-null"
79 #endif
80 #ifdef __GNUC__
81 #pragma GCC diagnostic push
82 #pragma GCC diagnostic ignored "-Wconversion-null"
83 #endif
84 // On some systems (like freebsd), we can't call write() at all in a
85 // global constructor, perhaps because errno hasn't been set up.
86 // Calling the write syscall is safer (it doesn't set errno), so we
87 // prefer that. Note we don't care about errno for logging: we just
88 // do logging on a best-effort basis.
89 #define WRITE_TO_STDERR(buf, len) (logbuf(LOG_FATAL, buf, len))
90 
91 /**
92  * \ingroup turilogger
93  * \addtogroup assertions Logging Assertions
94  * \brief Assertions
95  * \{
96  */
97 /**
98  * \def __CHECK(condition)
99  * CHECK dies with a fatal error if condition is not true. It is *not*
100  * controlled by NDEBUG, so the check will be executed regardless of
101  * compilation mode.
102  */
103 /**
104  * \def ASSERT_TRUE(val)
105  * Expects val to evaluate to true, dies with a fatal error otherwise. Synonyms are
106  * EXPECT_TRUE
107  */
108 /**
109  * \def ASSERT_FALSE(val)
110  * Expects val to evaluate to false, dies with a fatal error otherwise. Synonyms are
111  * EXPECT_FALSE
112  */
113 /**
114  * \def __CHECK_EQ(val1, val2)
115  * Expects val1 == val2, dies with a fatal error otherwise. Synonyms are
116  * ASSERT_EQ and EXPECT_EQ.
117  */
118 /**
119  * \def __CHECK_NE(val1, val2)
120  * Expects val1 != val2, dies with a fatal error otherwise. Synonyms are
121  * ASSERT_NE and EXPECT_NE
122  */
123 /**
124  * \def __CHECK_LE(val1, val2)
125  * Expects val1 <= val2, dies with a fatal error otherwise. Synonyms are
126  * ASSERT_LE and EXPECT_LE
127  */
128 /**
129  * \def __CHECK_LT(val1, val2)
130  * Expects val1 < val2, dies with a fatal error otherwise. Synonyms are
131  * ASSERT_LT and EXPECT_LT
132  */
133 /**
134  * \def __CHECK_GE(val1, val2)
135  * Expects val1 >= val2, dies with a fatal error otherwise. Synonyms are
136  * ASSERT_GE and EXPECT_GE
137  */
138 /**
139  * \def __CHECK_GT(val1, val2)
140  * Expects val1 > val2, dies with a fatal error otherwise. Synonyms are
141  * ASSERT_GT and EXPECT_GT
142  */
143 /**
144  * \def __CHECK_DELTA(val1, val2, delta)
145  * Expects |val1 - val2| <= delta difference,
146  * dies with a fatal error otherwise. Mainly meant for floating point values.
147  * ASSERT_DELTA and EXPECT_DELTA
148  */
149 /**
150  * \def DASSERT_TRUE(val)
151  * Like \ref ASSERT_TRUE but is compiled away by NDEBUG.
152  */
153 /**
154  * \def DASSERT_FALSE(val)
155  * Like \ref ASSERT_FALSE but is compiled away by NDEBUG.
156  */
157 /**
158  * \def __DCHECK_EQ(val1, val2)
159  * Like \ref __CHECK_EQ but is compiled away by NDEBUG. Synonyms are
160  * DASSERT_EQ.
161  */
162 /**
163  * \def __DCHECK_NE(val1, val2)
164  * Like \ref __CHECK_NE but is compiled away by NDEBUG. Synonyms are
165  * DASSERT_NE.
166  */
167 /**
168  * \def __DCHECK_LE(val1, val2)
169  * Like \ref __CHECK_LE but is compiled away by NDEBUG. Synonyms are
170  * DASSERT_LE.
171  */
172 /**
173  * \def __DCHECK_LT(val1, val2)
174  * Like \ref __CHECK_LT but is compiled away by NDEBUG. Synonyms are
175  * DASSERT_LT.
176  */
177 /**
178  * \def __DCHECK_GE(val1, val2)
179  * Like \ref __CHECK_GE but is compiled away by NDEBUG. Synonyms are
180  * DASSERT_GE.
181  */
182 /**
183  * \def __DCHECK_GT(val1, val2)
184  * Like \ref __CHECK_GT but is compiled away by NDEBUG. Synonyms are
185  * DASSERT_GT.
186  */
187 /**
188  * \def __DCHECK_DELTA(val1, val2, delta)
189  * Like \ref __CHECK_DELTA but is compiled away by NDEBUG. Synonyms are
190  * DASSERT_DELTA.
191  */
192 /**
193  * \}
194  */
195 // CHECK dies with a fatal error if condition is not true. It is *not*
196 // controlled by NDEBUG, so the check will be executed regardless of
197 // compilation mode. Therefore, it is safe to do things like:
198 // __CHECK(fp->Write(x) == 4)
199 #define __CHECK(condition) \
200  do { \
201  if (UNLIKELY(!(condition))) { \
202  auto throw_error = [&]() GL_GCC_ONLY(GL_COLD_NOINLINE_ERROR) { \
203  std::ostringstream ss; \
204  ss << "Check failed (" << __FILE__ << ":" << __LINE__ \
205  << "): " << #condition << std::endl; \
206  logstream(LOG_ERROR) << ss.str(); \
207  __print_back_trace(); \
208  LOGGED_TURI_LOGGER_FAIL_METHOD(ss.str()); \
209  }; \
210  throw_error(); \
211  TURI_BUILTIN_UNREACHABLE(); \
212  } \
213  } while (0)
214 
215 // This prints errno as well. errno is the posix defined last error
216 // number. See errno.h
217 #define __PCHECK(condition) \
218  do { \
219  if (UNLIKELY(!(condition))) { \
220  auto throw_error = [&]() GL_GCC_ONLY(GL_COLD_NOINLINE_ERROR) { \
221  const int _PCHECK_err_no_ = errno; \
222  std::ostringstream ss; \
223  ss << "Assertion failed (" << __FILE__ << ":" << __LINE__ \
224  << "): " << #condition << ": " << strerror(err_no) << std::endl; \
225  logstream(LOG_ERROR) << ss.str(); \
226  __print_back_trace(); \
227  LOGGED_TURI_LOGGER_FAIL_METHOD(ss.str()); \
228  }; \
229  throw_error(); \
230  TURI_BUILTIN_UNREACHABLE(); \
231  } \
232  } while (0)
233 
234 // Helper macro for binary operators; prints the two values on error
235 // Don't use this macro directly in your code, use __CHECK_EQ et al below
236 
237 // WARNING: These don't compile correctly if one of the arguments is a pointer
238 // and the other is NULL. To work around this, simply static_cast NULL to the
239 // type of the desired pointer.
240 #define __CHECK_OP(op, val1, val2) \
241  do { \
242  const auto _CHECK_OP_v1_ = val1; \
243  const auto _CHECK_OP_v2_ = val2; \
244  if (__builtin_expect(!((_CHECK_OP_v1_)op(decltype(val1))(_CHECK_OP_v2_)), \
245  0)) { \
246  auto throw_error = [&]() GL_GCC_ONLY(GL_COLD_NOINLINE_ERROR) { \
247  std::ostringstream ss; \
248  ss << "Assertion failed: (" << __FILE__ << ":" << __LINE__ \
249  << "): " << #val1 << #op << #val2 << " [" << _CHECK_OP_v1_ << ' ' \
250  << #op << ' ' << _CHECK_OP_v2_ << "]" << std::endl; \
251  logstream(LOG_ERROR) << ss.str(); \
252  __print_back_trace(); \
253  LOGGED_TURI_LOGGER_FAIL_METHOD(ss.str()); \
254  }; \
255  throw_error(); \
256  TURI_BUILTIN_UNREACHABLE(); \
257  } \
258  } while (0)
259 
260 #define __CHECK_DELTA(val1, val2, delta) \
261  do { \
262  const double _CHECK_OP_v1_ = val1; \
263  const double _CHECK_OP_v2_ = val2; \
264  const double _CHECK_OP_delta_ = delta; \
265  if (__builtin_expect( \
266  !(std::abs((_CHECK_OP_v1_) - (_CHECK_OP_v2_)) <= _CHECK_OP_delta_),\
267  0)) { \
268  auto throw_error = [&]() GL_GCC_ONLY(GL_COLD_NOINLINE_ERROR) { \
269  std::ostringstream ss; \
270  ss << "Assertion failed: (" << __FILE__ << ":" << __LINE__ << "): " \
271  << "abs(" << #val1 << " - " << #val2 << ") <= " << #delta << ". [" \
272  << "abs(" << _CHECK_OP_v2_ << " - " << _CHECK_OP_v1_ << ") > " \
273  << _CHECK_OP_delta_ << "]" << std::endl; \
274  logstream(LOG_ERROR) << ss.str(); \
275  __print_back_trace(); \
276  LOGGED_TURI_LOGGER_FAIL_METHOD(ss.str()); \
277  }; \
278  throw_error(); \
279  TURI_BUILTIN_UNREACHABLE(); \
280  } \
281  } while (0)
282 
283 #define __CHECK_EQ(val1, val2) __CHECK_OP(==, val1, val2)
284 #define __CHECK_NE(val1, val2) __CHECK_OP(!=, val1, val2)
285 #define __CHECK_LE(val1, val2) __CHECK_OP(<=, val1, val2)
286 #define __CHECK_LT(val1, val2) __CHECK_OP(< , val1, val2)
287 #define __CHECK_GE(val1, val2) __CHECK_OP(>=, val1, val2)
288 #define __CHECK_GT(val1, val2) __CHECK_OP(> , val1, val2)
289 
290 // Synonyms for __CHECK_* that are used in some unittests.
291 #define EXPECT_EQ(val1, val2) __CHECK_EQ(val1, val2)
292 #define EXPECT_DELTA(val1, val2, delta) __CHECK_DELTA(val1, val2, delta)
293 #define EXPECT_NE(val1, val2) __CHECK_NE(val1, val2)
294 #define EXPECT_LE(val1, val2) __CHECK_LE(val1, val2)
295 #define EXPECT_LT(val1, val2) __CHECK_LT(val1, val2)
296 #define EXPECT_GE(val1, val2) __CHECK_GE(val1, val2)
297 #define EXPECT_GT(val1, val2) __CHECK_GT(val1, val2)
298 #define ASSERT_EQ(val1, val2) EXPECT_EQ(val1, val2)
299 #define ASSERT_DELTA(val1, val2, delta) __CHECK_DELTA(val1, val2, delta)
300 #define ASSERT_NE(val1, val2) EXPECT_NE(val1, val2)
301 #define ASSERT_LE(val1, val2) EXPECT_LE(val1, val2)
302 #define ASSERT_LT(val1, val2) EXPECT_LT(val1, val2)
303 #define ASSERT_GE(val1, val2) EXPECT_GE(val1, val2)
304 #define ASSERT_GT(val1, val2) EXPECT_GT(val1, val2)
305 // As are these variants.
306 #define EXPECT_TRUE(cond) __CHECK(cond)
307 #define EXPECT_FALSE(cond) __CHECK(!(cond))
308 #define EXPECT_STREQ(a, b) __CHECK(strcmp(a, b) == 0)
309 #define ASSERT_TRUE(cond) EXPECT_TRUE(cond)
310 #define ASSERT_FALSE(cond) EXPECT_FALSE(cond)
311 #define ASSERT_STREQ(a, b) EXPECT_STREQ(a, b)
312 
313 #define ASSERT_UNREACHABLE() { EXPECT_TRUE(false); assert(false); TURI_BUILTIN_UNREACHABLE(); }
314 
315 #define ASSERT_MSG(condition, fmt, ...) \
316  do { \
317  if (__builtin_expect(!(condition), 0)) { \
318  auto throw_error = [&]() GL_GCC_ONLY(GL_COLD_NOINLINE_ERROR) { \
319  logstream(LOG_ERROR) << "Check failed: " << #condition << ":\n"; \
320  std::ostringstream ss; \
321  ss << "Assertion Failure: " << #condition << ": " << fmt; \
322  logger(LOG_ERROR, fmt, ##__VA_ARGS__, "\n"); \
323  __print_back_trace(); \
324  TURI_LOGGER_FAIL_METHOD(ss.str().c_str()); \
325  ASSERT_UNREACHABLE(); \
326  }; \
327  throw_error(); \
328  TURI_BUILTIN_UNREACHABLE(); \
329  } \
330  } while (0)
331 
332 // Used for (libc) functions that return -1 and set errno
333 #define __CHECK_ERR(invocation) __PCHECK((invocation) != -1)
334 
335 // A few more checks that only happen in debug mode
336 #ifdef NDEBUG
337 #define __DCHECK_EQ(val1, val2)
338 #define __DCHECK_DELTA(val1, val2, delta)
339 #define __DCHECK_NE(val1, val2)
340 #define __DCHECK_LE(val1, val2)
341 #define __DCHECK_LT(val1, val2)
342 #define __DCHECK_GE(val1, val2)
343 #define __DCHECK_GT(val1, val2)
344 #define DASSERT_TRUE(cond)
345 #define DASSERT_FALSE(cond)
346 #define DASSERT_EQ(val1, val2)
347 #define DASSERT_DELTA(val1, val2, delta)
348 #define DASSERT_NE(val1, val2)
349 #define DASSERT_LE(val1, val2)
350 #define DASSERT_LT(val1, val2)
351 #define DASSERT_GE(val1, val2)
352 #define DASSERT_GT(val1, val2)
353 
354 #define DASSERT_MSG(condition, fmt, ...)
355 
356 #else
357 #define __DCHECK_EQ(val1, val2) __CHECK_EQ(val1, val2)
358 #define __DCHECK_DELTA(val1, val2, delta) __CHECK_DELTA(val1, val2, delta)
359 #define __DCHECK_NE(val1, val2) __CHECK_NE(val1, val2)
360 #define __DCHECK_LE(val1, val2) __CHECK_LE(val1, val2)
361 #define __DCHECK_LT(val1, val2) __CHECK_LT(val1, val2)
362 #define __DCHECK_GE(val1, val2) __CHECK_GE(val1, val2)
363 #define __DCHECK_GT(val1, val2) __CHECK_GT(val1, val2)
364 #define DASSERT_TRUE(cond) ASSERT_TRUE(cond)
365 #define DASSERT_FALSE(cond) ASSERT_FALSE(cond)
366 #define DASSERT_EQ(val1, val2) ASSERT_EQ(val1, val2)
367 #define DASSERT_DELTA(val1, val2, delta) ASSERT_DELTA(val1, val2, delta)
368 #define DASSERT_NE(val1, val2) ASSERT_NE(val1, val2)
369 #define DASSERT_LE(val1, val2) ASSERT_LE(val1, val2)
370 #define DASSERT_LT(val1, val2) ASSERT_LT(val1, val2)
371 #define DASSERT_GE(val1, val2) ASSERT_GE(val1, val2)
372 #define DASSERT_GT(val1, val2) ASSERT_GT(val1, val2)
373 
374 
375 #define DASSERT_MSG(condition, fmt, ...) \
376  ASSERT_MSG(condition, fmt, ##__VA_ARGS__)
377 
378 #endif
379 
380 
381 #ifdef ERROR
382 #undef ERROR // may conflict with ERROR macro on windows
383 #endif
384 
385 #endif // _LOGGING_H_