libcamera/src/lc-compliance/main.cpp
Niklas Söderlund 02bc110857 lc-compliance: Add a libcamera compliance tool
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 <niklas.soderlund@ragnatech.se>
Acked-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Tested-by: Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com>
2021-04-12 10:48:56 +02:00

148 lines
2.7 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2020, Google Inc.
*
* main.cpp - lc-compliance - The libcamera compliance tool
*/
#include <iomanip>
#include <iostream>
#include <string.h>
#include <libcamera/libcamera.h>
#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<CameraManager> cm_;
std::shared_ptr<Camera> camera_;
};
Harness::Harness(const OptionsParser::Options &options)
: options_(options)
{
cm_ = std::make_unique<CameraManager>();
}
Harness::~Harness()
{
if (camera_) {
camera_->release();
camera_.reset();
}
cm_->stop();
}
int Harness::exec()
{
int ret = init();
if (ret)
return ret;
std::vector<Results> 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<Camera> &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;
}