Coverage Report

Created: 2023-12-08 06:52

/src/capnproto/c++/src/kj/test.h
Line
Count
Source (jump to first uncovered line)
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
protected:
43
  template <typename Func>
44
  void doBenchmark(Func&& func) {
45
    // Perform a benchmark with configurable iterations. func() will be called N times, where N
46
    // is set by the --benchmark CLI flag. This defaults to 1, so that when --benchmark is not
47
    // specified, we only test that the benchmark works.
48
    //
49
    // In the future, this could adaptively choose iteration count by running a few iterations to
50
    // find out how fast the benchmark is, then scaling.
51
52
    for (size_t i = iterCount(); i-- > 0;) {
53
      func();
54
    }
55
  }
56
57
private:
58
  const char* file;
59
  uint line;
60
  const char* description;
61
  TestCase* next;
62
  TestCase** prev;
63
  bool matchedFilter;
64
65
  static size_t iterCount();
66
67
  friend class TestRunner;
68
};
69
70
#define KJ_TEST(description) \
71
  /* Make sure the linker fails if tests are not in anonymous namespaces. */ \
72
  extern int KJ_CONCAT(YouMustWrapTestsInAnonymousNamespace, __COUNTER__) KJ_UNUSED; \
73
  class KJ_UNIQUE_NAME(TestCase): public ::kj::TestCase { \
74
  public: \
75
    KJ_UNIQUE_NAME(TestCase)(): ::kj::TestCase(__FILE__, __LINE__, description) {} \
76
    void run() override; \
77
  } KJ_UNIQUE_NAME(testCase); \
78
  void KJ_UNIQUE_NAME(TestCase)::run()
79
80
#if KJ_MSVC_TRADITIONAL_CPP
81
#define KJ_INDIRECT_EXPAND(m, vargs) m vargs
82
#define KJ_FAIL_EXPECT(...) \
83
  KJ_INDIRECT_EXPAND(KJ_LOG, (ERROR , __VA_ARGS__));
84
#define KJ_EXPECT(cond, ...) \
85
  if (auto _kjCondition = ::kj::_::MAGIC_ASSERT << cond); \
