Formatting

This commit is contained in:
2025-07-09 10:44:23 +02:00
parent 6b79fcc552
commit 3426ca9d32
5 changed files with 299 additions and 257 deletions

View File

@@ -2,10 +2,10 @@
// Copyright (C) 2021 Contributors to the SLS Detector Package // Copyright (C) 2021 Contributors to the SLS Detector Package
#include "CommandLineOptions.h" #include "CommandLineOptions.h"
#include "sls/sls_detector_defs.h"
#include "sls/versionAPI.h"
#include "sls/ToString.h" #include "sls/ToString.h"
#include "sls/logger.h" #include "sls/logger.h"
#include "sls/sls_detector_defs.h"
#include "sls/versionAPI.h"
#include <csignal> #include <csignal>
#include <cstring> #include <cstring>
@@ -40,12 +40,10 @@ ParsedOptions CommandLineOptions::parse(int argc, char *argv[]) {
case 'h': case 'h':
handleCommonOption(opt, optarg, base); handleCommonOption(opt, optarg, base);
return base; // exit after version/help return base; // exit after version/help
case 'p': case 'p':
case 'u': case 'u':
handleCommonOption(opt, optarg, base); handleCommonOption(opt, optarg, base);
break; break;
case 'c': case 'c':
case 'n': case 'n':
case 't': case 't':
@@ -60,10 +58,12 @@ ParsedOptions CommandLineOptions::parse(int argc, char *argv[]) {
if (optind < argc) { if (optind < argc) {
// deprecated and current options => invalid // deprecated and current options => invalid
if (base.port != DEFAULT_TCP_RX_PORTNO || if (base.port != DEFAULT_TCP_RX_PORTNO || multi.numReceivers != 1 ||
multi.numReceivers != 1 || frame.numReceivers != 1 || multi.callbackEnabled != false || frame.printHeaders != false) { frame.numReceivers != 1 || multi.callbackEnabled != false ||
LOG(sls::logWARNING) frame.printHeaders != false) {
<< "Cannot use both deprecated options and the valid options simultaneously. Please move away from the deprecated options.\n"; LOG(sls::logWARNING) << "Cannot use both deprecated options and "
"the valid options simultaneously. Please "
"move away from the deprecated options.\n";
} }
// unsupported deprecated arguments // unsupported deprecated arguments
@@ -74,7 +74,6 @@ ParsedOptions CommandLineOptions::parse(int argc, char *argv[]) {
// parse deprecated arguments // parse deprecated arguments
std::vector<std::string> args(argv, argv + argc); std::vector<std::string> args(argv, argv + argc);
auto [p, n, o] = ParseDeprecated(args); auto [p, n, o] = ParseDeprecated(args);
// set options // set options
base.port = p; base.port = p;
if (appType_ == AppType::MultiReceiver) { if (appType_ == AppType::MultiReceiver) {
@@ -113,9 +112,9 @@ ParsedOptions CommandLineOptions::parse(int argc, char *argv[]) {
std::vector<option> CommandLineOptions::buildOptionList() const { std::vector<option> CommandLineOptions::buildOptionList() const {
std::vector<option> opts = { std::vector<option> opts = {
{"version", no_argument, nullptr, 'v'}, {"version", no_argument, nullptr, 'v'},
{"help", no_argument, nullptr, 'h'},
{"port", required_argument, nullptr, 'p'}, {"port", required_argument, nullptr, 'p'},
{"uid", required_argument, nullptr, 'u'}, {"uid", required_argument, nullptr, 'u'},
{"help", no_argument, nullptr, 'h'},
}; };
switch (appType_) { switch (appType_) {
case AppType::SingleReceiver: case AppType::SingleReceiver:
@@ -135,7 +134,7 @@ std::vector<option> CommandLineOptions::buildOptionList() const {
} }
std::string CommandLineOptions::buildOptString() const { std::string CommandLineOptions::buildOptString() const {
std::string optstr = "vp:u:h"; std::string optstr = "vhp:u:";
if (appType_ == AppType::MultiReceiver || if (appType_ == AppType::MultiReceiver ||
appType_ == AppType::FrameSynchronizer) appType_ == AppType::FrameSynchronizer)
optstr += "cn:"; optstr += "cn:";
@@ -241,8 +240,10 @@ void CommandLineOptions::handleAppSpecificOption(int opt, const char *optarg,
} }
} }
/* maintain backward compatibility of [start port] [num receivers] [optional arg] */ /* maintain backward compatibility of [start port] [num receivers] [optional
std::tuple<uint16_t, uint16_t, bool> CommandLineOptions::ParseDeprecated(const std::vector<std::string> &args) { * arg] */
std::tuple<uint16_t, uint16_t, bool>
CommandLineOptions::ParseDeprecated(const std::vector<std::string> &args) {
size_t nargs = args.size(); size_t nargs = args.size();
if (nargs != 1 && nargs != 3 && nargs != 4) { if (nargs != 1 && nargs != 3 && nargs != 4) {
@@ -251,7 +252,7 @@ std::tuple<uint16_t, uint16_t, bool> CommandLineOptions::ParseDeprecated(const s
LOG(sls::logWARNING) LOG(sls::logWARNING)
<< "Deprecated options will be removed in future versions. " << "Deprecated options will be removed in future versions. "
"Please use the new options.\n"; "Please use the new options.\n";
// default deprecated values // default deprecated values
if (nargs == 1) { if (nargs == 1) {
@@ -334,7 +335,7 @@ std::string CommandLineOptions::getHelpMessage() const {
void CommandLineOptions::setupSignalHandler(int signal, void (*handler)(int)) { void CommandLineOptions::setupSignalHandler(int signal, void (*handler)(int)) {
// Catch signal SIGINT to close files and call destructors properly // Catch signal SIGINT to close files and call destructors properly
struct sigaction sa{}; struct sigaction sa {};
sa.sa_handler = handler; sa.sa_handler = handler;
sigemptyset(&sa.sa_mask); // dont block additional signals sigemptyset(&sa.sa_mask); // dont block additional signals
sa.sa_flags = 0; sa.sa_flags = 0;

View File

@@ -5,16 +5,11 @@
#include <cstdint> #include <cstdint>
#include <getopt.h> #include <getopt.h>
#include <string> #include <string>
#include <tuple>
#include <variant> #include <variant>
#include <vector> #include <vector>
#include <tuple>
enum class AppType {
MultiReceiver,
SingleReceiver,
FrameSynchronizer
};
enum class AppType { MultiReceiver, SingleReceiver, FrameSynchronizer };
struct CommonOptions { struct CommonOptions {
uint16_t port = -1; uint16_t port = -1;
@@ -33,7 +28,8 @@ struct FrameSyncOptions : CommonOptions {
bool printHeaders = false; bool printHeaders = false;
}; };
using ParsedOptions = std::variant<CommonOptions, MultiReceiverOptions, FrameSyncOptions>; using ParsedOptions =
std::variant<CommonOptions, MultiReceiverOptions, FrameSyncOptions>;
class CommandLineOptions { class CommandLineOptions {
public: public:
@@ -45,7 +41,9 @@ class CommandLineOptions {
std::string getHelpMessage() const; std::string getHelpMessage() const;
static void setupSignalHandler(int signal, void (*handler)(int)); static void setupSignalHandler(int signal, void (*handler)(int));
static void setEffectiveUID(uid_t uid); static void setEffectiveUID(uid_t uid);
static std::tuple<uint16_t, uint16_t, bool> ParseDeprecated(const std::vector<std::string> &args); static std::tuple<uint16_t, uint16_t, bool>
ParseDeprecated(const std::vector<std::string> &args);
private: private:
AppType appType_; AppType appType_;
std::vector<option> buildOptionList() const; std::vector<option> buildOptionList() const;
@@ -60,8 +58,5 @@ class CommandLineOptions {
MultiReceiverOptions &multi, MultiReceiverOptions &multi,
FrameSyncOptions &frame); FrameSyncOptions &frame);
static constexpr uint16_t MAX_RECEIVERS = 1000; static constexpr uint16_t MAX_RECEIVERS = 1000;
}; };

View File

@@ -549,18 +549,19 @@ int main(int argc, char *argv[]) {
<< "Thread " << i << " [ Tid: " << gettid() << ']'; << "Thread " << i << " [ Tid: " << gettid() << ']';
try { try {
sls::Receiver receiver(port); sls::Receiver receiver(port);
receiver.registerCallBackStartAcquisition(StartAcquisitionCallback, receiver.registerCallBackStartAcquisition(
user_data); StartAcquisitionCallback, user_data);
receiver.registerCallBackAcquisitionFinished( receiver.registerCallBackAcquisitionFinished(
AcquisitionFinishedCallback, user_data); AcquisitionFinishedCallback, user_data);
receiver.registerCallBackRawDataReady(GetDataCallback, user_data); receiver.registerCallBackRawDataReady(GetDataCallback,
user_data);
/** - as long as no Ctrl+C */ /** - as long as no Ctrl+C */
// each child shares the common semaphore // each child shares the common semaphore
sem_wait(semaphore); sem_wait(semaphore);
} catch (...) { } catch (...) {
LOG(sls::logINFOBLUE) LOG(sls::logINFOBLUE)
<< "Exiting Thread " << i << " [ Tid: " << gettid() << " ]"; << "Exiting Thread " << i << " [ Tid: " << gettid() << " ]";
for (auto &s : semaphores) for (auto &s : semaphores)
sem_destroy(&s); sem_destroy(&s);
cleanup(); cleanup();
@@ -569,7 +570,7 @@ int main(int argc, char *argv[]) {
std::exit(EXIT_FAILURE); std::exit(EXIT_FAILURE);
} }
LOG(sls::logINFOBLUE) LOG(sls::logINFOBLUE)
<< "Exiting Thread " << i << " [ Tid: " << gettid() << " ]"; << "Exiting Thread " << i << " [ Tid: " << gettid() << " ]";
sem_destroy(semaphore); sem_destroy(semaphore);
}); });
} }

View File

@@ -38,7 +38,7 @@ int main(int argc, char *argv[]) {
} catch (sls::RuntimeError &e) { } catch (sls::RuntimeError &e) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
auto& o = std::get<CommonOptions>(opts); auto &o = std::get<CommonOptions>(opts);
if (o.versionRequested || o.helpRequested) { if (o.versionRequested || o.helpRequested) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@@ -1,283 +1,328 @@
// SPDX-License-Identifier: LGPL-3.0-or-other // SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package // Copyright (C) 2021 Contributors to the SLS Detector Package
#include "catch.hpp"
#include "CommandLineOptions.h" #include "CommandLineOptions.h"
#include "catch.hpp"
#include "sls/versionAPI.h" #include "sls/versionAPI.h"
#include <unistd.h> #include <unistd.h>
namespace sls { namespace sls {
template<typename T, typename U> template <typename T, typename U> constexpr bool is_type() {
constexpr bool is_type() { return std::is_same_v<std::decay_t<U>, T>;
return std::is_same_v<std::decay_t<U>, T>; }
}
TEST_CASE("CommandLineOption construction", "[.rxcmdcall]") { TEST_CASE("CommandLineOption construction", "[.rxcmdcall]") {
CommandLineOptions s(AppType::SingleReceiver); CommandLineOptions s(AppType::SingleReceiver);
REQUIRE(s.getTypeString() == "slsReceiver"); REQUIRE(s.getTypeString() == "slsReceiver");
REQUIRE(s.getVersion() == std::string("slsReceiver Version: ") + APIRECEIVER); REQUIRE(s.getVersion() ==
REQUIRE_NOTHROW(s.getHelpMessage()); std::string("slsReceiver Version: ") + APIRECEIVER);
REQUIRE_NOTHROW(s.getHelpMessage());
CommandLineOptions m(AppType::MultiReceiver); CommandLineOptions m(AppType::MultiReceiver);
REQUIRE(m.getTypeString() == "slsMultiReceiver"); REQUIRE(m.getTypeString() == "slsMultiReceiver");
REQUIRE(m.getVersion() == std::string("slsMultiReceiver Version: ") + APIRECEIVER); REQUIRE(m.getVersion() ==
REQUIRE_NOTHROW(m.getHelpMessage()); std::string("slsMultiReceiver Version: ") + APIRECEIVER);
REQUIRE_NOTHROW(m.getHelpMessage());
CommandLineOptions f(AppType::FrameSynchronizer); CommandLineOptions f(AppType::FrameSynchronizer);
REQUIRE(f.getTypeString() == "slsFrameSynchronizer"); REQUIRE(f.getTypeString() == "slsFrameSynchronizer");
REQUIRE(f.getVersion() == std::string("slsFrameSynchronizer Version: ") + APIRECEIVER); REQUIRE(f.getVersion() ==
REQUIRE_NOTHROW(f.getHelpMessage()); std::string("slsFrameSynchronizer Version: ") + APIRECEIVER);
} REQUIRE_NOTHROW(f.getHelpMessage());
}
TEST_CASE("Validate common options", "[.rxcmdcall]") { TEST_CASE("Validate common options", "[.rxcmdcall]") {
std::string uidStr = std::to_string(getuid()); std::string uidStr = std::to_string(getuid());
for (auto app : {AppType::SingleReceiver, AppType::MultiReceiver, AppType::FrameSynchronizer}) { for (auto app : {AppType::SingleReceiver, AppType::MultiReceiver,
CommandLineOptions s(app); AppType::FrameSynchronizer}) {
REQUIRE_NOTHROW(s.parse({})); CommandLineOptions s(app);
REQUIRE_NOTHROW(s.parse({"", "-v"})); REQUIRE_NOTHROW(s.parse({}));
REQUIRE_NOTHROW(s.parse({"", "-h"})); REQUIRE_NOTHROW(s.parse({"", "-v"}));
REQUIRE_NOTHROW(s.parse({"", "-h", "gdfg"})); // ignored extra args REQUIRE_NOTHROW(s.parse({"", "-h"}));
REQUIRE_NOTHROW(s.parse({"", "-p", "1955"})); REQUIRE_NOTHROW(s.parse({"", "-h", "gdfg"})); // ignored extra args
REQUIRE_NOTHROW(s.parse({"", "-u", uidStr})); REQUIRE_NOTHROW(s.parse({"", "-p", "1955"}));
REQUIRE_NOTHROW(s.parse({"", "-p", "1234", "-u", uidStr})); REQUIRE_NOTHROW(s.parse({"", "-u", uidStr}));
} REQUIRE_NOTHROW(s.parse({"", "-p", "1234", "-u", uidStr}));
}
TEST_CASE("Validate specific options", "[.rxcmdcall]") {
std::string uidStr = std::to_string(getuid());
CommandLineOptions s(AppType::SingleReceiver);
REQUIRE_NOTHROW(s.parse({"", "-t", "1955"}));
REQUIRE_THROWS(s.parse({"", "-c"}));
REQUIRE_THROWS(s.parse({"", "-n", "2"}));
REQUIRE_THROWS(s.parse({"", "-m", "2"}));
for (auto app : {AppType::MultiReceiver, AppType::FrameSynchronizer}) {
CommandLineOptions m(app);
REQUIRE_NOTHROW(m.parse({"", "-c"}));
REQUIRE_NOTHROW(m.parse({"", "-n", "2"}));
REQUIRE_NOTHROW(m.parse({"", "-p", "1234", "-u", uidStr, "-c", "-n", "2"}));
REQUIRE_THROWS(m.parse({"", "-t", "1955"}));
REQUIRE_THROWS(m.parse({"", "-m", "2"}));
}
}
TEST_CASE("Parse version and help", "[.rxcmdcall]") {
for (auto app : {AppType::SingleReceiver, AppType::MultiReceiver, AppType::FrameSynchronizer}) {
CommandLineOptions s(app);
auto opts = s.parse({});
std::visit([](const auto& o) {
REQUIRE(o.versionRequested == false); // default
REQUIRE(o.helpRequested == false); // default
}, opts);
opts = s.parse({"", "-v"});
std::visit([](const auto& o) {
REQUIRE(o.versionRequested == true);
REQUIRE(o.helpRequested == false);
}, opts);
opts = s.parse({"", "-h"});
std::visit([](const auto& o) {
REQUIRE(o.versionRequested == false);
REQUIRE(o.helpRequested == true);
}, opts);
opts = s.parse({"", "-h", "-v"});
std::visit([](const auto& o) {
REQUIRE(o.versionRequested == false); // exits after help
REQUIRE(o.helpRequested == true);
}, opts);
opts = s.parse({"", "-v", "-h"});
std::visit([](const auto& o) {
REQUIRE(o.helpRequested == false); // exits after version
REQUIRE(o.versionRequested == true);
}, opts);
opts = s.parse({"", "-v", "-h", "sdfsf"}); // ignores extra args
std::visit([](const auto& o) {
REQUIRE(o.helpRequested == false); // exits after version
REQUIRE(o.versionRequested == true);
}, opts);
}
}
TEST_CASE("Parse port and uid", "[.rxcmdcall]") {
uid_t uid = getuid();
std::string uidStr = std::to_string(uid);
uid_t invalidUid = uid + 1000;
std::string invalidUidStr = std::to_string(invalidUid);
for (auto app : {AppType::SingleReceiver, AppType::MultiReceiver, AppType::FrameSynchronizer}) {
CommandLineOptions s(app);
REQUIRE_THROWS(s.parse({"", "-p", "1234", "-u", invalidUidStr})); // invalid uid
REQUIRE_THROWS(s.parse({"", "-p", "500"})); // invalid port
auto opts = s.parse({"", "-p", "1234", "-u", uidStr});
std::visit([&](const auto& o){
REQUIRE(o.port == 1234);
REQUIRE(o.userid == uid);
}, opts);
opts = s.parse({"", "-p", "5678"});
std::visit([](const auto& o) {
REQUIRE(o.port == 5678);
REQUIRE(o.userid == static_cast<uid_t>(-1)); // default
}, opts);
opts = s.parse({});
std::visit([](const auto& o) {
REQUIRE(o.port == 1954); // default
REQUIRE(o.userid == static_cast<uid_t>(-1)); // default
}, opts);
}
}
TEST_CASE("Parse num receivers and opt arg (Specific opt)", "[.rxcmdcall]") {
for (auto app : {AppType::MultiReceiver, AppType::FrameSynchronizer}) {
CommandLineOptions s(app);
REQUIRE_THROWS(s.parse({"", "-n", "0"})); // invalid number of receivers
REQUIRE_THROWS(s.parse({"", "-n", "1001"})); // exceeds max receivers
REQUIRE_NOTHROW(s.parse({"", "-n", "10"})); // valid
auto opts = s.parse({""});
std::visit([](const auto& o) {
using T = decltype(o);
if constexpr (is_type<MultiReceiverOptions, T>()) {
REQUIRE(o.numReceivers == 1); // default
REQUIRE(o.callbackEnabled == false);
} else if constexpr (is_type<FrameSyncOptions, T>()) {
REQUIRE(o.numReceivers == 1); // default
REQUIRE(o.printHeaders == false);
}
}, opts);
opts = s.parse({"", "-n", "5"});
std::visit([](const auto& o) {
using T = decltype(o);
if constexpr (is_type<MultiReceiverOptions, T>()) {
REQUIRE(o.numReceivers == 5);
REQUIRE(o.callbackEnabled == false); // default
} else if constexpr (is_type<FrameSyncOptions, T>()) {
REQUIRE(o.numReceivers == 5);
REQUIRE(o.printHeaders == false); // default
}
}, opts);
opts = s.parse({"", "-c", "-n", "3"});
std::visit([](const auto& o) {
using T = decltype(o);
if constexpr (is_type<MultiReceiverOptions, T>()) {
REQUIRE(o.numReceivers == 3);
REQUIRE(o.callbackEnabled == true);
} else if constexpr (is_type<FrameSyncOptions, T>()) {
REQUIRE(o.numReceivers == 3);
REQUIRE(o.printHeaders == true);
}
}, opts);
}
}
TEST_CASE("Parse deprecated options", "[.rxcmdcall]") {
for (auto app : {AppType::SingleReceiver, AppType::MultiReceiver, AppType::FrameSynchronizer}) {
CommandLineOptions s(app);
// argc 3 or 4, invalid
REQUIRE_THROWS(s.parse({"", "1954"}));
REQUIRE_THROWS(s.parse({"", "1954", }));
// argc 3 or 4
if (app == AppType::SingleReceiver) {
REQUIRE_THROWS(s.parse({"", "1954", "1"})); // deprecated unsupported
} else {
REQUIRE_THROWS(s.parse({"", "1954", "1", "1", "-p", "1954"}));// mix deprecated and current
REQUIRE_THROWS(s.parse({"", "1954", "1", "-c"}));// mix deprecated and current
REQUIRE_THROWS(s.parse({"", "1954", "1", "-n", "34"}));// mix deprecated and current
REQUIRE_THROWS(s.parse({"", "110", "1954"}));// mix order
REQUIRE_THROWS(s.parse({"", "1023", "10"}));// privileged port
REQUIRE_THROWS(s.parse({"", "2000", "0"}));// invalid num receivers
REQUIRE_THROWS(s.parse({"", "2000", "1001"}));// invalid num receivers
REQUIRE_THROWS(s.parse({"", "1954", "1", "2"}));// invalid 3rd opt
REQUIRE_NOTHROW(s.parse({""}));
REQUIRE_NOTHROW(s.parse({"", "1954", "1"}));
REQUIRE_NOTHROW(s.parse({"", "1954", "1", "0"}));
REQUIRE_NOTHROW(s.parse({"", "1954", "1", "1"}));
// default
auto opts = s.parse({""});
std::visit([](const auto& o) {
using T = decltype(o);
if constexpr (is_type<MultiReceiverOptions, T>()) {
REQUIRE(o.port == 1954);
REQUIRE(o.numReceivers == 1);
REQUIRE(o.callbackEnabled == false);
} else if constexpr (is_type<FrameSyncOptions, T>()) {
REQUIRE(o.port == 1954);
REQUIRE(o.numReceivers == 1);
REQUIRE(o.printHeaders == false); // default
}
}, opts);
opts = s.parse({"", "1958", "10"});
std::visit([](const auto& o) {
using T = decltype(o);
if constexpr (is_type<MultiReceiverOptions, T>()) {
REQUIRE(o.port == 1958);
REQUIRE(o.numReceivers == 10);
REQUIRE(o.callbackEnabled == false); // default
} else if constexpr (is_type<FrameSyncOptions, T>()) {
REQUIRE(o.port == 1958);
REQUIRE(o.numReceivers == 10);
REQUIRE(o.printHeaders == false); // default
}
}, opts);
opts = s.parse({"", "1958", "10", "1"});
std::visit([](const auto& o) {
using T = decltype(o);
if constexpr (is_type<MultiReceiverOptions, T>()) {
REQUIRE(o.port == 1958);
REQUIRE(o.numReceivers == 10);
REQUIRE(o.callbackEnabled == true); // default
} else if constexpr (is_type<FrameSyncOptions, T>()) {
REQUIRE(o.port == 1958);
REQUIRE(o.numReceivers == 10);
REQUIRE(o.printHeaders == true); // default
}
}, opts);
}
}
// test function directly
// nargs can be 1, 3 or 4
REQUIRE_THROWS(CommandLineOptions::ParseDeprecated({"",""}));
REQUIRE_THROWS(CommandLineOptions::ParseDeprecated({"","", "", "", ""}));
// default
auto [p, n, o] = CommandLineOptions::ParseDeprecated({""});
REQUIRE(p == 1954);
REQUIRE(n == 1);
REQUIRE(o == false);
std::tie(p, n, o) = CommandLineOptions::ParseDeprecated({"", "1955", "6"});
REQUIRE(p == 1955);
REQUIRE(n == 6);
REQUIRE(o == false);
std::tie(p, n, o) = CommandLineOptions::ParseDeprecated({"", "1955", "6", "1"});
REQUIRE(p == 1955);
REQUIRE(n == 6);
REQUIRE(o == true);
} }
} }
TEST_CASE("Validate specific options", "[.rxcmdcall]") {
std::string uidStr = std::to_string(getuid());
CommandLineOptions s(AppType::SingleReceiver);
REQUIRE_NOTHROW(s.parse({"", "-t", "1955"}));
REQUIRE_THROWS(s.parse({"", "-c"}));
REQUIRE_THROWS(s.parse({"", "-n", "2"}));
REQUIRE_THROWS(s.parse({"", "-m", "2"}));
for (auto app : {AppType::MultiReceiver, AppType::FrameSynchronizer}) {
CommandLineOptions m(app);
REQUIRE_NOTHROW(m.parse({"", "-c"}));
REQUIRE_NOTHROW(m.parse({"", "-n", "2"}));
REQUIRE_NOTHROW(
m.parse({"", "-p", "1234", "-u", uidStr, "-c", "-n", "2"}));
REQUIRE_THROWS(m.parse({"", "-t", "1955"}));
REQUIRE_THROWS(m.parse({"", "-m", "2"}));
}
}
TEST_CASE("Parse version and help", "[.rxcmdcall]") {
for (auto app : {AppType::SingleReceiver, AppType::MultiReceiver,
AppType::FrameSynchronizer}) {
CommandLineOptions s(app);
auto opts = s.parse({});
std::visit(
[](const auto &o) {
REQUIRE(o.versionRequested == false); // default
REQUIRE(o.helpRequested == false); // default
},
opts);
opts = s.parse({"", "-v"});
std::visit(
[](const auto &o) {
REQUIRE(o.versionRequested == true);
REQUIRE(o.helpRequested == false);
},
opts);
opts = s.parse({"", "-h"});
std::visit(
[](const auto &o) {
REQUIRE(o.versionRequested == false);
REQUIRE(o.helpRequested == true);
},
opts);
opts = s.parse({"", "-h", "-v"});
std::visit(
[](const auto &o) {
REQUIRE(o.versionRequested == false); // exits after help
REQUIRE(o.helpRequested == true);
},
opts);
opts = s.parse({"", "-v", "-h"});
std::visit(
[](const auto &o) {
REQUIRE(o.helpRequested == false); // exits after version
REQUIRE(o.versionRequested == true);
},
opts);
opts = s.parse({"", "-v", "-h", "sdfsf"}); // ignores extra args
std::visit(
[](const auto &o) {
REQUIRE(o.helpRequested == false); // exits after version
REQUIRE(o.versionRequested == true);
},
opts);
}
}
TEST_CASE("Parse port and uid", "[.rxcmdcall]") {
uid_t uid = getuid();
std::string uidStr = std::to_string(uid);
uid_t invalidUid = uid + 1000;
std::string invalidUidStr = std::to_string(invalidUid);
for (auto app : {AppType::SingleReceiver, AppType::MultiReceiver,
AppType::FrameSynchronizer}) {
CommandLineOptions s(app);
REQUIRE_THROWS(
s.parse({"", "-p", "1234", "-u", invalidUidStr})); // invalid uid
REQUIRE_THROWS(s.parse({"", "-p", "500"})); // invalid port
auto opts = s.parse({"", "-p", "1234", "-u", uidStr});
std::visit(
[&](const auto &o) {
REQUIRE(o.port == 1234);
REQUIRE(o.userid == uid);
},
opts);
opts = s.parse({"", "-p", "5678"});
std::visit(
[](const auto &o) {
REQUIRE(o.port == 5678);
REQUIRE(o.userid == static_cast<uid_t>(-1)); // default
},
opts);
opts = s.parse({});
std::visit(
[](const auto &o) {
REQUIRE(o.port == 1954); // default
REQUIRE(o.userid == static_cast<uid_t>(-1)); // default
},
opts);
}
}
TEST_CASE("Parse num receivers and opt arg (Specific opt)", "[.rxcmdcall]") {
for (auto app : {AppType::MultiReceiver, AppType::FrameSynchronizer}) {
CommandLineOptions s(app);
REQUIRE_THROWS(s.parse({"", "-n", "0"})); // invalid number of receivers
REQUIRE_THROWS(s.parse({"", "-n", "1001"})); // exceeds max receivers
REQUIRE_NOTHROW(s.parse({"", "-n", "10"})); // valid
auto opts = s.parse({""});
std::visit(
[](const auto &o) {
using T = decltype(o);
if constexpr (is_type<MultiReceiverOptions, T>()) {
REQUIRE(o.numReceivers == 1); // default
REQUIRE(o.callbackEnabled == false);
} else if constexpr (is_type<FrameSyncOptions, T>()) {
REQUIRE(o.numReceivers == 1); // default
REQUIRE(o.printHeaders == false);
}
},
opts);
opts = s.parse({"", "-n", "5"});
std::visit(
[](const auto &o) {
using T = decltype(o);
if constexpr (is_type<MultiReceiverOptions, T>()) {
REQUIRE(o.numReceivers == 5);
REQUIRE(o.callbackEnabled == false); // default
} else if constexpr (is_type<FrameSyncOptions, T>()) {
REQUIRE(o.numReceivers == 5);
REQUIRE(o.printHeaders == false); // default
}
},
opts);
opts = s.parse({"", "-c", "-n", "3"});
std::visit(
[](const auto &o) {
using T = decltype(o);
if constexpr (is_type<MultiReceiverOptions, T>()) {
REQUIRE(o.numReceivers == 3);
REQUIRE(o.callbackEnabled == true);
} else if constexpr (is_type<FrameSyncOptions, T>()) {
REQUIRE(o.numReceivers == 3);
REQUIRE(o.printHeaders == true);
}
},
opts);
}
}
TEST_CASE("Parse deprecated options", "[.rxcmdcall]") {
for (auto app : {AppType::SingleReceiver, AppType::MultiReceiver,
AppType::FrameSynchronizer}) {
CommandLineOptions s(app);
// argc 3 or 4, invalid
REQUIRE_THROWS(s.parse({"", "1954"}));
REQUIRE_THROWS(s.parse({
"",
"1954",
}));
// argc 3 or 4
if (app == AppType::SingleReceiver) {
REQUIRE_THROWS(
s.parse({"", "1954", "1"})); // deprecated unsupported
} else {
REQUIRE_THROWS(s.parse({"", "1954", "1", "1", "-p",
"1954"})); // mix deprecated and current
REQUIRE_THROWS(
s.parse({"", "1954", "1", "-c"})); // mix deprecated and current
REQUIRE_THROWS(s.parse(
{"", "1954", "1", "-n", "34"})); // mix deprecated and current
REQUIRE_THROWS(s.parse({"", "110", "1954"})); // mix order
REQUIRE_THROWS(s.parse({"", "1023", "10"})); // privileged port
REQUIRE_THROWS(s.parse({"", "2000", "0"})); // invalid num receivers
REQUIRE_THROWS(
s.parse({"", "2000", "1001"})); // invalid num receivers
REQUIRE_THROWS(s.parse({"", "1954", "1", "2"})); // invalid 3rd opt
REQUIRE_NOTHROW(s.parse({""}));
REQUIRE_NOTHROW(s.parse({"", "1954", "1"}));
REQUIRE_NOTHROW(s.parse({"", "1954", "1", "0"}));
REQUIRE_NOTHROW(s.parse({"", "1954", "1", "1"}));
// default
auto opts = s.parse({""});
std::visit(
[](const auto &o) {
using T = decltype(o);
if constexpr (is_type<MultiReceiverOptions, T>()) {
REQUIRE(o.port == 1954);
REQUIRE(o.numReceivers == 1);
REQUIRE(o.callbackEnabled == false);
} else if constexpr (is_type<FrameSyncOptions, T>()) {
REQUIRE(o.port == 1954);
REQUIRE(o.numReceivers == 1);
REQUIRE(o.printHeaders == false); // default
}
},
opts);
opts = s.parse({"", "1958", "10"});
std::visit(
[](const auto &o) {
using T = decltype(o);
if constexpr (is_type<MultiReceiverOptions, T>()) {
REQUIRE(o.port == 1958);
REQUIRE(o.numReceivers == 10);
REQUIRE(o.callbackEnabled == false); // default
} else if constexpr (is_type<FrameSyncOptions, T>()) {
REQUIRE(o.port == 1958);
REQUIRE(o.numReceivers == 10);
REQUIRE(o.printHeaders == false); // default
}
},
opts);
opts = s.parse({"", "1958", "10", "1"});
std::visit(
[](const auto &o) {
using T = decltype(o);
if constexpr (is_type<MultiReceiverOptions, T>()) {
REQUIRE(o.port == 1958);
REQUIRE(o.numReceivers == 10);
REQUIRE(o.callbackEnabled == true); // default
} else if constexpr (is_type<FrameSyncOptions, T>()) {
REQUIRE(o.port == 1958);
REQUIRE(o.numReceivers == 10);
REQUIRE(o.printHeaders == true); // default
}
},
opts);
}
}
// test function directly
// nargs can be 1, 3 or 4
REQUIRE_THROWS(CommandLineOptions::ParseDeprecated({"", ""}));
REQUIRE_THROWS(CommandLineOptions::ParseDeprecated({"", "", "", "", ""}));
// default
auto [p, n, o] = CommandLineOptions::ParseDeprecated({""});
REQUIRE(p == 1954);
REQUIRE(n == 1);
REQUIRE(o == false);
std::tie(p, n, o) = CommandLineOptions::ParseDeprecated({"", "1955", "6"});
REQUIRE(p == 1955);
REQUIRE(n == 6);
REQUIRE(o == false);
std::tie(p, n, o) =
CommandLineOptions::ParseDeprecated({"", "1955", "6", "1"});
REQUIRE(p == 1955);
REQUIRE(n == 6);
REQUIRE(o == true);
}
} // namespace sls