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 | #if defined(__GNUC__) && !KJ_HEADER_WARNINGS |
25 | #pragma GCC system_header |
26 | #endif |
27 | |
28 | #include "debug.h" |
29 | #include "vector.h" |
30 | #include "function.h" |
31 | #include "windows-sanity.h" // work-around macro conflict with `ERROR` |
32 | |
33 | namespace kj { |
34 | |
35 | class TestRunner; |
36 | |
37 | class TestCase { |
38 | public: |
39 | TestCase(const char* file, uint line, const char* description); |
40 | ~TestCase(); |
41 | |
42 | virtual void run() = 0; |
43 | |
44 | private: |
45 | const char* file; |
46 | uint line; |
47 | const char* description; |
48 | TestCase* next; |
49 | TestCase** prev; |
50 | bool matchedFilter; |
51 | |
52 | friend class TestRunner; |
53 | }; |
54 | |
55 | #define KJ_TEST(description) \ |
56 | /* Make sure the linker fails if tests are not in anonymous namespaces. */ \ |
57 | extern int KJ_CONCAT(YouMustWrapTestsInAnonymousNamespace, __COUNTER__) KJ_UNUSED; \ |
58 | class KJ_UNIQUE_NAME(TestCase): public ::kj::TestCase { \ |
59 | public: \ |
60 | KJ_UNIQUE_NAME(TestCase)(): ::kj::TestCase(__FILE__, __LINE__, description) {} \ |
61 | void run() override; \ |
62 | } KJ_UNIQUE_NAME(testCase); \ |
63 | void KJ_UNIQUE_NAME(TestCase)::run() |
64 | |
65 | #if _MSC_VER |
66 | #define KJ_INDIRECT_EXPAND(m, vargs) m vargs |
67 | #define KJ_FAIL_EXPECT(...) \ |
68 | KJ_INDIRECT_EXPAND(KJ_LOG, (ERROR , __VA_ARGS__)); |
69 | #define KJ_EXPECT(cond, ...) \ |
70 | if (cond); else KJ_INDIRECT_EXPAND(KJ_FAIL_EXPECT, ("failed: expected " #cond , __VA_ARGS__)) |
71 | #else |
72 | #define KJ_FAIL_EXPECT(...) \ |
73 | KJ_LOG(ERROR, ##__VA_ARGS__); |
74 | #define KJ_EXPECT(cond, ...) \ |
75 | if (cond); else KJ_FAIL_EXPECT("failed: expected " #cond, ##__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->getType()); \ |
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->getDescription()); \ |
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 | |