File indexing completed on 2025-02-16 05:12:10
0001 /* 0002 * test/test.hpp 0003 * Copyright 2013 Google Inc. All Rights Reserved. 0004 * 0005 * Permission is hereby granted, free of charge, to any person obtaining a copy 0006 * of this software and associated documentation files (the "Software"), to deal 0007 * in the Software without restriction, including without limitation the rights 0008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 0009 * copies of the Software, and to permit persons to whom the Software is 0010 * furnished to do so, subject to the following conditions: 0011 * 0012 * The above copyright notice and this permission notice shall be included in 0013 * all copies or substantial portions of the Software. 0014 * 0015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 0016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 0017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 0018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 0019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 0020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 0021 * SOFTWARE. 0022 */ 0023 0024 #pragma once 0025 #ifndef H_54E531F7_9154_454B_BEB9_257408429470 0026 #define H_54E531F7_9154_454B_BEB9_257408429470 0027 0028 #include <cstdio> 0029 #include <cstring> 0030 #include <exception> 0031 #include <sstream> 0032 #include <string> 0033 #include <vector> 0034 0035 namespace test { 0036 0037 struct AssertFailedError : std::exception { 0038 ~AssertFailedError() throw() {} 0039 0040 AssertFailedError(const char *filename, int _line, const char *_errmsg) 0041 : basename(_basename(filename)), line(_line), errmsg(_errmsg) {} 0042 0043 const char *what() const throw() { 0044 if (!_what.size()) { 0045 std::ostringstream ss; 0046 ss << "assertion failed (" << basename << ":" << line; 0047 ss << ") " << errmsg; 0048 _what = ss.str(); 0049 } 0050 return _what.c_str(); 0051 } 0052 0053 const char *basename; 0054 int line; 0055 const char *errmsg; 0056 0057 mutable std::string _what; 0058 0059 static const char *_basename(const char *filename) { 0060 const char *basename = filename + strlen(filename); 0061 while (basename != filename && *basename != '/') { 0062 basename -= 1; 0063 } 0064 return basename + 1; 0065 } 0066 }; 0067 0068 enum TestStatus { 0069 SUCCESS = 0 << 0, 0070 FAILED = 1 << 0, 0071 0072 ASSERT_FAIL = FAILED | 1 << 1, 0073 EXCEPTION_UNCAUGHT = FAILED | 2 << 1, 0074 SIGNAL_UNCAUGHT = FAILED | 3 << 1, 0075 SIGNAL_SEGFAULT = SIGNAL_UNCAUGHT | 1 << 3, 0076 SIGNAL_ABORT = SIGNAL_UNCAUGHT | 2 << 3, 0077 SIGNAL_DIVZERO = SIGNAL_UNCAUGHT | 2 << 3, 0078 0079 STATUS_MASK = 0x1F 0080 }; 0081 0082 struct TestBase { 0083 const char *name; 0084 TestStatus expected_status; 0085 0086 virtual ~TestBase() {} 0087 TestBase(const char *, TestStatus); 0088 virtual void do_test() = 0; 0089 0090 TestStatus run() { 0091 try { 0092 do_test(); 0093 return SUCCESS; 0094 } catch (const AssertFailedError &e) { 0095 printf("!! %s\n", e.what()); 0096 return ASSERT_FAIL; 0097 } catch (const std::exception &e) { 0098 printf("!! exception: %s\n", e.what()); 0099 return EXCEPTION_UNCAUGHT; 0100 } catch (...) { 0101 printf("!! unknown exception\n"); 0102 return EXCEPTION_UNCAUGHT; 0103 } 0104 } 0105 }; 0106 0107 typedef std::vector<TestBase *> test_registry_t; 0108 inline test_registry_t &test_registry() { 0109 static test_registry_t reg; 0110 return reg; 0111 } 0112 0113 inline TestBase::TestBase(const char *n, TestStatus s) 0114 : name(n), expected_status(s) { 0115 test_registry().push_back(this); 0116 } 0117 0118 } // namespace test 0119 0120 #define _TEST_STATUS(name, status) \ 0121 struct TEST_##name : ::test::TestBase { \ 0122 TEST_##name() : TestBase(#name, status) {} \ 0123 void do_test(); \ 0124 } TEST_##name; \ 0125 void TEST_##name::do_test() 0126 0127 #define TEST(name) _TEST_STATUS(name, ::test::SUCCESS) 0128 #define TEST_FAIL(name) _TEST_STATUS(name, ::test::FAILED) 0129 #define TEST_FAIL_ASSERT(name) _TEST_STATUS(name, ::test::ASSERT_FAIL) 0130 #define TEST_UNCAUGHT_EXCEPTION(name) \ 0131 _TEST_STATUS(name, ::test::EXCEPTION_UNCAUGHT) 0132 #define TEST_UNCAUGHT_SIGNAL(name) _TEST_STATUS(name, ::test::SIGNAL_UNCAUGHT) 0133 #define TEST_SEGFAULT(name) _TEST_STATUS(name, ::test::SIGNAL_SEGFAULT) 0134 #define TEST_ABORT(name) _TEST_STATUS(name, ::test::SIGNAL_ABORT) 0135 #define TEST_DIVZERO(name) _TEST_STATUS(name, ::test::SIGNAL_DIVZERO) 0136 0137 #define ASSERT(expr) \ 0138 (expr) ? static_cast<void>(0) \ 0139 : throw ::test::AssertFailedError(__FILE__, __LINE__, #expr) 0140 0141 #define _ASSERT_BINOP(a, b, cmp) \ 0142 (!(a cmp b)) ? static_cast<void>(0) \ 0143 : throw ::test::AssertFailedError( \ 0144 __FILE__, __LINE__, "because " #a " " #cmp " " #b) 0145 0146 #define ASSERT_EQ(a, b) _ASSERT_BINOP(a, b, !=) 0147 #define ASSERT_NE(a, b) _ASSERT_BINOP(a, b, ==) 0148 #define ASSERT_LT(a, b) _ASSERT_BINOP(a, b, >=) 0149 #define ASSERT_LE(a, b) _ASSERT_BINOP(a, b, >) 0150 #define ASSERT_GT(a, b) _ASSERT_BINOP(a, b, <=) 0151 #define ASSERT_GE(a, b) _ASSERT_BINOP(a, b, <) 0152 0153 #define ASSERT_THROW(expr, e_type) \ 0154 do { \ 0155 try { \ 0156 expr \ 0157 } catch (const e_type &) { \ 0158 break; \ 0159 } \ 0160 throw ::test::AssertFailedError(__FILE__, __LINE__, \ 0161 "expected exception " #e_type); \ 0162 } while (0) 0163 0164 #define ASSERT_ANY_THROW(expr) \ 0165 do { \ 0166 try { \ 0167 expr \ 0168 } catch (...) { \ 0169 break; \ 0170 } \ 0171 throw ::test::AssertFailedError(__FILE__, __LINE__, \ 0172 "expected any exception"); \ 0173 } while (0) 0174 0175 #define ASSERT_NO_THROW(expr) \ 0176 try { \ 0177 expr \ 0178 } catch (...) { \ 0179 throw ::test::AssertFailedError(__FILE__, __LINE__, \ 0180 "no exception expected"); \ 0181 } 0182 0183 #endif /* H_GUARD */