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.
This commit is contained in:
		
							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 = [ | ||||
|     catch2, | ||||
|     fmt, | ||||
|     gtkmm, | ||||
|     jsoncpp, | ||||
|     spdlog, | ||||
| ] | ||||
|  | @ -14,8 +15,21 @@ config_test = executable( | |||
|     include_directories: test_inc, | ||||
| ) | ||||
| 
 | ||||
| safesignal_test = executable( | ||||
|     'safesignal_test', | ||||
|     'SafeSignal.cpp', | ||||
|     dependencies: test_dep, | ||||
|     include_directories: test_inc, | ||||
| ) | ||||
| 
 | ||||
| test( | ||||
|     'Configuration test', | ||||
|     config_test, | ||||
|     workdir: meson.source_root(), | ||||
| ) | ||||
| 
 | ||||
| test( | ||||
|     'SafeSignal test', | ||||
|     safesignal_test, | ||||
|     workdir: meson.source_root(), | ||||
| ) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue