summaryrefslogtreecommitdiff
path: root/src/ipa/raspberrypi/controller/pwl.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipa/raspberrypi/controller/pwl.hpp')
0 files changed, 0 insertions, 0 deletions
0' href='#n80'>80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * message.cpp - Messages test
 */

#include <chrono>
#include <iostream>
#include <thread>

#include "libcamera/internal/message.h"
#include "libcamera/internal/thread.h"

#include "test.h"

using namespace std;
using namespace libcamera;

class MessageReceiver : public Object
{
public:
	enum Status {
		NoMessage,
		InvalidThread,
		MessageReceived,
	};

	MessageReceiver()
		: status_(NoMessage)
	{
	}

	Status status() const { return status_; }
	void reset() { status_ = NoMessage; }

protected:
	void message(Message *msg)
	{
		if (msg->type() != Message::None) {
			Object::message(msg);
			return;
		}

		if (thread() != Thread::current())
			status_ = InvalidThread;
		else
			status_ = MessageReceived;
	}

private:
	Status status_;
};

class SlowMessageReceiver : public Object
{
protected:
	void message(Message *msg)
	{
		if (msg->type() != Message::None) {
			Object::message(msg);
			return;
		}

		/*
		 * 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.
		 */
		this_thread::sleep_for(chrono::milliseconds(100));
	}
};

class MessageTest : public Test
{
protected:
	int run()
	{
		Message::Type msgType[2] = {
			Message::registerMessageType(),
			Message::registerMessageType(),
		};

		if (msgType[0] != Message::UserMessage ||
		    msgType[1] != Message::UserMessage + 1) {
			cout << "Failed to register message types" << endl;
			return TestFail;
		}

		MessageReceiver receiver;
		receiver.moveToThread(&thread_);

		thread_.start();

		receiver.postMessage(std::make_unique<Message>(Message::None));

		this_thread::sleep_for(chrono::milliseconds(100));

		switch (receiver.status()) {
		case MessageReceiver::NoMessage:
			cout << "No message received" << endl;
			return TestFail;
		case MessageReceiver::InvalidThread:
			cout << "Message received in incorrect thread" << endl;
			return TestFail;
		default:
			break;
		}

		/*
		 * Test for races between message delivery and object deletion.
		 * Failures result in assertion errors, there is no need for
		 * explicit checks.
		 */
		SlowMessageReceiver *slowReceiver = new SlowMessageReceiver();
		slowReceiver->moveToThread(&thread_);
		slowReceiver->postMessage(std::make_unique<Message>(Message::None));

		this_thread::sleep_for(chrono::milliseconds(10));

		delete slowReceiver;

		return TestPass;
	}

	void cleanup()
	{
		thread_.exit(0);
		thread_.wait();
	}

private:
	Thread thread_;
};

TEST_REGISTER(MessageTest)