From 39198ff8451c10d066658d12f01d6d402e139c6f Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 2 Dec 2021 15:06:35 +0100 Subject: [PATCH] Basic tests for BoostThreadWorker Separate job tests --- src/slic3r/GUI/Jobs/BoostThreadWorker.hpp | 2 - tests/slic3rutils/CMakeLists.txt | 1 + tests/slic3rutils/slic3r_jobs_tests.cpp | 134 ++++++++++++++++++++++ 3 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 tests/slic3rutils/slic3r_jobs_tests.cpp diff --git a/src/slic3r/GUI/Jobs/BoostThreadWorker.hpp b/src/slic3r/GUI/Jobs/BoostThreadWorker.hpp index 31ca9b591..f2da275c3 100644 --- a/src/slic3r/GUI/Jobs/BoostThreadWorker.hpp +++ b/src/slic3r/GUI/Jobs/BoostThreadWorker.hpp @@ -5,8 +5,6 @@ #include "Worker.hpp" -#include - #include #include diff --git a/tests/slic3rutils/CMakeLists.txt b/tests/slic3rutils/CMakeLists.txt index e1ac113ae..be1b645d7 100644 --- a/tests/slic3rutils/CMakeLists.txt +++ b/tests/slic3rutils/CMakeLists.txt @@ -1,6 +1,7 @@ get_filename_component(_TEST_NAME ${CMAKE_CURRENT_LIST_DIR} NAME) add_executable(${_TEST_NAME}_tests ${_TEST_NAME}_tests_main.cpp + slic3r_jobs_tests.cpp ) target_link_libraries(${_TEST_NAME}_tests test_common libslic3r_gui libslic3r) diff --git a/tests/slic3rutils/slic3r_jobs_tests.cpp b/tests/slic3rutils/slic3r_jobs_tests.cpp new file mode 100644 index 000000000..1d4f165af --- /dev/null +++ b/tests/slic3rutils/slic3r_jobs_tests.cpp @@ -0,0 +1,134 @@ +#include "catch2/catch.hpp" + +#include "slic3r/GUI/Jobs/BoostThreadWorker.hpp" +#include "slic3r/GUI/Jobs/ProgressIndicator.hpp" + +struct Progress: Slic3r::ProgressIndicator { + int range = 100; + int pr = 0; + std::string statustxt; + void set_range(int r) override { range = r; } + void set_cancel_callback(CancelFn = CancelFn()) override {} + void set_progress(int p) override { pr = p; } + void set_status_text(const char *txt) override { statustxt = txt; } + int get_range() const override { return range; } +}; + +TEST_CASE("nullptr job should be ignored", "[Jobs]") { + Slic3r::GUI::BoostThreadWorker worker{std::make_unique()}; + worker.push(nullptr); + + REQUIRE(worker.is_idle()); +} + +TEST_CASE("State should not be idle while running a job", "[Jobs]") { + using namespace Slic3r; + using namespace Slic3r::GUI; + BoostThreadWorker worker{std::make_unique(), "worker_thread"}; + + queue_job(worker, [&worker](Job::Ctl &ctl) { + ctl.call_on_main_thread([&worker] { + REQUIRE(!worker.is_idle()); + }).wait(); + }); + + while (!worker.is_idle()) + worker.process_events(); + + REQUIRE(worker.is_idle()); +} + +TEST_CASE("Status messages should be received by the main thread during job execution", "[Jobs]") { + using namespace Slic3r; + using namespace Slic3r::GUI; + auto pri = std::make_shared(); + BoostThreadWorker worker{pri}; + + queue_job(worker, [](Job::Ctl &ctl){ + for (int s = 0; s <= 100; ++s) { + ctl.update_status(s, "Running"); + } + }); + + while (!worker.is_idle()) + worker.process_events(); + + REQUIRE(pri->pr == 100); + REQUIRE(pri->statustxt == "Running"); +} + +TEST_CASE("Cancellation should be recognized be the worker", "[Jobs]") { + using namespace Slic3r; + using namespace Slic3r::GUI; + + auto pri = std::make_shared(); + BoostThreadWorker worker{pri}; + + queue_job( + worker, + [](Job::Ctl &ctl) { + for (int s = 0; s <= 100; ++s) { + usleep(10000); + ctl.update_status(s, "Running"); + if (ctl.was_canceled()) break; + } + }, + [](bool cancelled, std::exception_ptr &) { // finalize + REQUIRE(cancelled == true); + }); + + usleep(1000); + worker.cancel(); + + while (!worker.is_idle()) + worker.process_events(); + + REQUIRE(pri->pr != 100); +} + +TEST_CASE("Cancel_all should remove all pending jobs", "[Jobs]") { + using namespace Slic3r; + using namespace Slic3r::GUI; + + auto pri = std::make_shared(); + BoostThreadWorker worker{pri}; + + std::array jobres = {false}; + + queue_job(worker, [&jobres](Job::Ctl &) { jobres[0] = true; usleep(1000); }); + queue_job(worker, [&jobres](Job::Ctl &) { jobres[1] = true; usleep(1000); }); + queue_job(worker, [&jobres](Job::Ctl &) { jobres[2] = true; usleep(1000); }); + queue_job(worker, [&jobres](Job::Ctl &) { jobres[3] = true; usleep(1000); }); + + usleep(500); + worker.cancel_all(); + + REQUIRE(jobres[0] == true); + REQUIRE(jobres[1] == false); + REQUIRE(jobres[2] == false); + REQUIRE(jobres[3] == false); +} + +TEST_CASE("Exception should be properly forwarded to finalize()", "[Jobs]") { + using namespace Slic3r; + using namespace Slic3r::GUI; + + auto pri = std::make_shared(); + BoostThreadWorker worker{pri}; + + queue_job( + worker, [](Job::Ctl &) { throw std::runtime_error("test"); }, + [](bool /*canceled*/, std::exception_ptr &eptr) { + REQUIRE(eptr != nullptr); + try { + std::rethrow_exception(eptr); + } catch (std::runtime_error &e) { + REQUIRE(std::string(e.what()) == "test"); + } + + eptr = nullptr; + }); + + while (!worker.is_idle()) + worker.process_events(); +}