/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * ipa_interface_test.cpp - Test the IPA interface
 */

#include <fcntl.h>
#include <iostream>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <libcamera/ipa/vimc_ipa_proxy.h>

#include "libcamera/internal/device_enumerator.h"
#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/event_notifier.h"
#include "libcamera/internal/ipa_manager.h"
#include "libcamera/internal/ipa_module.h"
#include "libcamera/internal/pipeline_handler.h"
#include "libcamera/internal/process.h"
#include "libcamera/internal/thread.h"
#include "libcamera/internal/timer.h"

#include "test.h"

using namespace std;
using namespace libcamera;

class IPAInterfaceTest : public Test, public Object
{
public:
	IPAInterfaceTest()
		: trace_(ipa::vimc::IPAOperationNone), notifier_(nullptr), fd_(-1)
	{
	}

	~IPAInterfaceTest()
	{
		delete notifier_;
		ipa_.reset();
		ipaManager_.reset();
	}

protected:
	int init() override
	{
		ipaManager_ = make_unique<IPAManager>();

		/* Create a pipeline handler for vimc. */
		std::vector<PipelineHandlerFactory *> &factories =
			PipelineHandlerFactory::factories();
		for (PipelineHandlerFactory *factory : factories) {
			if (factory->name() == "PipelineHandlerVimc") {
				pipe_ = factory->create(nullptr);
				break;
			}
		}

		if (!pipe_) {
			cerr << "Vimc pipeline not found" << endl;
			return TestPass;
		}

		/* Create and open the communication FIFO. */
		int ret = mkfifo(ipa::vimc::VimcIPAFIFOPath.c_str(), S_IRUSR | S_IWUSR);
		if (ret) {
			ret = errno;
			cerr << "Failed to create IPA test FIFO at '"
			     << ipa::vimc::VimcIPAFIFOPath << "': " << strerror(ret)
			     << endl;
			return TestFail;
		}

		ret = open(ipa::vimc::VimcIPAFIFOPath.c_str(), O_RDONLY | O_NONBLOCK);
		if (ret < 0) {
			ret = errno;
			cerr << "Failed to open IPA test FIFO at '"
			     << ipa::vimc::VimcIPAFIFOPath << "': " << strerror(ret)
			     << endl;
			unlink(ipa::vimc::VimcIPAFIFOPath.c_str());
			return TestFail;
		}
		fd_ = ret;

		notifier_ = new EventNotifier(fd_, EventNotifier::Read, this);
		notifier_->activated.connect(this, &IPAInterfaceTest::readTrace);

		return TestPass;
	}

	int run() override
	{
		EventDispatcher *dispatcher = thread()->eventDispatcher();
		Timer timer;

		ipa_ = IPAManager::createIPA<ipa::vimc::IPAProxyVimc>(pipe_.get(), 0, 0);
		if (!ipa_) {
			cerr << "Failed to create VIMC IPA interface" << endl;
			return TestFail;
		}

		/* Test initialization of IPA module. */
		std::string conf = ipa_->configurationFile("vimc.conf");
		int ret = ipa_->init(IPASettings{ conf, "vimc" });
		if (ret < 0) {
			cerr << "IPA interface init() failed" << endl;
			return TestFail;
		}

		timer.start(1000);
		while (timer.isRunning() && trace_ != ipa::vimc::IPAOperationInit)
			dispatcher->processEvents();

		if (trace_ != ipa::vimc::IPAOperationInit) {
			cerr << "Failed to test IPA initialization sequence"
			     << endl;
			return TestFail;
		}

		/* Test start of IPA module. */
		ipa_->start();
		timer.start(1000);
		while (timer.isRunning() && trace_ != ipa::vimc::IPAOperationStart)
			dispatcher->processEvents();

		if (trace_ != ipa::vimc::IPAOperationStart) {
			cerr << "Failed to test IPA start sequence" << endl;
			return TestFail;
		}

		/* Test stop of IPA module. */
		ipa_->stop();
		timer.start(1000);
		while (timer.isRunning() && trace_ != ipa::vimc::IPAOperationStop)
			dispatcher->processEvents();

		if (trace_ != ipa::vimc::IPAOperationStop) {
			cerr << "Failed to test IPA stop sequence" << endl;
			return TestFail;
		}

		return TestPass;
	}

