test.h (5655B)
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors 2 // Licensed under the MIT License: 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 22 #pragma once 23 24 #include "debug.h" 25 #include "vector.h" 26 #include "function.h" 27 #include "windows-sanity.h" // work-around macro conflict with `ERROR` 28 29 KJ_BEGIN_HEADER 30 31 namespace kj { 32 33 class TestRunner; 34 35 class TestCase { 36 public: 37 TestCase(const char* file, uint line, const char* description); 38 ~TestCase(); 39 40 virtual void run() = 0; 41 42 private: 43 const char* file; 44 uint line; 45 const char* description; 46 TestCase* next; 47 TestCase** prev; 48 bool matchedFilter; 49 50 friend class TestRunner; 51 }; 52 53 #define KJ_TEST(description) \ 54 /* Make sure the linker fails if tests are not in anonymous namespaces. */ \ 55 extern int KJ_CONCAT(YouMustWrapTestsInAnonymousNamespace, __COUNTER__) KJ_UNUSED; \ 56 class KJ_UNIQUE_NAME(TestCase): public ::kj::TestCase { \ 57 public: \ 58 KJ_UNIQUE_NAME(TestCase)(): ::kj::TestCase(__FILE__, __LINE__, description) {} \ 59 void run() override; \ 60 } KJ_UNIQUE_NAME(testCase); \ 61 void KJ_UNIQUE_NAME(TestCase)::run() 62 63 #if _MSC_VER && !defined(__clang__) 64 #define KJ_INDIRECT_EXPAND(m, vargs) m vargs 65 #define KJ_FAIL_EXPECT(...) \ 66 KJ_INDIRECT_EXPAND(KJ_LOG, (ERROR , __VA_ARGS__)); 67 #define KJ_EXPECT(cond, ...) \ 68 if (auto _kjCondition = ::kj::_::MAGIC_ASSERT << cond); \ 69 else KJ_INDIRECT_EXPAND(KJ_FAIL_EXPECT, ("failed: expected " #cond , _kjCondition, __VA_ARGS__)) 70 #else 71 #define KJ_FAIL_EXPECT(...) \ 72 KJ_LOG(ERROR, ##__VA_ARGS__); 73 #define KJ_EXPECT(cond, ...) \ 74 if (auto _kjCondition = ::kj::_::MAGIC_ASSERT << cond); \ 75 else KJ_FAIL_EXPECT("failed: expected " #cond, _kjCondition, ##__VA_ARGS__) 76 #endif 77 78 #define KJ_EXPECT_THROW_RECOVERABLE(type, code) \ 79 do { \ 80 KJ_IF_MAYBE(e, ::kj::runCatchingExceptions([&]() { code; })) { \ 81 KJ_EXPECT(e->getType() == ::kj::Exception::Type::type, \ 82 "code threw wrong exception type: " #code, *e); \ 83 } else { \ 84 KJ_FAIL_EXPECT("code did not throw: " #code); \ 85 } \ 86 } while (false) 87 88 #define KJ_EXPECT_THROW_RECOVERABLE_MESSAGE(message, code) \ 89 do { \ 90 KJ_IF_MAYBE(e, ::kj::runCatchingExceptions([&]() { code; })) { \ 91 KJ_EXPECT(::kj::_::hasSubstring(e->getDescription(), message), \ 92 "exception description didn't contain expected substring", *e); \ 93 } else { \ 94 KJ_FAIL_EXPECT("code did not throw: " #code); \ 95 } \ 96 } while (false) 97 98 #if KJ_NO_EXCEPTIONS 99 #define KJ_EXPECT_THROW(type, code) \ 100 do { \ 101 KJ_EXPECT(::kj::_::expectFatalThrow(::kj::Exception::Type::type, nullptr, [&]() { code; })); \ 102 } while (false) 103 #define KJ_EXPECT_THROW_MESSAGE(message, code) \ 104 do { \ 105 KJ_EXPECT(::kj::_::expectFatalThrow(nullptr, kj::StringPtr(message), [&]() { code; })); \ 106 } while (false) 107 #else 108 #define KJ_EXPECT_THROW KJ_EXPECT_THROW_RECOVERABLE 109 #define KJ_EXPECT_THROW_MESSAGE KJ_EXPECT_THROW_RECOVERABLE_MESSAGE 110 #endif 111 112 #define KJ_EXPECT_LOG(level, substring) \ 113 ::kj::_::LogExpectation KJ_UNIQUE_NAME(_kjLogExpectation)(::kj::LogSeverity::level, substring) 114 // Expects that a log message with the given level and substring text will be printed within 115 // the current scope. This message will not cause the test to fail, even if it is an error. 116 117 // ======================================================================================= 118 119 namespace _ { // private 120 121 bool hasSubstring(kj::StringPtr haystack, kj::StringPtr needle); 122 123 #if KJ_NO_EXCEPTIONS 124 bool expectFatalThrow(Maybe<Exception::Type> type, Maybe<StringPtr> message, 125 Function<void()> code); 126 // Expects that the given code will throw a fatal exception matching the given type and/or message. 127 // Since exceptions are disabled, the test will fork() and run in a subprocess. On Windows, where 128 // fork() is not available, this always returns true. 129 #endif 130 131 class LogExpectation: public ExceptionCallback { 132 public: 133 LogExpectation(LogSeverity severity, StringPtr substring); 134 ~LogExpectation(); 135 136 void logMessage(LogSeverity severity, const char* file, int line, int contextDepth, 137 String&& text) override; 138 139 private: 140 LogSeverity severity; 141 StringPtr substring; 142 bool seen; 143 UnwindDetector unwindDetector; 144 }; 145 146 class GlobFilter { 147 // Implements glob filters for the --filter flag. 148 // 149 // Exposed in header only for testing. 150 151 public: 152 explicit GlobFilter(const char* pattern); 153 explicit GlobFilter(ArrayPtr<const char> pattern); 154 155 bool matches(StringPtr name); 156 157 private: 158 String pattern; 159 Vector<uint> states; 160 161 void applyState(char c, int state); 162 }; 163 164 } // namespace _ (private) 165 } // namespace kj 166 167 KJ_END_HEADER