blob: c6d11317b5a124da16d038a3683aae9a21b5e5b2 [file] [log] [blame]
Jan Kundrát5c805212018-03-02 13:57:12 +01001#pragma once
2
3#ifdef REQUIRE
4# error This file needs to be included prior to including anything from Catch.
5#endif
6
7// clang-format off
8
9#include <ostream>
10#include <thread>
11#include <catch.hpp>
12#include <trompeloeil.hpp>
13
14// this is copy-paste from https://github.com/rollbear/trompeloeil/blob/master/docs/CookBook.md/#unit_test_frameworks
15namespace trompeloeil {
16
17/** @short Pass reports from the Trompeloeil mocker to Catch for processing as test failures */
18template <>
19struct reporter<trompeloeil::specialized>
20{
21 static void send(trompeloeil::severity s,
22 const char* file,
23 unsigned long line,
24 const char* msg)
25 {
26 std::ostringstream os;
27 if (line) os << file << ':' << line << '\n';
28 os << msg;
29 auto failure = os.str();
30 if (s == severity::fatal)
31 {
32 FAIL(failure);
33 }
34 else
35 {
36 CAPTURE(failure);
37 CHECK(failure.empty());
38 }
39 }
40};
41}
42
43/** @short Wait until a given sequence of expectation is matched, and then a bit more to ensure that there's silence afterwards */
44void waitForCompletionAndBitMore(const trompeloeil::sequence& seq)
45{
46 using namespace std::literals;
47 using clock = std::chrono::steady_clock;
48
49 // We're busy-waiting a bit
50 const auto waitingStep = 30ms;
51 // Timeout after this much
52 const auto completionTimeout = 5000ms;
53 // When checking for silence afterwards, wait at least this long.
54 // We'll also wait as long as it originally took to process everything.
55 const auto minExtraWait = 100ms;
56
57 auto start = clock::now();
58 while (!seq.is_completed()) {
59 std::this_thread::sleep_for(waitingStep);
60 if (clock::now() - start > completionTimeout) {
61 break;
62 }
63 }
64 REQUIRE(seq.is_completed());
65 auto duration = std::chrono::duration<double>(clock::now() - start);
66 std::this_thread::sleep_for(std::max(duration, decltype(duration)(minExtraWait)));
67}