fixed tests
Some checks failed
Build on RHEL8 / build (push) Failing after 1m7s
Build on RHEL9 / build (push) Failing after 2m43s

This commit is contained in:
2025-07-08 15:20:28 +02:00
parent 318b19ad79
commit fb4a25ecee
6 changed files with 313 additions and 163 deletions

View File

@ -28,9 +28,6 @@ ParsedOptions CommandLineOptions::parse(int argc, char *argv[]) {
MultiReceiverOptions multi;
FrameSyncOptions frame;
uint16_t numReceivers = 1;
bool optionalArg = false;
auto optString = buildOptString();
auto longOptions = buildOptionList();
@ -62,34 +59,40 @@ ParsedOptions CommandLineOptions::parse(int argc, char *argv[]) {
// remaining arguments
if (optind < argc) {
// no deprecated arguments
// deprecated and current options => invalid
if (base.port != DEFAULT_TCP_RX_PORTNO ||
multi.numReceivers != 1 || frame.numReceivers != 1 || multi.callbackEnabled != false || frame.printHeaders != false) {
LOG(sls::logWARNING)
<< "Cannot use both deprecated options and the valid options simultaneously. Please use only the new options.\n";
}
// unsupported deprecated arguments
if (appType_ == AppType::SingleReceiver) {
throw sls::RuntimeError("Invalid arguments." + getHelpMessage());
}
// maintain backward compatibility of [start port] [num receivers]
// [optional arg]
if (argc != 3 && argc != 4) {
throw sls::RuntimeError("Invalid number of arguments." +
getHelpMessage());
}
GetDeprecated(argc, argv, base.port, numReceivers, optionalArg);
// parse deprecated arguments
std::vector<std::string> args(argv, argv + argc);
auto [p, n, o] = ParseDeprecated(args);
// set options
base.port = p;
if (appType_ == AppType::MultiReceiver) {
multi.numReceivers = numReceivers;
multi.callbackEnabled = optionalArg;
multi.numReceivers = n;
multi.callbackEnabled = o;
} else if (appType_ == AppType::FrameSynchronizer) {
frame.numReceivers = numReceivers;
frame.printHeaders = optionalArg;
frame.numReceivers = n;
frame.printHeaders = o;
}
}
// Logging
LOG(sls::logINFO) << "Number of receivers: " << numReceivers;
LOG(sls::logINFO) << "TCP Port: " << base.port;
if (appType_ == AppType::MultiReceiver) {
LOG(sls::logINFO) << "Number of receivers: " << multi.numReceivers;
LOG(sls::logINFO) << "Callback enabled: " << multi.callbackEnabled;
} else if (appType_ == AppType::FrameSynchronizer) {
LOG(sls::logINFO) << "Number of receivers: " << frame.numReceivers;
LOG(sls::logINFO) << "Print headers: " << frame.printHeaders;
}
@ -241,30 +244,37 @@ void CommandLineOptions::handleAppSpecificOption(int opt, const char *optarg,
}
}
void CommandLineOptions::GetDeprecated(int argc, char *argv[],
uint16_t &startPort,
uint16_t &numReceivers,
bool &optionalArg) {
if (argc > 1) {
if (argc == 3 || argc == 4) {
LOG(sls::logWARNING)
<< "Detected deprecated Options. Please update.\n";
/* maintain backward compatibility of [start port] [num receivers] [optional arg] */
std::tuple<uint16_t, uint16_t, bool> CommandLineOptions::ParseDeprecated(const std::vector<std::string> &args) {
startPort = parsePort(argv[1]);
numReceivers = parseNumReceivers(argv[2]);
if (argc == 4) {
try {
optionalArg = sls::StringTo<bool>(argv[3]);
} catch (...) {
throw sls::RuntimeError("Invalid optional argument "
"parsed. Expected 1 (true) or "
"0 (false).");
}
}
} else
throw std::runtime_error("Invalid number of arguments");
size_t nargs = args.size();
if (nargs != 1 && nargs != 3 && nargs != 4) {
throw sls::RuntimeError("Invalid number of arguments.");
}
LOG(sls::logWARNING)
<< "Deprecated options will be removed in future versions. "
"Please use the new options.\n";
// default deprecated values
if (nargs == 1) {
return std::make_tuple(DEFAULT_TCP_RX_PORTNO, 1, false);
}
// parse deprecated arguments
uint16_t p = parsePort(args[1].c_str());
uint16_t n = parseNumReceivers(args[2].c_str());
bool o = false;
if (nargs == 4) {
try {
o = sls::StringTo<bool>(args[3].c_str());
} catch (...) {
throw sls::RuntimeError("Invalid optional argument "
"parsed. Expected 1 (true) or "
"0 (false).");
}
}
return std::make_tuple(p, n, o);
}
std::string CommandLineOptions::getTypeString() const {

View File

@ -7,6 +7,7 @@
#include <string>
#include <variant>
#include <vector>
#include <tuple>
enum class AppType {
MultiReceiver,
@ -44,7 +45,7 @@ class CommandLineOptions {
std::string getHelpMessage() const;
static void setupSignalHandler(int signal, void (*handler)(int));
static void setEffectiveUID(uid_t uid);
static std::tuple<uint16_t, uint16_t, bool> ParseDeprecated(const std::vector<std::string> &args);
private:
AppType appType_;
std::vector<option> buildOptionList() const;
@ -59,8 +60,8 @@ class CommandLineOptions {
MultiReceiverOptions &multi,
FrameSyncOptions &frame);
static void GetDeprecated(int argc, char *argv[], uint16_t &startPort,
uint16_t &numReceivers, bool &optionalArg);
static constexpr uint16_t MAX_RECEIVERS = 1000;
};

View File

@ -504,7 +504,12 @@ void sigInterruptHandler(int p) {
int main(int argc, char *argv[]) {
CommandLineOptions cli(AppType::SingleReceiver);
auto opts = cli.parse(argc, argv);
ParsedOptions opts;
try {
opts = cli.parse(argc, argv);
} catch (sls::RuntimeError &e) {
return EXIT_FAILURE;
}
auto &o = std::get<CommonOptions>(opts);
auto &f = std::get<FrameSyncOptions>(opts);
if (o.versionRequested || o.helpRequested) {

View File

@ -144,7 +144,12 @@ void sigInterruptHandler(int signal) {
int main(int argc, char *argv[]) {
CommandLineOptions cli(AppType::SingleReceiver);
auto opts = cli.parse(argc, argv);
ParsedOptions opts;
try {
opts = cli.parse(argc, argv);
} catch (sls::RuntimeError &e) {
return EXIT_FAILURE;
}
auto& o = std::get<CommonOptions>(opts);
auto &m = std::get<MultiReceiverOptions>(opts);
if (o.versionRequested || o.helpRequested) {

View File

@ -32,7 +32,12 @@ void sigInterruptHandler(int signal) {
int main(int argc, char *argv[]) {
CommandLineOptions cli(AppType::SingleReceiver);
auto opts = cli.parse(argc, argv);
ParsedOptions opts;
try {
opts = cli.parse(argc, argv);
} catch (sls::RuntimeError &e) {
return EXIT_FAILURE;
}
auto& o = std::get<CommonOptions>(opts);
if (o.versionRequested || o.helpRequested) {
return EXIT_SUCCESS;

View File

@ -4,8 +4,15 @@
#include "CommandLineOptions.h"
#include "sls/versionAPI.h"
#include <unistd.h>
namespace sls {
template<typename T, typename U>
constexpr bool is_type(const U&) {
return std::is_same_v<std::decay_t<U>, T>;
}
TEST_CASE("CommandLineOption construction", "[.rxcmdcall]") {
CommandLineOptions s(AppType::SingleReceiver);
REQUIRE(s.getTypeString() == "slsReceiver");
@ -23,131 +30,248 @@ namespace sls {
REQUIRE_NOTHROW(f.getHelpMessage());
}
TEST_CASE("Validate slsReceiver options", "[.rxcmdcall]") {
CommandLineOptions s(AppType::SingleReceiver);
// valid options
REQUIRE_NOTHROW(s.parse({}));
REQUIRE_NOTHROW(s.parse({"", "-v"}));
REQUIRE_NOTHROW(s.parse({"", "-h"}));
REQUIRE_NOTHROW(s.parse({"", "-h", "gdfg"})); // ignored extra args
REQUIRE_NOTHROW(s.parse({"", "-p", "1955"}));
REQUIRE_NOTHROW(s.parse({"", "-u", "1001"}));
REQUIRE_NOTHROW(s.parse({"", "-p", "1234", "-u", "1001"}));
REQUIRE_NOTHROW(s.parse({"", "-t", "1955"}));
// invalid options
REQUIRE_THROWS(s.parse({"", "-c"}));
REQUIRE_THROWS(s.parse({"", "-n", "2"}));
REQUIRE_THROWS(s.parse({"", "-m", "2"}));
}
TEST_CASE("Validate common options", "[.rxcmdcall]") {
std::string uidStr = std::to_string(getuid());
TEST_CASE("Validate slsMultiReceiver options", "[.rxcmdcall]") {
CommandLineOptions s(AppType::MultiReceiver);
// valid options
REQUIRE_NOTHROW(s.parse({}));
REQUIRE_NOTHROW(s.parse({"", "-v"}));
REQUIRE_NOTHROW(s.parse({"", "-h"}));
REQUIRE_NOTHROW(s.parse({"", "-h", "gdfg"})); // ignored extra args
REQUIRE_NOTHROW(s.parse({"", "-p", "1955"}));
REQUIRE_NOTHROW(s.parse({"", "-u", "1001"}));
REQUIRE_NOTHROW(s.parse({"", "-p", "1234", "-u", "1001"}));
REQUIRE_NOTHROW(s.parse({"", "-c"}));
REQUIRE_NOTHROW(s.parse({"", "-n", "2"}));
REQUIRE_NOTHROW(s.parse({"", "-p", "1234", "-u", "1001", "-c", "-n", "2"}));
// invalid options
REQUIRE_THROWS(s.parse({"", "-t", "1955"}));
REQUIRE_THROWS(s.parse({"", "-m", "2"}));
}
TEST_CASE("Validate slsFrameSynchronizer options", "[.rxcmdcall]") {
CommandLineOptions s(AppType::FrameSynchronizer);
// valid options
REQUIRE_NOTHROW(s.parse({}));
REQUIRE_NOTHROW(s.parse({"", "-v"}));
REQUIRE_NOTHROW(s.parse({"", "-h"}));
REQUIRE_NOTHROW(s.parse({"", "-h", "gdfg"})); // ignored extra args
REQUIRE_NOTHROW(s.parse({"", "-p", "1955"}));
REQUIRE_NOTHROW(s.parse({"", "-u", "1001"}));
REQUIRE_NOTHROW(s.parse({"", "-p", "1234", "-u", "1001"}));
REQUIRE_NOTHROW(s.parse({"", "-c"}));
REQUIRE_NOTHROW(s.parse({"", "-n", "2"}));
REQUIRE_NOTHROW(s.parse({"", "-p", "1234", "-u", "1001", "-c", "-n", "2"}));
// invalid options
REQUIRE_THROWS(s.parse({"", "-t", "1955"}));
REQUIRE_THROWS(s.parse({"", "-m", "2"}));
}
TEST_CASE("Parse version and help", "[.rxcmdcall]") {
CommandLineOptions s(AppType::SingleReceiver);
auto opts = s.parse({});
auto &o = std::get<CommonOptions>(opts);
REQUIRE(o.versionRequested == false);
REQUIRE(o.helpRequested == false);
opts = s.parse({"", "-v"});
o = std::get<CommonOptions>(opts);
REQUIRE(o.versionRequested == true);
REQUIRE(o.helpRequested == false);
opts = s.parse({"", "-h"});
o = std::get<CommonOptions>(opts);
REQUIRE(o.versionRequested == false);
REQUIRE(o.helpRequested == true);
opts = s.parse({"", "-h", "-v"});
o = std::get<CommonOptions>(opts);
REQUIRE(o.versionRequested == false); // because it exits after help
REQUIRE(o.helpRequested == true);
opts = s.parse({"", "-v", "-h"});
o = std::get<CommonOptions>(opts);
REQUIRE(o.helpRequested == false); // because it exits after version
REQUIRE(o.versionRequested == true);
opts = s.parse({"", "-v", "-h", "sdfsf"}); // should ignore extra args
o = std::get<CommonOptions>(opts);
REQUIRE(o.helpRequested == false); // because it exits after version
REQUIRE(o.versionRequested == true);
}
TEST_CASE("Parse port and uid", "[.rxcmdcall]") {
for (auto app : {AppType::SingleReceiver, AppType::MultiReceiver, AppType::FrameSynchronizer}) {
CommandLineOptions s(app);
REQUIRE_THROWS(s.parse({"", "-p", "1234", "-u", "1000"})); // invalid uid
REQUIRE_THROWS(s.parse({"", "-p", "500"})); // invalid port
auto opts = s.parse({"", "-p", "1234", "-u", "1001"});
auto &o = std::get<CommonOptions>(opts);
REQUIRE(o.port == 1234);
REQUIRE(o.userid == 1001);
opts = s.parse({"", "-p", "5678"});
o = std::get<CommonOptions>(opts);
REQUIRE(o.port == 5678);
REQUIRE(o.userid == static_cast<uid_t>(-1)); // default value
opts = s.parse({});
o = std::get<CommonOptions>(opts);
REQUIRE(o.port == 1954); // default value
REQUIRE(o.userid == static_cast<uid_t>(-1)); // default value
REQUIRE_NOTHROW(s.parse({}));
REQUIRE_NOTHROW(s.parse({"", "-v"}));
REQUIRE_NOTHROW(s.parse({"", "-h"}));
REQUIRE_NOTHROW(s.parse({"", "-h", "gdfg"})); // ignored extra args
REQUIRE_NOTHROW(s.parse({"", "-p", "1955"}));
REQUIRE_NOTHROW(s.parse({"", "-u", uidStr}));
REQUIRE_NOTHROW(s.parse({"", "-p", "1234", "-u", uidStr}));
}
}
TEST_CASE("Parse number of receivers and optional arg", "[.rxcmdcall]") {
CommandLineOptions s(AppType::MultiReceiver);
// invalid options
REQUIRE_THROWS(s.parse({"", "-n", "0"})); // invalid number of receivers
REQUIRE_THROWS(s.parse({"", "-n", "1001"})); // exceeds max receivers
// valid options
REQUIRE_NOTHROW(s.parse({"", "-n", "10"})); // valid number of receivers
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"}));
auto opts = s.parse({"", "-n", "5"});
auto &m = std::get<MultiReceiverOptions>(opts);
REQUIRE(m.numReceivers == 5);
REQUIRE(m.callbackEnabled == false); // default value
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"}));
}
}
opts = s.parse({"", "-c", "-n", "3"});
m = std::get<MultiReceiverOptions>(opts);
REQUIRE(m.numReceivers == 3);
REQUIRE(m.callbackEnabled == true);
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) {
if constexpr (is_type<MultiReceiverOptions>(o)) {
REQUIRE(o.numReceivers == 1); // default
REQUIRE(o.callbackEnabled == false);
} else if constexpr (is_type<FrameSyncOptions>(o)) {
REQUIRE(o.numReceivers == 1); // default
REQUIRE(o.printHeaders == false);
}
}, opts);
opts = s.parse({"", "-n", "5"});
std::visit([&](const auto& o) {
if constexpr (is_type<MultiReceiverOptions>(o)) {
REQUIRE(o.numReceivers == 5);
REQUIRE(o.callbackEnabled == false); // default
} else if constexpr (is_type<FrameSyncOptions>(o)) {
REQUIRE(o.numReceivers == 5);
REQUIRE(o.printHeaders == false); // default
}
}, opts);
opts = s.parse({"", "-c", "-n", "3"});
std::visit([&](const auto& o) {
if constexpr (is_type<MultiReceiverOptions>(o)) {
REQUIRE(o.numReceivers == 3);
REQUIRE(o.callbackEnabled == true);
} else if constexpr (is_type<FrameSyncOptions>(o)) {
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", "1000"}));// 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) {
if constexpr (is_type<MultiReceiverOptions>(o)) {
REQUIRE(o.port == 1954);
REQUIRE(o.numReceivers == 1);
REQUIRE(o.callbackEnabled == false);
} else if constexpr (is_type<FrameSyncOptions>(o)) {
REQUIRE(o.port == 1958);
REQUIRE(o.numReceivers == 10);
REQUIRE(o.printHeaders == false); // default
}
}, opts);
auto opts = s.parse({"", "1958", "10"});
std::visit([&](const auto& o) {
if constexpr (is_type<MultiReceiverOptions>(o)) {
REQUIRE(o.port == 1958);
REQUIRE(o.numReceivers == 10);
REQUIRE(o.callbackEnabled == false); // default
} else if constexpr (is_type<FrameSyncOptions>(o)) {
REQUIRE(o.port == 1958);
REQUIRE(o.numReceivers == 10);
REQUIRE(o.printHeaders == false); // default
}
}, opts);
auto opts = s.parse({"", "1958", "1", "1"});
std::visit([&](const auto& o) {
if constexpr (is_type<MultiReceiverOptions>(o)) {
REQUIRE(o.port == 1958);
REQUIRE(o.numReceivers == 10);
REQUIRE(o.callbackEnabled == true); // default
} else if constexpr (is_type<FrameSyncOptions>(o)) {
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);
auto [p, n, o] = CommandLineOptions::ParseDeprecated({"", "1955", "6"});
REQUIRE(p == 1954);
REQUIRE(n == 6);
REQUIRE(o == false);
auto [p, n, o] = CommandLineOptions::ParseDeprecated({"", "1955", "6", "1"});
REQUIRE(p == 1954);
REQUIRE(n == 6);
REQUIRE(o == true);
}
}