summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/apps/lc-compliance/meson.build3
-rw-r--r--src/apps/lc-compliance/tests/request_test.cpp206
2 files changed, 208 insertions, 1 deletions
diff --git a/src/apps/lc-compliance/meson.build b/src/apps/lc-compliance/meson.build
index c53b2603..ae9596a8 100644
--- a/src/apps/lc-compliance/meson.build
+++ b/src/apps/lc-compliance/meson.build
@@ -16,7 +16,8 @@ lc_compliance_sources = files([
'main.cpp',
'tests/capture_test.cpp',
'tests/configure_test.cpp',
- 'tests/controls_test.cpp'
+ 'tests/controls_test.cpp',
+ 'tests/request_test.cpp'
])
lc_compliance_includes = ([
diff --git a/src/apps/lc-compliance/tests/request_test.cpp b/src/apps/lc-compliance/tests/request_test.cpp
new file mode 100644
index 00000000..957db590
--- /dev/null
+++ b/src/apps/lc-compliance/tests/request_test.cpp
@@ -0,0 +1,206 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2023, Ideas On Board Oy
+ *
+ * request_test.cpp - Request handling test
+ */
+
+#include <gtest/gtest.h>
+
+#include <libcamera/libcamera.h>
+
+#include "environment.h"
+
+#include "../common/event_loop.h"
+
+using namespace libcamera;
+
+class RequestTest : public testing::Test
+{
+public:
+ void setExposureTime(Request *request);
+
+protected:
+ void SetUp() override;
+ void TearDown() override;
+
+ bool controlSupported(const ControlId *) const;
+
+ void configure(Span<const StreamRole> roles);
+ void start(unsigned int minRequests, unsigned int maxRequests);
+ void stop();
+
+ std::unique_ptr<libcamera::FrameBufferAllocator> allocator_;
+ std::vector<std::unique_ptr<libcamera::Request>> requests_;
+ std::unique_ptr<libcamera::CameraConfiguration> config_;
+ std::shared_ptr<Camera> camera_;
+ EventLoop *loop_;
+
+ bool testPass;
+
+private:
+ unsigned int requestCount_;
+ unsigned int maxRequests_;
+ unsigned int minRequests_;
+};
+
+void RequestTest::SetUp()
+{
+ Environment *env = Environment::get();
+
+ camera_ = env->cm()->get(env->cameraId());
+
+ ASSERT_EQ(camera_->acquire(), 0);
+}
+
+void RequestTest::TearDown()
+{
+ if (!camera_)
+ return;
+
+ camera_->release();
+ camera_.reset();
+}
+
+bool RequestTest::controlSupported(const ControlId *id) const
+{
+ auto it = camera_->controls().find(id);
+ return it != camera_->controls().end();
+}
+
+void RequestTest::configure(Span<const StreamRole> roles)
+{
+ config_ = camera_->generateConfiguration(roles);
+ if (!config_) {
+ std::cout << "Roles not supported by camera" << std::endl;
+ GTEST_SKIP();
+ }
+
+ if (config_->validate() != CameraConfiguration::Valid) {
+ config_.reset();
+ FAIL() << "Configuration not valid";
+ }
+
+ if (camera_->configure(config_.get())) {
+ config_.reset();
+ FAIL() << "Failed to configure camera";
+ }
+
+ Stream *stream = config_->at(0).stream();
+ allocator_ = (std::make_unique<FrameBufferAllocator>(camera_));
+ allocator_->allocate(stream);
+
+ const auto &buffers = allocator_->buffers(stream);
+ for (const auto &buffer : buffers) {
+ std::unique_ptr<Request> request = camera_->createRequest();
+ request->addBuffer(stream, buffer.get(), 0);
+ requests_.push_back(std::move(request));
+ }
+}
+
+void RequestTest::start(unsigned int minRequests, unsigned int maxRequests)
+{
+ minRequests_ = minRequests;
+ maxRequests_ = maxRequests;
+ requestCount_ = 0;
+ testPass = true;
+
+ ASSERT_EQ(camera_->start(), 0) << "Failed to start camera";
+
+ for (const auto &request : requests_) {
+ if (camera_->queueRequest(request.get()))
+ return;
+ }
+}
+
+void RequestTest::stop()
+{
+ if (!config_ || !allocator_->allocated())
+ return;
+
+ camera_->stop();
+
+ camera_->requestCompleted.disconnect(this);
+
+ requests_.clear();
+
+ for (auto const &config : *config_) {
+ Stream *stream = config.stream();
+ allocator_->free(stream);
+ }
+}
+
+void RequestTest::setExposureTime(Request *request)
+{
+ static unsigned int metadataCounter = 0;
+ static int expectedResult = 0;
+
+ /* Requests completed after a 'stop()' are returned in error state. */
+ if (requestCount_ < maxRequests_) {
+ EXPECT_EQ(request->status(), Request::Status::RequestComplete)
+ << "Request didn't complete successfully";
+ }
+
+ if (expectedResult) {
+ std::cout << "CHECK METADATA" << std::endl;
+ const auto &metadata = request->metadata();
+ auto exposureTime = metadata.get<int>(controls::ExposureTime);
+ if (!exposureTime) {
+ std::cout << "NO EXPOSURE TIME" << std::endl;
+ --metadataCounter;
+ } else if (*exposureTime == expectedResult) {
+ std::cout << "FOUND EXPOSURE TIME: " << *exposureTime << std::endl;
+ requestCount_ = maxRequests_;
+ testPass = true;
+ } else if (--metadataCounter == 0) {
+ /*
+ * The requested exposureTime has not been set in
+ * less than the expected number of completed requests.
+ *
+ * Break the loop and set the test status to failure.
+ */
+ std::cout << "FOUND EXPOSURE TIME: " << *exposureTime << std::endl;
+ requestCount_ = maxRequests_;
+ }
+ }
+
+ /* Wait for a min number of requests to fill the pipeline. */
+ if (requestCount_++ > minRequests_ && !expectedResult) {
+ std::cout << "SET EXPOSURE TIEM TO 100" << std::endl;
+
+ testPass = false;
+ metadataCounter = 1;
+ expectedResult = 100;
+ request->controls().set(controls::ExposureTime, 100);
+ }
+
+ if (requestCount_ >= maxRequests_) {
+ loop_->exit(0);
+ return;
+ }
+
+ request->reuse(Request::ReuseBuffers);
+ if (camera_->queueRequest(request))
+ loop_->exit(-EINVAL);
+}
+
+TEST_F(RequestTest, ExposureTime)
+{
+ if (!controlSupported(&controls::ExposureTime))
+ GTEST_SKIP() << "ExposureTime control not supported";
+
+ const std::array<StreamRole, 1> roles{ StreamRole::Viewfinder };
+ configure(roles);
+
+ camera_->requestCompleted.connect(dynamic_cast<RequestTest *>(this),
+ &RequestTest::setExposureTime);
+
+ start(4, 20);
+
+ loop_ = new EventLoop();
+ loop_->exec();
+ stop();
+ delete loop_;
+
+ EXPECT_EQ(testPass, true);
+}