diff options
Diffstat (limited to 'test/message.cpp')
-rw-r--r-- | test/message.cpp | 79 |
1 files changed, 57 insertions, 22 deletions
diff --git a/test/message.cpp b/test/message.cpp index 478bc79d..19e6646d 100644 --- a/test/message.cpp +++ b/test/message.cpp @@ -2,15 +2,18 @@ /* * Copyright (C) 2019, Google Inc. * - * message.cpp - Messages test + * Messages test */ #include <chrono> #include <iostream> +#include <memory> #include <thread> -#include "message.h" -#include "thread.h" +#include <libcamera/base/message.h> +#include <libcamera/base/object.h> +#include <libcamera/base/thread.h> + #include "test.h" using namespace std; @@ -25,8 +28,8 @@ public: MessageReceived, }; - MessageReceiver() - : status_(NoMessage) + MessageReceiver(Object *parent = nullptr) + : Object(parent), status_(NoMessage) { } @@ -51,23 +54,43 @@ private: Status status_; }; -class SlowMessageReceiver : public Object +class RecursiveMessageReceiver : public Object { +public: + RecursiveMessageReceiver() + : child_(this), success_(false) + { + } + + bool success() const { return success_; } + protected: - void message(Message *msg) + void message([[maybe_unused]] Message *msg) { if (msg->type() != Message::None) { Object::message(msg); return; } + child_.postMessage(std::make_unique<Message>(Message::None)); + /* - * Don't access any member of the object here (including the - * vtable) as the object will be deleted by the main thread - * while we're sleeping. + * If the child has already received the message, something is + * wrong. */ - this_thread::sleep_for(chrono::milliseconds(100)); + if (child_.status() != MessageReceiver::NoMessage) + return; + + Thread::current()->dispatchMessages(Message::None); + + /* The child should now have received the message. */ + if (child_.status() == MessageReceiver::MessageReceived) + success_ = true; } + +private: + MessageReceiver child_; + bool success_; }; class MessageTest : public Test @@ -86,16 +109,19 @@ protected: return TestFail; } - MessageReceiver receiver; - receiver.moveToThread(&thread_); + MessageReceiver *receiver = new MessageReceiver(); + receiver->moveToThread(&thread_); thread_.start(); - receiver.postMessage(std::make_unique<Message>(Message::None)); + receiver->postMessage(std::make_unique<Message>(Message::None)); this_thread::sleep_for(chrono::milliseconds(100)); - switch (receiver.status()) { + MessageReceiver::Status status = receiver->status(); + receiver->deleteLater(); + + switch (status) { case MessageReceiver::NoMessage: cout << "No message received" << endl; return TestFail; @@ -107,17 +133,26 @@ protected: } /* - * Test for races between message delivery and object deletion. - * Failures result in assertion errors, there is no need for - * explicit checks. + * Test recursive calls to Thread::dispatchMessages(). Messages + * should be delivered correctly, without crashes or memory + * leaks. Two messages need to be posted to ensure we don't only + * test the simple case of a queue containing a single message. */ - SlowMessageReceiver *slowReceiver = new SlowMessageReceiver(); - slowReceiver->moveToThread(&thread_); - slowReceiver->postMessage(std::make_unique<Message>(Message::None)); + RecursiveMessageReceiver *recursiveReceiver = new RecursiveMessageReceiver(); + recursiveReceiver->moveToThread(&thread_); + + recursiveReceiver->postMessage(std::make_unique<Message>(Message::None)); + recursiveReceiver->postMessage(std::make_unique<Message>(Message::UserMessage)); this_thread::sleep_for(chrono::milliseconds(10)); - delete slowReceiver; + bool success = recursiveReceiver->success(); + recursiveReceiver->deleteLater(); + + if (!success) { + cout << "Recursive message delivery failed" << endl; + return TestFail; + } return TestPass; } |