From 02bc1108578e8b8eb68fa7d9ae3eeea558723931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Wed, 27 Jan 2021 01:23:51 +0100 Subject: lc-compliance: Add a libcamera compliance tool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a compliance tool to ease testing of cameras. In contrast to the unit-tests under test/ that aims to test the internal components of libcamera the compliance tool aims to test application use-cases and to some extent the public API. This change adds the boilerplate code of a simple framework for the creation of tests. The tests aim both to demonstrate the tool and to catch real problems. The tests added are: - Test that if one queues exactly N requests to a camera exactly N requests are eventually completed. - Test that a configured camera can be started and stopped multiple times in an attempt to exercise cleanup code paths otherwise not often tested with 'cam' for example. Signed-off-by: Niklas Söderlund Acked-by: Kieran Bingham Tested-by: Kieran Bingham Reviewed-by: Laurent Pinchart Tested-by: Jean-Michel Hautbois --- src/lc-compliance/main.cpp | 148 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 src/lc-compliance/main.cpp (limited to 'src/lc-compliance/main.cpp') diff --git a/src/lc-compliance/main.cpp b/src/lc-compliance/main.cpp new file mode 100644 index 00000000..54cee54a --- /dev/null +++ b/src/lc-compliance/main.cpp @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * main.cpp - lc-compliance - The libcamera compliance tool + */ + +#include +#include +#include + +#include + +#include "../cam/options.h" +#include "tests.h" + +using namespace libcamera; + +enum { + OptCamera = 'c', + OptHelp = 'h', +}; + +class Harness +{ +public: + Harness(const OptionsParser::Options &options); + ~Harness(); + + int exec(); + +private: + int init(); + void listCameras(); + + OptionsParser::Options options_; + std::unique_ptr cm_; + std::shared_ptr camera_; +}; + +Harness::Harness(const OptionsParser::Options &options) + : options_(options) +{ + cm_ = std::make_unique(); +} + +Harness::~Harness() +{ + if (camera_) { + camera_->release(); + camera_.reset(); + } + + cm_->stop(); +} + +int Harness::exec() +{ + int ret = init(); + if (ret) + return ret; + + std::vector results; + + results.push_back(testSingleStream(camera_)); + + for (const Results &result : results) { + ret = result.summary(); + if (ret) + return ret; + } + + return 0; +} + +int Harness::init() +{ + int ret = cm_->start(); + if (ret) { + std::cout << "Failed to start camera manager: " + << strerror(-ret) << std::endl; + return ret; + } + + if (!options_.isSet(OptCamera)) { + std::cout << "No camera specified, available cameras:" << std::endl; + listCameras(); + return -ENODEV; + } + + const std::string &cameraId = options_[OptCamera]; + camera_ = cm_->get(cameraId); + if (!camera_) { + std::cout << "Camera " << cameraId << " not found, available cameras:" << std::endl; + listCameras(); + return -ENODEV; + } + + if (camera_->acquire()) { + std::cout << "Failed to acquire camera" << std::endl; + return -EINVAL; + } + + std::cout << "Using camera " << cameraId << std::endl; + + return 0; +} + +void Harness::listCameras() +{ + for (const std::shared_ptr &cam : cm_->cameras()) + std::cout << "- " << cam.get()->id() << std::endl; +} + +static int parseOptions(int argc, char **argv, OptionsParser::Options *options) +{ + OptionsParser parser; + parser.addOption(OptCamera, OptionString, + "Specify which camera to operate on, by id", "camera", + ArgumentRequired, "camera"); + parser.addOption(OptHelp, OptionNone, "Display this help message", + "help"); + + *options = parser.parse(argc, argv); + if (!options->valid()) + return -EINVAL; + + if (options->isSet(OptHelp)) { + parser.usage(); + return -EINTR; + } + + return 0; +} + +int main(int argc, char **argv) +{ + OptionsParser::Options options; + int ret = parseOptions(argc, argv, &options); + if (ret == -EINTR) + return EXIT_SUCCESS; + if (ret < 0) + return EXIT_FAILURE; + + Harness harness(options); + + return harness.exec() ? EXIT_FAILURE : EXIT_SUCCESS; +} -- cgit v1.2.1