/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2023, Ideas On Board Oy * * request_test.cpp - Request handling test */ #include #include #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 roles); void start(unsigned int minRequests, unsigned int maxRequests); void stop(); std::unique_ptr allocator_; std::vector> requests_; std::unique_ptr config_; std::shared_ptr 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 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(camera_)); allocator_->allocate(stream); const auto &buffers = allocator_->buffers(stream); for (const auto &buffer : buffers) { std::unique_ptr 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(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 roles{ StreamRole::Viewfinder }; configure(roles); camera_->requestCompleted.connect(dynamic_cast(this), &RequestTest::setExposureTime); start(4, 20); loop_ = new EventLoop(); loop_->exec(); stop(); delete loop_; EXPECT_EQ(testPass, true); }