From patchwork Sun Jan 21 03:59:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 19430 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 73EAEC32BE for ; Sun, 21 Jan 2024 04:00:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2C63562945; Sun, 21 Jan 2024 05:00:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705809605; bh=v9GuiS/h4iMeflUS4bTI8gyEEBPHzrxo/e9UcfRjy78=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=plR/8+egEhb/VIFPArgVM0YAib0/1LKTeFyuK5m3oHY/SPcCxLmtGPxjyOGdznB4J PxbZM27DvpOnpE58EFvZEk9lNo+nlSmwFf5lNbPbf3ouLTKce8GvX4hNySS0NQh+F5 KAwKRFGv2fM8m0dOpgWncBVNenE0p3cteK8+4UwAuI2mGDMGRWOhl4kHWqXG9H9xhx 3VcbUYWudTinfiDwBxvXRpqC5IXpjz1+bnLCFt6x0Vw+3Djdn8WGDA1SVIJhHlcGrk awOVfVJovHhSAVQ0FSFLfKXffrC3QXCQadG+yoWrTdGGyCTqOGiHAPloCJF/xIRVwD IC8HzTp86TdhQ== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D1CA66294C for ; Sun, 21 Jan 2024 04:59:57 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="LWQHChuL"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (89-27-53-110.bb.dnainternet.fi [89.27.53.110]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id CF4C513C5; Sun, 21 Jan 2024 04:58:45 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1705809526; bh=v9GuiS/h4iMeflUS4bTI8gyEEBPHzrxo/e9UcfRjy78=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LWQHChuLjZq1rsNpUBrO3E7V9qnx5XKDyEJhSrGGEwcw8zZDWkvyyQjY9qF1XKHAN ongqn6BUmo6s5/4+F5mXBhH7fAkDn+yWTS4jsg5qQremBCnMPfezz0itF6PnV2BCas FO39RYiJ7z8K6QUbUqJW4bsrmAF/frX6W7IKV0RA= To: libcamera-devel@lists.libcamera.org Date: Sun, 21 Jan 2024 05:59:45 +0200 Message-ID: <20240121035948.4226-10-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240121035948.4226-1-laurent.pinchart@ideasonboard.com> References: <20240121035948.4226-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 09/12] test: timer-thread: Move timer start from wrong thread to separate test X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Starting a timer from the wrong thread is expected to fail, and we test this in the timer-thread unit test. This is however not something that a caller is allowed to do, and libcamera will get assertion failures to catch this invalid usage. The unit test will then fail. To prepare for this, split the unit test in two, with a test that is expected by meson to succeed, and one that is expected to fail. The assertion will then cause an expected failure, making the test suite succeed. Signed-off-by: Laurent Pinchart --- test/meson.build | 9 ++-- test/timer-fail.cpp | 101 ++++++++++++++++++++++++++++++++++++++++++ test/timer-thread.cpp | 22 --------- 3 files changed, 107 insertions(+), 25 deletions(-) create mode 100644 test/timer-fail.cpp diff --git a/test/meson.build b/test/meson.build index 189e1428485a..8b6057d4e800 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 000000000000..e9a3b1b61bcb --- /dev/null +++ b/test/timer-fail.cpp @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024, Ideas on Board Oy + * + * timer-fail.cpp - Threaded timer failure test + */ + +#include +#include + +#include +#include +#include +#include + +#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)); + + /* + * Meson expects this test to fail, so 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 0bcd0d8ce194..4caf4e33b2ba 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; }