#include #include "fgc/Paths.h" #include using namespace fgc; TEST_CASE("expandUser expands ~ and environment variables") { setenv("HOME", "/home/tester", 1); setenv("FOO", "bar", 1); CHECK(paths::expandUser("~/x") == "/home/tester/x"); CHECK(paths::expandUser("~") == "/home/tester"); CHECK(paths::expandUser("$FOO/y") == "bar/y"); CHECK(paths::expandUser("${FOO}z") == "barz"); CHECK(paths::expandUser("/abs/path") == "/abs/path"); CHECK(paths::expandUser("") == ""); } TEST_CASE("configSearchPaths honours the CLI argument first") { auto p = paths::configSearchPaths("/explicit/config.ini"); REQUIRE(!p.empty()); CHECK(p.front() == "/explicit/config.ini"); } TEST_CASE("hardwareSearchPaths looks in the documented order") { unsetenv("FGC_HARDWARE"); auto p = paths::hardwareSearchPaths("", "/opt/fgc/config.ini"); auto at = [&](const std::string& s) { for (size_t i = 0; i < p.size(); ++i) if (p[i] == s) return static_cast(i); return -1; }; // /etc is the normal answer on a tower - root-owned, per-device, and OUTSIDE // the deploy tree - so it is searched before a checkout-local file. REQUIRE(at("/etc/fire_gimbal_control/hardware.ini") >= 0); REQUIRE(at("/opt/fgc/hardware.ini") >= 0); CHECK(at("/etc/fire_gimbal_control/hardware.ini") < at("/opt/fgc/hardware.ini")); SUBCASE("an explicit argument outranks everything") { auto q = paths::hardwareSearchPaths("/tmp/mine.ini", "/opt/fgc/config.ini"); CHECK(q.front() == "/tmp/mine.ini"); } SUBCASE("the environment outranks /etc but not the argument") { setenv("FGC_HARDWARE", "/tmp/env.ini", 1); auto q = paths::hardwareSearchPaths("/tmp/cli.ini", "/opt/fgc/config.ini"); REQUIRE(q.size() >= 2); CHECK(q[0] == "/tmp/cli.ini"); CHECK(q[1] == "/tmp/env.ini"); unsetenv("FGC_HARDWARE"); } SUBCASE("with no config path there is simply no sibling candidate") { auto q = paths::hardwareSearchPaths("", ""); for (const auto& s : q) CHECK(s.find("/opt/fgc/") == std::string::npos); } } TEST_CASE("resolveHardwarePath returns nothing when there is no hardware.ini") { // Not an error: every existing tower is in this state until it is migrated, // and the program must go on reading everything from config.ini. unsetenv("FGC_HARDWARE"); CHECK_FALSE(paths::resolveHardwarePath("/nonexistent/nope.ini", "").has_value()); }