86
  else KJ_INDIRECT_EXPAND(KJ_FAIL_EXPECT, ("failed: expected " #cond , _kjCondition, __VA_ARGS__))
87
#else
88
#define KJ_FAIL_EXPECT(...) \
89
193k
  KJ_LOG(ERROR, ##__VA_ARGS__);
90
#define KJ_EXPECT(cond, ...) \
91
205k
  if (auto _kjCondition = ::kj::_::MAGIC_ASSERT << cond); \
92
205k
  else KJ_FAIL_EXPECT("failed: expected " #cond, _kjCondition, ##__VA_ARGS__)
93
#endif
94
95
// TODO(msvc): cast results to void like non-MSVC versions do
96
#if _MSC_VER && !defined(__clang__)
97
#define KJ_EXPECT_THROW_RECOVERABLE(type, code, ...) \
98
  do { \
99
    KJ_IF_SOME(e, ::kj::runCatchingExceptions([&]() { code; })) { \
100
      KJ_INDIRECT_EXPAND(KJ_EXPECT, (e.getType() == ::kj::Exception::Type::type, \
101
          "code threw wrong exception type: " #code, e, __VA_ARGS__)); \
102
    } else { \
103
      KJ_INDIRECT_EXPAND(KJ_FAIL_EXPECT, ("code did not throw: " #code, __VA_ARGS__)); \
104
    } \
105
  } while (false)
106
107
#define KJ_EXPECT_THROW_RECOVERABLE_MESSAGE(message, code, ...) \
108
  do { \
109
    KJ_IF_SOME(e, ::kj::runCatchingExceptions([&]() { code; })) { \
110
      KJ_INDIRECT_EXPAND(KJ_EXPECT, (e.getDescription().contains(message), \
111
          "exception description didn't contain expected substring", e, __VA_ARGS__)); \
112
    } else { \
113
      KJ_INDIRECT_EXPAND(KJ_FAIL_EXPECT, ("code did not throw: " #code, __VA_ARGS__)); \
114
    } \
115
  } while (false)
116
#else
117
#define KJ_EXPECT_THROW_RECOVERABLE(type, code, ...) \
118
  do { \
119
    KJ_IF_SOME(e, ::kj::runCatchingExceptions([&]() { (void)({code;}); })) { \
120
      KJ_EXPECT(e.getType() == ::kj::Exception::Type::type, \
121
          "code threw wrong exception type: " #code, e, ##__VA_ARGS__); \
122
    } else { \
123
      KJ_FAIL_EXPECT("code did not throw: " #code, ##__VA_ARGS__); \
124
    } \
125
  } while (false)
126
127
#define KJ_EXPECT_THROW_RECOVERABLE_MESSAGE(message, code, ...) \
128
  do { \
129
    KJ_IF_SOME(e, ::kj::runCatchingExceptions([&]() { (void)({code;}); })) { \
130
      KJ_EXPECT(e.getDescription().contains(message), \
131
          "exception description didn't contain expected substring", e, ##__VA_ARGS__); \
132
    } else { \
133
      KJ_FAIL_EXPECT("code did not throw: " #code, ##__VA_ARGS__); \
134
    } \
135
  } while (false)
136
#endif
137
138
#define KJ_EXPECT_THROW KJ_EXPECT_THROW_RECOVERABLE
139
#define KJ_EXPECT_THROW_MESSAGE KJ_EXPECT_THROW_RECOVERABLE_MESSAGE
140
141
#define KJ_EXPECT_EXIT(statusCode, code) \
142
  do { \
143
    KJ_EXPECT(::kj::_::expectExit(statusCode, [&]() { code; })); \
144
  } while (false)
145
// Forks the code and expects it to exit with a given code.
146
147
#define KJ_EXPECT_SIGNAL(signal, code) \
148
  do { \
149
    KJ_EXPECT(::kj::_::expectSignal(signal, [&]() { code; })); \
150
  } while (false)
151
// Forks the code and expects it to trigger a signal.
152
// In the child resets all signal handlers as printStackTraceOnCrash sets.
153
154
#define KJ_EXPECT_LOG(level, substring) \
155
  ::kj::_::LogExpectation KJ_UNIQUE_NAME(_kjLogExpectation)(::kj::LogSeverity::level, substring)
156
// Expects that a log message with the given level and substring text will be printed within
157
// the current scope. This message will not cause the test to fail, even if it is an error.
158
159
// =======================================================================================
160
161
namespace _ {  // private
162
163
bool expectExit(Maybe<int> statusCode, FunctionParam<void()> code) noexcept;
164
// Expects that the given code will exit with a given statusCode.
165
// The test will fork() and run in a subprocess. On Windows, where fork() is not available,
166
// this always returns true.
167
168
bool expectSignal(Maybe<int> signal, FunctionParam<void()> code) noexcept;
169
// Expects that the given code will trigger a signal.
170
// The test will fork() and run in a subprocess. On Windows, where fork() is not available,
171
// this always returns true.
172
// Resets signal handlers to default prior to running the code in the child process.
173
174
class LogExpectation: public ExceptionCallback {
175
public:
176
  LogExpectation(LogSeverity severity, StringPtr substring);
177
  ~LogExpectation();
178
179
  void logMessage(LogSeverity severity, const char* file, int line, int contextDepth,
180
                  String&& text) override;
181
182
private:
183
  LogSeverity severity;
184
  StringPtr substring;
185
  bool seen;
186
  UnwindDetector unwindDetector;
187
};
188
189
class GlobFilter {
190
  // Implements glob filters for the --filter flag.
191
  //
192
  // Exposed in header only for testing.
193
194
public:
195
  explicit GlobFilter(const char* pattern);
196
  explicit GlobFilter(ArrayPtr<const char> pattern);
197
198
  bool matches(StringPtr name);
199
200
private:
201
  String pattern;
202
  Vector<uint> states;
203
204
  void applyState(char c, int state);
205
};
206
207
}  // namespace _ (private)
208
}  // namespace kj
209
210
KJ_END_HEADER