summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/meson.build9
-rw-r--r--test/timer-fail.cpp103
-rw-r--r--test/timer-thread.cpp22
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;
}