You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
5.4 KiB
157 lines
5.4 KiB
#define CATCH_CONFIG_MAIN
|
|
#include "catch2/catch.hpp"
|
|
#include "common/util.h"
|
|
#include "system/proclogd/proclog.h"
|
|
|
|
const std::string allowed_states = "RSDTZtWXxKWPI";
|
|
|
|
TEST_CASE("Parser::procStat") {
|
|
SECTION("from string") {
|
|
const std::string stat_str =
|
|
"33012 (code )) S 32978 6620 6620 0 -1 4194368 2042377 0 144 0 24510 11627 0 "
|
|
"0 20 0 39 0 53077 830029824 62214 18446744073709551615 94257242783744 94257366235808 "
|
|
"140735738643248 0 0 0 0 4098 1073808632 0 0 0 17 2 0 0 2 0 0 94257370858656 94257371248232 "
|
|
"94257404952576 140735738648768 140735738648823 140735738648823 140735738650595 0";
|
|
auto stat = Parser::procStat(stat_str);
|
|
REQUIRE(stat);
|
|
REQUIRE(stat->pid == 33012);
|
|
REQUIRE(stat->name == "code )");
|
|
REQUIRE(stat->state == 'S');
|
|
REQUIRE(stat->ppid == 32978);
|
|
REQUIRE(stat->utime == 24510);
|
|
REQUIRE(stat->stime == 11627);
|
|
REQUIRE(stat->cutime == 0);
|
|
REQUIRE(stat->cstime == 0);
|
|
REQUIRE(stat->priority == 20);
|
|
REQUIRE(stat->nice == 0);
|
|
REQUIRE(stat->num_threads == 39);
|
|
REQUIRE(stat->starttime == 53077);
|
|
REQUIRE(stat->vms == 830029824);
|
|
REQUIRE(stat->rss == 62214);
|
|
REQUIRE(stat->processor == 2);
|
|
}
|
|
SECTION("all processes") {
|
|
std::vector<int> pids = Parser::pids();
|
|
REQUIRE(pids.size() > 1);
|
|
int parsed_cnt = 0;
|
|
for (int pid : pids) {
|
|
if (auto stat = Parser::procStat(util::read_file("/proc/" + std::to_string(pid) + "/stat"))) {
|
|
REQUIRE(stat->pid == pid);
|
|
REQUIRE(allowed_states.find(stat->state) != std::string::npos);
|
|
++parsed_cnt;
|
|
}
|
|
}
|
|
REQUIRE(parsed_cnt == pids.size());
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Parser::cpuTimes") {
|
|
SECTION("from string") {
|
|
std::string stat =
|
|
"cpu 0 0 0 0 0 0 0 0 0 0\n"
|
|
"cpu0 1 2 3 4 5 6 7 8 9 10\n"
|
|
"cpu1 1 2 3 4 5 6 7 8 9 10\n";
|
|
std::istringstream stream(stat);
|
|
auto stats = Parser::cpuTimes(stream);
|
|
REQUIRE(stats.size() == 2);
|
|
for (int i = 0; i < stats.size(); ++i) {
|
|
REQUIRE(stats[i].id == i);
|
|
REQUIRE(stats[i].utime == 1);
|
|
REQUIRE(stats[i].ntime ==2);
|
|
REQUIRE(stats[i].stime == 3);
|
|
REQUIRE(stats[i].itime == 4);
|
|
REQUIRE(stats[i].iowtime == 5);
|
|
REQUIRE(stats[i].irqtime == 6);
|
|
REQUIRE(stats[i].sirqtime == 7);
|
|
}
|
|
}
|
|
SECTION("all cpus") {
|
|
std::istringstream stream(util::read_file("/proc/stat"));
|
|
auto stats = Parser::cpuTimes(stream);
|
|
REQUIRE(stats.size() == sysconf(_SC_NPROCESSORS_ONLN));
|
|
for (int i = 0; i < stats.size(); ++i) {
|
|
REQUIRE(stats[i].id == i);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Parser::memInfo") {
|
|
SECTION("from string") {
|
|
std::istringstream stream("MemTotal: 1024 kb\nMemFree: 2048 kb\n");
|
|
auto meminfo = Parser::memInfo(stream);
|
|
REQUIRE(meminfo["MemTotal:"] == 1024 * 1024);
|
|
REQUIRE(meminfo["MemFree:"] == 2048 * 1024);
|
|
}
|
|
SECTION("from /proc/meminfo") {
|
|
std::string require_keys[] = {"MemTotal:", "MemFree:", "MemAvailable:", "Buffers:", "Cached:", "Active:", "Inactive:", "Shmem:"};
|
|
std::istringstream stream(util::read_file("/proc/meminfo"));
|
|
auto meminfo = Parser::memInfo(stream);
|
|
for (auto &key : require_keys) {
|
|
REQUIRE(meminfo.find(key) != meminfo.end());
|
|
REQUIRE(meminfo[key] > 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void test_cmdline(std::string cmdline, const std::vector<std::string> requires) {
|
|
std::stringstream ss;
|
|
ss.write(&cmdline[0], cmdline.size());
|
|
auto cmds = Parser::cmdline(ss);
|
|
REQUIRE(cmds.size() == requires.size());
|
|
for (int i = 0; i < requires.size(); ++i) {
|
|
REQUIRE(cmds[i] == requires[i]);
|
|
}
|
|
}
|
|
TEST_CASE("Parser::cmdline") {
|
|
test_cmdline(std::string("a\0b\0c\0", 7), {"a", "b", "c"});
|
|
test_cmdline(std::string("a\0\0c\0", 6), {"a", "c"});
|
|
test_cmdline(std::string("a\0b\0c\0\0\0", 9), {"a", "b", "c"});
|
|
}
|
|
|
|
TEST_CASE("buildProcLogerMessage") {
|
|
std::vector<int> current_pids = Parser::pids();
|
|
|
|
MessageBuilder msg;
|
|
buildProcLogMessage(msg);
|
|
|
|
kj::Array<capnp::word> buf = capnp::messageToFlatArray(msg);
|
|
capnp::FlatArrayMessageReader reader(buf);
|
|
auto log = reader.getRoot<cereal::Event>().getProcLog();
|
|
REQUIRE(log.totalSize().wordCount > 0);
|
|
|
|
// test cereal::ProcLog::CPUTimes
|
|
auto cpu_times = log.getCpuTimes();
|
|
REQUIRE(cpu_times.size() == sysconf(_SC_NPROCESSORS_ONLN));
|
|
REQUIRE(cpu_times[cpu_times.size() - 1].getCpuNum() == cpu_times.size() - 1);
|
|
|
|
// test cereal::ProcLog::Mem
|
|
auto mem = log.getMem();
|
|
REQUIRE(mem.getTotal() > 0);
|
|
REQUIRE(mem.getShared() > 0);
|
|
|
|
// test cereal::ProcLog::Process
|
|
auto procs = log.getProcs();
|
|
REQUIRE(procs.size() == current_pids.size());
|
|
|
|
for (auto p : procs) {
|
|
REQUIRE_THAT(current_pids, Catch::Matchers::VectorContains(p.getPid()));
|
|
REQUIRE(allowed_states.find(p.getState()) != std::string::npos);
|
|
if (p.getPid() == ::getpid()) {
|
|
REQUIRE(p.getName() == "test_proclog");
|
|
REQUIRE(p.getState() == 'R');
|
|
REQUIRE_THAT(p.getExe().cStr(), Catch::Matchers::Contains("test_proclog"));
|
|
REQUIRE(p.getCmdline().size() == 1);
|
|
REQUIRE_THAT(p.getCmdline()[0], Catch::Matchers::Contains("test_proclog"));
|
|
} else {
|
|
std::string cmd_path = "/proc/" + std::to_string(p.getPid()) + "/cmdline";
|
|
if (util::file_exists(cmd_path)) {
|
|
std::ifstream stream(cmd_path);
|
|
auto cmdline = Parser::cmdline(stream);
|
|
REQUIRE(cmdline.size() == p.getCmdline().size());
|
|
for (int i = 0; i < p.getCmdline().size(); ++i) {
|
|
REQUIRE(cmdline[i] == p.getCmdline()[i].cStr());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|