test(util): add tests for SafeSignal
Add a fixture for writing tests that require interaction with Glib event loop and a very basic test for SafeSignal.pull/1244/head
parent
79883dbce4
commit
3e2197a82a
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
#include <glibmm/main.h>
|
||||||
|
/**
|
||||||
|
* Minimal Glib application to be used for tests that require Glib main loop
|
||||||
|
*/
|
||||||
|
class GlibTestsFixture : public sigc::trackable {
|
||||||
|
public:
|
||||||
|
GlibTestsFixture() : main_loop_{Glib::MainLoop::create()} {}
|
||||||
|
|
||||||
|
void run(std::function<void()> fn) {
|
||||||
|
Glib::signal_idle().connect_once(fn);
|
||||||
|
main_loop_->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
void quit() { main_loop_->quit(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Glib::RefPtr<Glib::MainLoop> main_loop_;
|
||||||
|
};
|
|
@ -0,0 +1,63 @@
|
||||||
|
#define CATCH_CONFIG_RUNNER
|
||||||
|
#include "util/SafeSignal.hpp"
|
||||||
|
|
||||||
|
#include <glibmm.h>
|
||||||
|
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include "GlibTestsFixture.hpp"
|
||||||
|
|
||||||
|
using namespace waybar;
|
||||||
|
/**
|
||||||
|
* Basic sanity test for SafeSignal:
|
||||||
|
* check that type deduction works, events are delivered and the order is right
|
||||||
|
* Running this with -fsanitize=thread should not fail
|
||||||
|
*/
|
||||||
|
TEST_CASE_METHOD(GlibTestsFixture, "SafeSignal basic functionality", "[signal][thread][util]") {
|
||||||
|
const int NUM_EVENTS = 100;
|
||||||
|
int count = 0;
|
||||||
|
int last_value = 0;
|
||||||
|
|
||||||
|
SafeSignal<int, std::string> test_signal;
|
||||||
|
|
||||||
|
const auto main_tid = std::this_thread::get_id();
|
||||||
|
std::thread producer;
|
||||||
|
|
||||||
|
// timeout the test in 500ms
|
||||||
|
Glib::signal_timeout().connect_once([]() { throw std::runtime_error("Test timed out"); }, 500);
|
||||||
|
|
||||||
|
test_signal.connect([&](auto val, auto str) {
|
||||||
|
static_assert(std::is_same<int, decltype(val)>::value);
|
||||||
|
static_assert(std::is_same<std::string, decltype(str)>::value);
|
||||||
|
// check that we're in the same thread as the main loop
|
||||||
|
REQUIRE(std::this_thread::get_id() == main_tid);
|
||||||
|
// check event order
|
||||||
|
REQUIRE(val == last_value + 1);
|
||||||
|
|
||||||
|
last_value = val;
|
||||||
|
if (++count >= NUM_EVENTS) {
|
||||||
|
this->quit();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
run([&]() {
|
||||||
|
// check that events from the same thread are delivered and processed synchronously
|
||||||
|
test_signal.emit(1, "test");
|
||||||
|
REQUIRE(count == 1);
|
||||||
|
|
||||||
|
// start another thread and generate events
|
||||||
|
producer = std::thread([&]() {
|
||||||
|
for (auto i = 2; i <= NUM_EVENTS; ++i) {
|
||||||
|
test_signal.emit(i, "test");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
producer.join();
|
||||||
|
REQUIRE(count == NUM_EVENTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
Glib::init();
|
||||||
|
return Catch::Session().run(argc, argv);
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ test_inc = include_directories('../include')
|
||||||
test_dep = [
|
test_dep = [
|
||||||
catch2,
|
catch2,
|
||||||
fmt,
|
fmt,
|
||||||
|
gtkmm,
|
||||||
jsoncpp,
|
jsoncpp,
|
||||||
spdlog,
|
spdlog,
|
||||||
]
|
]
|
||||||
|
@ -14,8 +15,21 @@ config_test = executable(
|
||||||
include_directories: test_inc,
|
include_directories: test_inc,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
safesignal_test = executable(
|
||||||
|
'safesignal_test',
|
||||||
|
'SafeSignal.cpp',
|
||||||
|
dependencies: test_dep,
|
||||||
|
include_directories: test_inc,
|
||||||
|
)
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'Configuration test',
|
'Configuration test',
|
||||||
config_test,
|
config_test,
|
||||||
workdir: meson.source_root(),
|
workdir: meson.source_root(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
test(
|
||||||
|
'SafeSignal test',
|
||||||
|
safesignal_test,
|
||||||
|
workdir: meson.source_root(),
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue