module; #include "../../src/ErrorSimulator.hpp" module Tests; import Core.Test; import Core.Thread; import Core.Meta; static int runDone = 0; struct IntHolder { int value; }; static void run(void*) { runDone = 1; } static void testStart() { runDone = 0; { Core::Thread t; Core::testFalse(t.start(run, nullptr)); } Core::test(1, runDone); } static void testLambda() { IntHolder i(0); Core::Thread t; Core::testFalse(t.start( [](void* p) { IntHolder* ip = static_cast(p); ip->value = 2; }, &i)); Core::testFalse(t.join()); Core::test(2, i.value); } static void testJoinWithoutStart() { Core::Thread t; Core::testFalse(t.join()); } static void testAutoJoin() { Core::Thread t; Core::testFalse(t.start([](void*) {}, nullptr)); } static void testMove() { Core::Thread t; Core::testFalse(t.start([](void*) {}, nullptr)); Core::Thread m = Core::move(t); Core::testFalse(m.join()); } static void testMoveAssignment() { Core::Thread t; Core::testFalse(t.start([](void*) {}, nullptr)); Core::Thread m; m = Core::move(t); Core::testFalse(m.join()); } static void testMoveIntoActive() { Core::Thread t; Core::testFalse(t.start([](void*) {}, nullptr)); Core::Thread m; t = Core::move(m); } static void testDoubleJoin() { Core::Thread t; Core::testFalse(t.start([](void*) {}, nullptr)); Core::testFalse(t.join()); Core::testFalse(t.join()); } struct MutexCounter { Core::Mutex m{}; int counter = 0; }; static void incrementMutexCounter(void* p) { MutexCounter* mcp = static_cast(p); for(int i = 0; i < 100'000; i++) { Core::MutexGuard mg(mcp->m); mcp->counter++; } } static void testMutex() { MutexCounter mc; Core::Thread t[2]; Core::testFalse(t[0].start(incrementMutexCounter, &mc)); Core::testFalse(t[1].start(incrementMutexCounter, &mc)); Core::testFalse(t[0].join()); Core::testFalse(t[1].join()); Core::test(200'000, mc.counter); } static void testDoubleStart() { Core::Thread t; Core::testFalse(t.start([](void*) {}, nullptr)); Core::testTrue(t.start([](void*) {}, nullptr)); } static void testFail() { #ifdef ERROR_SIMULATOR Core::Mutex m; failStepThrow = 1; m.lock(); failStepThrow = 1; m.unlock(); Core::Thread t; failStepThrow = 1; Core::testTrue(t.start([](void*) {}, nullptr)); Core::testFalse(t.start([](void*) {}, nullptr)); failStepThrow = 1; Core::testTrue(t.join()); #endif } void testThread() { testStart(); testLambda(); testJoinWithoutStart(); testAutoJoin(); testMove(); testMoveAssignment(); testMoveIntoActive(); testDoubleJoin(); testMutex(); testDoubleStart(); testFail(); }