	void cleanup() override
	{
		close(fd_);
		unlink(ipa::vimc::VimcIPAFIFOPath.c_str());
	}

private:
	void readTrace(EventNotifier *notifier)
	{
		ssize_t s = read(notifier->fd(), &trace_, sizeof(trace_));
		if (s < 0) {
			int ret = errno;
			cerr << "Failed to read from IPA test FIFO at '"
			     << ipa::vimc::VimcIPAFIFOPath << "': " << strerror(ret)
			     << endl;
			trace_ = ipa::vimc::IPAOperationNone;
		}
	}

	ProcessManager processManager_;

	std::shared_ptr<PipelineHandler> pipe_;
	std::unique_ptr<ipa::vimc::IPAProxyVimc> ipa_;
	std::unique_ptr<IPAManager> ipaManager_;
	enum ipa::vimc::IPAOperationCode trace_;
	EventNotifier *notifier_;
	int fd_;
};

TEST_REGISTER(IPAInterfaceTest)
t/tree/?h=multicontext/rpi/v3&amp;id=3e743ee8ebb13cadbc18175ced0462e99054d0d0'>root</a>/<a href='/libcamera/jmondi/libcamera.git/tree/utils?h=multicontext/rpi/v3&amp;id=3e743ee8ebb13cadbc18175ced0462e99054d0d0'>utils</a>/<a href='/libcamera/jmondi/libcamera.git/tree/utils/ipc?h=multicontext/rpi/v3&amp;id=3e743ee8ebb13cadbc18175ced0462e99054d0d0'>ipc</a>/<a href='/libcamera/jmondi/libcamera.git/tree/utils/ipc/mojo?h=multicontext/rpi/v3&amp;id=3e743ee8ebb13cadbc18175ced0462e99054d0d0'>mojo</a>/<a href='/libcamera/jmondi/libcamera.git/tree/utils/ipc/mojo/public?h=multicontext/rpi/v3&amp;id=3e743ee8ebb13cadbc18175ced0462e99054d0d0'>public</a>/<a href='/libcamera/jmondi/libcamera.git/tree/utils/ipc/mojo/public/tools?h=multicontext/rpi/v3&amp;id=3e743ee8ebb13cadbc18175ced0462e99054d0d0'>tools</a>/<a href='/libcamera/jmondi/libcamera.git/tree/utils/ipc/mojo/public/tools/BUILD.gn?h=multicontext/rpi/v3&amp;id=3e743ee8ebb13cadbc18175ced0462e99054d0d0'>BUILD.gn</a></div><div class='content'>blob: 4c68350b3996cde21af7eb7127eb182d7101e848 (<a href='/libcamera/jmondi/libcamera.git/plain/utils/ipc/mojo/public/tools/BUILD.gn?h=multicontext/rpi/v3&amp;id=3e743ee8ebb13cadbc18175ced0462e99054d0d0'>plain</a>)
<table summary='blob content' class='blob'>
<tr><td class='linenumbers'><pre><a id='n1' href='#n1'>1</a>
<a id='n2' href='#n2'>2</a>
<a id='n3' href='#n3'>3</a>
<a id='n4' href='#n4'>4</a>
<a id='n5' href='#n5'>5</a>
<a id='n6' href='#n6'>6</a>
<a id='n7' href='#n7'>7</a>
<a id='n8' href='#n8'>8</a>
<a id='n9' href='#n9'>9</a>
<a id='n10' href='#n10'>10</a>
<a id='n11' href='#n11'>11</a>
<a id='n12' href='#n12'>12</a>
<a id='n13' href='#n13'>13</a>
<a id='n14' href='#n14'>14</a>
<a id='n15' href='#n15'>15</a>
<a id='n16' href='#n16'>16</a>
<a id='n17' href='#n17'>17</a>
<a id='n18' href='#n18'>18</a>
</pre></td>
<td class='lines'><pre><code># Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# The main target used to aggregate all unit tests for Python-based Mojo tools.
# This is used to generate a complete isolate which can be pushed to bots to run
# the tests.
group(&quot;mojo_python_unittests&quot;) {
  data = [
    &quot;run_all_python_unittests.py&quot;,
    &quot;//testing/scripts/common.py&quot;,
    &quot;//testing/scripts/run_isolated_script_test.py&quot;,
    &quot;//testing/test_env.py&quot;,
    &quot;//testing/xvfb.py&quot;,
  ]
  deps = [ &quot;//mojo/public/tools/mojom/mojom:tests&quot; ]
  data_deps = [ &quot;//third_party/catapult/third_party/typ/&quot; ]
}
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.1</a> (<a href='https://git-scm.com/'>git 2.18.0</a>) at 2025-03-04 16:01:34 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>