#include #include #include #include #include #include #include #include #include "catch2/catch.hpp" #include "common/util.h" std::string random_bytes(int size) { std::random_device rd; std::independent_bits_engine rbe(rd()); std::string bytes(size + 1, '\0'); std::generate(bytes.begin(), bytes.end(), std::ref(rbe)); return bytes; } TEST_CASE("util::read_file") { SECTION("read /proc/version") { std::string ret = util::read_file("/proc/version"); REQUIRE(ret.find("Linux version") != std::string::npos); } SECTION("read from sysfs") { std::string ret = util::read_file("/sys/power/wakeup_count"); REQUIRE(!ret.empty()); } SECTION("read file") { char filename[] = "/tmp/test_read_XXXXXX"; int fd = mkstemp(filename); REQUIRE(util::read_file(filename).empty()); std::string content = random_bytes(64 * 1024); write(fd, content.c_str(), content.size()); std::string ret = util::read_file(filename); bool equal = (ret == content); REQUIRE(equal); close(fd); } SECTION("read directory") { REQUIRE(util::read_file(".").empty()); } SECTION("read non-existent file") { std::string ret = util::read_file("does_not_exist"); REQUIRE(ret.empty()); } SECTION("read non-permission") { REQUIRE(util::read_file("/proc/kmsg").empty()); } } TEST_CASE("util::file_exists") { char filename[] = "/tmp/test_file_exists_XXXXXX"; int fd = mkstemp(filename); REQUIRE(fd != -1); close(fd); SECTION("existent file") { REQUIRE(util::file_exists(filename)); REQUIRE(util::file_exists("/tmp")); } SECTION("nonexistent file") { std::string fn = filename; REQUIRE(!util::file_exists(fn + "/nonexistent")); } SECTION("file has no access permissions") { std::string fn = "/proc/kmsg"; std::ifstream f(fn); REQUIRE(f.good() == false); REQUIRE(util::file_exists(fn)); } ::remove(filename); } TEST_CASE("util::read_files_in_dir") { char tmp_path[] = "/tmp/test_XXXXXX"; const std::string test_path = mkdtemp(tmp_path); const std::string files[] = {".test1", "'test2'", "test3"}; for (auto fn : files) { std::ofstream{test_path + "/" + fn} << fn; } mkdir((test_path + "/dir").c_str(), 0777); std::map result = util::read_files_in_dir(test_path); REQUIRE(result.find("dir") == result.end()); REQUIRE(result.size() == std::size(files)); for (auto& [k, v] : result) { REQUIRE(k == v); } } TEST_CASE("util::safe_fwrite") { char filename[] = "/tmp/XXXXXX"; int fd = mkstemp(filename); close(fd); std::string dat = random_bytes(1024 * 1024); FILE *f = util::safe_fopen(filename, "wb"); REQUIRE(f != nullptr); size_t size = util::safe_fwrite(dat.data(), 1, dat.size(), f); REQUIRE(size == dat.size()); int ret = util::safe_fflush(f); REQUIRE(ret == 0); ret = fclose(f); REQUIRE(ret == 0); bool equal = (dat == util::read_file(filename)); REQUIRE(equal); } TEST_CASE("util::create_directories") { system("rm /tmp/test_create_directories -rf"); std::string dir = "/tmp/test_create_directories/a/b/c/d/e/f"; auto check_dir_permissions = [](const std::string &dir, mode_t mode) -> bool { struct stat st = {}; return stat(dir.c_str(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR && (st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) == mode; }; SECTION("create_directories") { REQUIRE(util::create_directories(dir, 0755)); REQUIRE(check_dir_permissions(dir, 0755)); } SECTION("dir already exists") { REQUIRE(util::create_directories(dir, 0755)); REQUIRE(util::create_directories(dir, 0755)); } SECTION("a file exists with the same name") { REQUIRE(util::create_directories(dir, 0755)); int f = open((dir + "/file").c_str(), O_RDWR | O_CREAT); REQUIRE(f != -1); close(f); REQUIRE(util::create_directories(dir + "/file", 0755) == false); REQUIRE(util::create_directories(dir + "/file/1/2/3", 0755) == false); } SECTION("end with slashes") { REQUIRE(util::create_directories(dir + "/", 0755)); } SECTION("empty") { REQUIRE(util::create_directories("", 0755) == false); } }