From 84ad104499d9efc0253dae1a60ee070ed375ad95 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 20 Oct 2022 00:44:55 +0300 Subject: Move test applications to src/apps/ The cam and qcam test application share code, currently through a crude hack that references the cam source files directly from the qcam meson.build file. To prepare for the introduction of hosting that code in a static library, move all applications to src/apps/. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham --- src/apps/lc-compliance/main.cpp | 193 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 src/apps/lc-compliance/main.cpp (limited to 'src/apps/lc-compliance/main.cpp') diff --git a/src/apps/lc-compliance/main.cpp b/src/apps/lc-compliance/main.cpp new file mode 100644 index 00000000..7eb52ae4 --- /dev/null +++ b/src/apps/lc-compliance/main.cpp @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * Copyright (C) 2021, Collabora Ltd. + * + * main.cpp - lc-compliance - The libcamera compliance tool + */ + +#include +#include +#include + +#include + +#include + +#include "environment.h" +#include "../cam/options.h" + +using namespace libcamera; + +enum { + OptCamera = 'c', + OptList = 'l', + OptFilter = 'f', + OptHelp = 'h', +}; + +/* + * Make asserts act like exceptions, otherwise they only fail (or skip) the + * current function. From gtest documentation: + * https://google.github.io/googletest/advanced.html#asserting-on-subroutines-with-an-exception + */ +class ThrowListener : public testing::EmptyTestEventListener +{ + void OnTestPartResult(const testing::TestPartResult &result) override + { + if (result.type() == testing::TestPartResult::kFatalFailure || + result.type() == testing::TestPartResult::kSkip) + throw testing::AssertionException(result); + } +}; + +static void listCameras(CameraManager *cm) +{ + for (const std::shared_ptr &cam : cm->cameras()) + std::cout << "- " << cam.get()->id() << std::endl; +} + +static int initCamera(CameraManager *cm, OptionsParser::Options options) +{ + std::shared_ptr camera; + + 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(cm); + 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(cm); + return -ENODEV; + } + + Environment::get()->setup(cm, cameraId); + + std::cout << "Using camera " << cameraId << std::endl; + + return 0; +} + +static int initGtestParameters(char *arg0, OptionsParser::Options options) +{ + const std::map gtestFlags = { { "list", "--gtest_list_tests" }, + { "filter", "--gtest_filter" } }; + + int argc = 0; + std::string filterParam; + + /* + * +2 to have space for both the 0th argument that is needed but not + * used and the null at the end. + */ + char **argv = new char *[(gtestFlags.size() + 2)]; + if (!argv) + return -ENOMEM; + + argv[0] = arg0; + argc++; + + if (options.isSet(OptList)) { + argv[argc] = const_cast(gtestFlags.at("list").c_str()); + argc++; + } + + if (options.isSet(OptFilter)) { + /* + * The filter flag needs to be passed as a single parameter, in + * the format --gtest_filter=filterStr + */ + filterParam = gtestFlags.at("filter") + "=" + + static_cast(options[OptFilter]); + + argv[argc] = const_cast(filterParam.c_str()); + argc++; + } + + argv[argc] = nullptr; + + ::testing::InitGoogleTest(&argc, argv); + + delete[] argv; + + return 0; +} + +static int initGtest(char *arg0, OptionsParser::Options options) +{ + int ret = initGtestParameters(arg0, options); + if (ret) + return ret; + + testing::UnitTest::GetInstance()->listeners().Append(new ThrowListener); + + return 0; +} + +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(OptList, OptionNone, "List all tests and exit", "list"); + parser.addOption(OptFilter, OptionString, + "Specify which tests to run", "filter", + ArgumentRequired, "filter"); + 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(); + std::cerr << "Further options from Googletest can be passed as environment variables" + << std::endl; + 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; + + std::unique_ptr cm = std::make_unique(); + + /* No need to initialize the camera if we'll just list tests */ + if (!options.isSet(OptList)) { + ret = initCamera(cm.get(), options); + if (ret) + return ret; + } + + ret = initGtest(argv[0], options); + if (ret) + return ret; + + ret = RUN_ALL_TESTS(); + + if (!options.isSet(OptList)) + cm->stop(); + + return ret; +} -- cgit v1.2.1