diff options
-rw-r--r-- | test/meson.build | 9 | ||||
-rw-r--r-- | test/timer-fail.cpp | 103 | ||||
-rw-r--r-- | test/timer-thread.cpp | 22 |
3 files changed, 109 insertions, 25 deletions
diff --git a/test/meson.build b/test/meson.build index 189e1428..8b6057d4 100644 --- a/test/meson.build +++ b/test/meson.build @@ -69,6 +69,7 @@ internal_tests = [ {'name': 'signal-threads', 'sources': ['signal-threads.cpp']}, {'name': 'threads', 'sources': 'threads.cpp', 'dependencies': [libthreads]}, {'name': 'timer', 'sources': ['timer.cpp']}, + {'name': 'timer-fail', 'sources': ['timer-fail.cpp'], 'should_fail': true}, {'name': 'timer-thread', 'sources': ['timer-thread.cpp']}, {'name': 'unique-fd', 'sources': ['unique-fd.cpp']}, {'name': 'utils', 'sources': ['utils.cpp']}, @@ -91,7 +92,7 @@ foreach test : public_tests link_with : test_libraries, include_directories : test_includes_public) - test(test['name'], exe) + test(test['name'], exe, should_fail : test.get('should_fail', false)) endforeach foreach test : internal_tests @@ -105,7 +106,7 @@ foreach test : internal_tests link_with : test_libraries, include_directories : test_includes_internal) - test(test['name'], exe) + test(test['name'], exe, should_fail : test.get('should_fail', false)) endforeach foreach test : internal_non_parallel_tests @@ -119,5 +120,7 @@ foreach test : internal_non_parallel_tests link_with : test_libraries, include_directories : test_includes_internal) - test(test['name'], exe, is_parallel : false) + test(test['name'], exe, + is_parallel : false, + should_fail : test.get('should_fail', false)) endforeach diff --git a/test/timer-fail.cpp b/test/timer-fail.cpp new file mode 100644 index 00000000..2c622ca3 --- /dev/null +++ b/test/timer-fail.cpp @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024, Ideas on Board Oy + * + * timer-fail.cpp - Threaded timer failure test + */ + +#include <chrono> +#include <iostream> + +#include <libcamera/base/event_dispatcher.h> +#include <libcamera/base/object.h> +#include <libcamera/base/thread.h> +#include <libcamera/base/timer.h> + +#include "test.h" + +using namespace libcamera; +using namespace std; +using namespace std::chrono_literals; + +class TimeoutHandler : public Object +{ +public: + TimeoutHandler() + : timer_(this), timeout_(false) + { + timer_.timeout.connect(this, &TimeoutHandler::timeoutHandler); + } + + void start() + { + timer_.start(100ms); + } + + bool timeout() const + { + return timeout_; + } + +private: + void timeoutHandler() + { + timeout_ = true; + } + + Timer timer_; + bool timeout_; +}; + +class TimerFailTest : public Test +{ +protected: + int init() + { + thread_.start(); + timeout_.moveToThread(&thread_); + + return TestPass; + } + + int run() + { + /* + * Test that the forbidden operation of starting the timer from + * another thread results in a failure. We need to interrupt the + * event dispatcher to make sure we don't succeed simply because + * the event dispatcher hasn't noticed the timer restart. + */ + timeout_.start(); + thread_.eventDispatcher()->interrupt(); + + this_thread::sleep_for(chrono::milliseconds(200)); + + /* + * The wrong start() call should result in an assertion in debug + * builds, and a timeout in release builds. The test is + * therefore marked in meson.build as expected to fail. We need + * to return TestPass in the unexpected (usually known as + * "fail") case, and TestFail otherwise. + */ + if (timeout_.timeout()) { + cout << "Timer start from wrong thread succeeded unexpectedly" + << endl; + return TestPass; + } + + return TestFail; + } + + void cleanup() + { + /* Must stop thread before destroying timeout. */ + thread_.exit(0); + thread_.wait(); + } + +private: + TimeoutHandler timeout_; + Thread thread_; +}; + +TEST_REGISTER(TimerFailTest) diff --git a/test/timer-thread.cpp b/test/timer-thread.cpp index 0bcd0d8c..4caf4e33 100644 --- a/test/timer-thread.cpp +++ b/test/timer-thread.cpp @@ -29,12 +29,6 @@ public: timer_.start(100ms); } - void restart() - { - timeout_ = false; - timer_.start(100ms); - } - bool timeout() const { return timeout_; @@ -74,22 +68,6 @@ protected: return TestFail; } - /* - * Test that starting the timer from another thread fails. We - * need to interrupt the event dispatcher to make sure we don't - * succeed simply because the event dispatcher hasn't noticed - * the timer restart. - */ - timeout_.restart(); - thread_.eventDispatcher()->interrupt(); - - this_thread::sleep_for(chrono::milliseconds(200)); - - if (timeout_.timeout()) { - cout << "Timer restart test failed" << endl; - return TestFail; - } - return TestPass; } |