blob: 844ebaa3ae3dd401d3ed7110fc1749a5347b6589 [file] [log] [blame]
ncihnegnc5458f22019-01-28 05:08:18 -08001#include <doctest/doctest.h>
onqtamc9b4e1f2018-08-17 14:20:59 +03002
onqtam65cf6922018-08-20 11:29:33 +03003#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
4
onqtamc9b4e1f2018-08-17 14:20:59 +03005DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
6#include <thread>
onqtama2e77c72018-08-20 11:05:05 +03007#include <mutex>
8#include <exception>
9#include <stdexcept>
onqtamc9b4e1f2018-08-17 14:20:59 +030010DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
11
onqtamd5d67f32019-06-02 12:10:02 +030012DOCTEST_MSVC_SUPPRESS_WARNING(4626) // assignment operator was implicitly defined as deleted
13
onqtamc9b4e1f2018-08-17 14:20:59 +030014TEST_CASE("threads...") {
onqtama2e77c72018-08-20 11:05:05 +030015 auto call_from_thread = [](int value) {
16 INFO("print me!");
17 // one of these has to fail
18 CHECK(value == 1);
19 CHECK(value == 2);
20 };
21
22 int data_1 = 1;
23 int data_2 = 2;
24 CAPTURE(data_1); // will not be used for assertions in other threads
25
26 // subcases have to be used only in the main thread (where the test runner is)
27 SUBCASE("test runner thread") {
28 call_from_thread(data_1);
29 }
30
31 // normal threads which are assumed not to throw
32 SUBCASE("spawned threads") {
33 std::thread t1(call_from_thread, data_1);
34 std::thread t2(call_from_thread, data_2);
35
36 t1.join();
37 t2.join();
38 }
39
40 // exceptions from threads (that includes failing REQUIRE asserts) have to be handled explicitly
41 SUBCASE("spawned threads with exception propagation") {
onqtam8f100442018-08-20 11:53:10 +030042 std::exception_ptr exception_ptr = nullptr;
43 std::mutex mutex;
44
45 auto might_throw = [&]() {
onqtama2e77c72018-08-20 11:05:05 +030046 try {
47 REQUIRE(1 == 1);
48 REQUIRE(1 == 2); // will fail and throw an exception
49 MESSAGE("not reached!");
50 } catch(...) {
onqtam8f100442018-08-20 11:53:10 +030051 // make sure there are no races when dealing with the exception ptr
52 std::lock_guard<std::mutex> lock(mutex);
onqtama2e77c72018-08-20 11:05:05 +030053
onqtam8f100442018-08-20 11:53:10 +030054 // set the exception pointer in case of an exception - might overwrite
onqtama2e77c72018-08-20 11:05:05 +030055 // another exception but here we care about propagating any exception - not all
onqtam8f100442018-08-20 11:53:10 +030056 exception_ptr = std::current_exception();
onqtama2e77c72018-08-20 11:05:05 +030057 }
58 };
59 std::thread t1(might_throw);
60 std::thread t2(might_throw);
61
62 t1.join();
63 t2.join();
64
65 // if any thread has thrown an exception - rethrow it
onqtam8f100442018-08-20 11:53:10 +030066 if(exception_ptr)
67 std::rethrow_exception(exception_ptr);
onqtama2e77c72018-08-20 11:05:05 +030068 }
onqtamc9b4e1f2018-08-17 14:20:59 +030069}
onqtam65cf6922018-08-20 11:29:33 +030070
71#endif // DOCTEST_CONFIG_NO_EXCEPTIONS