/* 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; }