//
// libsemigroups - C++ library for semigroups and monoids
// Copyright (C) 2019 James D. Mitchell
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// The purpose of this file is to test the Race class.
#include <cstddef>
// for size_t
#include "catch.hpp" // for REQUIRE, REQUIRE_THROWS_AS
#include "libsemigroups/exception.hpp" // for LibsemigroupsException (ptr o...
#include "libsemigroups/race.hpp" // for Race
#include "libsemigroups/report.hpp" // for ReportGuard
#include "libsemigroups/runner.hpp" // for Runner
#include "test-main.hpp" // for LIBSEMIGROUPS_TEST_CASE
namespace libsemigroups {
struct LibsemigroupsException;
constexpr
bool REPORT =
false;
namespace detail {
class TestRunner1 :
public Runner {
private:
void run_impl() override {
while (!stopped()) {
}
}
bool finished_impl()
const override {
return stopped();
}
};
class TestRunner2 :
public Runner {
private:
void run_impl() override {}
bool finished_impl()
const override {
return true;
}
};
class TestRunner3 :
public Runner {
private:
void run_impl() override {
std::this_thread::sleep_for(std::chrono::milliseconds(25));
}
bool finished_impl()
const override {
return started();
}
};
LIBSEMIGROUPS_TEST_CASE(
"Race",
"001",
"run_for",
"[quick]") {
auto rg = ReportGuard(REPORT);
Race rc;
rc.max_threads(1);
REQUIRE(rc.max_threads() == 1);
rc.add_runner(std::make_shared<TestRunner1>());
rc.run_for(std::chrono::milliseconds(10));
rc.run_until([]() ->
bool {
return true; });
REQUIRE(rc.winner() != nullptr);
}
LIBSEMIGROUPS_TEST_CASE(
"Race",
"002",
"run_until",
"[quick]") {
auto rg = ReportGuard(REPORT);
Race rc;
rc.add_runner(std::make_shared<TestRunner1>());
size_t nr = 0;
auto foo = [&nr]() ->
bool {
return ++nr == 2; };
rc.run_until(foo, std::chrono::milliseconds(10));
REQUIRE(rc.winner() != nullptr);
}
LIBSEMIGROUPS_TEST_CASE(
"Race",
"003",
"exceptions",
"[quick]") {
auto rg = ReportGuard(REPORT);
Race rc;
REQUIRE_THROWS_AS(rc.run_for(std::chrono::milliseconds(10)),
LibsemigroupsException);
REQUIRE_THROWS_AS(rc.run_until([]() ->
bool {
return true; }),
LibsemigroupsException);
REQUIRE_THROWS_AS(rc.run(), LibsemigroupsException);
rc.add_runner(std::make_shared<TestRunner1>());
rc.run_for(std::chrono::milliseconds(10));
REQUIRE(rc.winner() != nullptr);
auto tr = std::make_shared<TestRunner1>();
REQUIRE_THROWS_AS(rc.add_runner(tr), LibsemigroupsException);
}
LIBSEMIGROUPS_TEST_CASE(
"Race",
"004",
"iterators",
"[quick]") {
auto rg = ReportGuard(REPORT);
Race rc;
rc.max_threads(2);
rc.add_runner(std::make_shared<TestRunner1>());
rc.add_runner(std::make_shared<TestRunner1>());
REQUIRE(size_t(rc.end() - rc.begin()) == rc.number_runners());
REQUIRE(size_t(rc.cend() - rc.cbegin()) == rc.number_runners());
REQUIRE(2 == rc.number_runners());
}
LIBSEMIGROUPS_TEST_CASE(
"Race",
"005",
"find_runner",
"[quick]") {
auto rg = ReportGuard(REPORT);
Race rc;
rc.max_threads(2);
rc.add_runner(std::make_shared<TestRunner1>());
rc.add_runner(std::make_shared<TestRunner1>());
REQUIRE(rc.find_runner<TestRunner1>() != nullptr);
REQUIRE(rc.find_runner<TestRunner2>() == nullptr);
}
LIBSEMIGROUPS_TEST_CASE(
"Race",
"006",
"run_func",
"[quick]") {
auto rg = ReportGuard(REPORT);
Race rc;
rc.max_threads(2);
rc.add_runner(std::make_shared<TestRunner1>());
rc.add_runner(std::make_shared<TestRunner3>());
rc.run_for(std::chrono::milliseconds(10));
REQUIRE(rc.winner() != nullptr);
}
LIBSEMIGROUPS_TEST_CASE(
"Race",
"007",
"run_func",
"[quick]") {
auto rg = ReportGuard(REPORT);
Race rc;
rc.max_threads(2);
TestRunner1* tr =
new TestRunner1();
tr->run_for(std::chrono::milliseconds(10));
rc.add_runner(std::shared_ptr<TestRunner1>(tr));
rc.add_runner(std::make_shared<TestRunner3>());
rc.run_for(std::chrono::milliseconds(10));
REQUIRE(rc.winner() != nullptr);
}
LIBSEMIGROUPS_TEST_CASE(
"Race",
"008",
"run_func",
"[quick]") {
auto rg = ReportGuard(REPORT);
Race rc;
rc.max_threads(4);
rc.add_runner(std::make_shared<TestRunner1>());
rc.add_runner(std::make_shared<TestRunner1>());
rc.add_runner(std::make_shared<TestRunner1>());
rc.add_runner(std::make_shared<TestRunner1>());
rc.run_for(std::chrono::milliseconds(10));
REQUIRE(rc.winner() != nullptr);
}
}
// namespace detail
}
// namespace libsemigroups