27 #include <gtest/gtest.h>
32 std::string
env(
const char* name) {
33 const char* v = getenv(name);
41 std::string r =
env(
"CCTLIB_ROOT");
42 if (!r.empty())
return r;
48 std::string r =
env(
"PIN_ROOT");
55 int run_pin(
const std::string& tool,
const std::vector<std::string>& args) {
56 std::string pin =
pin_root() +
"/pin";
57 std::vector<char*> argv;
58 argv.push_back(
const_cast<char*
>(pin.c_str()));
59 argv.push_back(
const_cast<char*
>(
"-t"));
60 argv.push_back(
const_cast<char*
>(tool.c_str()));
61 argv.push_back(
const_cast<char*
>(
"--"));
62 for (
auto&
a : args) argv.push_back(
const_cast<char*
>(
a.c_str()));
63 argv.push_back(
nullptr);
66 if (pid < 0)
return -1;
68 if (!
env(
"CCTLIB_TEST_VERBOSE").size()) {
69 int devnull = open(
"/dev/null", O_WRONLY);
76 execv(pin.c_str(), argv.data());
80 if (waitpid(pid, &
status, 0) < 0)
return -1;
88 std::string
find_newest(
const std::string& dir,
const std::string& prefix) {
89 std::string cmd =
"ls -t " + dir +
"/" + prefix +
"* 2>/dev/null | head -1";
90 FILE* p = popen(cmd.c_str(),
"r");
94 if (fgets(
buf,
sizeof(
buf), p)) out =
buf;
96 if (!out.empty() && out.back() ==
'\n') out.pop_back();
101 std::ifstream in(path);
102 std::stringstream ss;
108 void cleanup(
const std::string& dir,
const std::string& prefix) {
109 std::string cmd =
"rm -f " + dir +
"/" + prefix +
"*";
110 (void)system(cmd.c_str());
119 <<
"PIN_ROOT environment variable required for integration tests";
120 ASSERT_EQ(0, access((root_ +
"/tests/obj-intel64/cct_client.so").c_str(), F_OK))
121 <<
"tests/obj-intel64/cct_client.so missing; run `make` first";
125 ASSERT_EQ(0, chdir(root_.c_str())) <<
"chdir(" << root_ <<
") failed";
133 int rc =
run_pin(root_ +
"/tests/obj-intel64/cct_client.so", {
"/bin/echo",
"hi"});
134 ASSERT_EQ(0, rc) <<
"cct_client on /bin/echo returned " << rc;
135 std::string outfile =
find_newest(root_,
"client.out.");
136 ASSERT_FALSE(outfile.empty()) <<
"no client.out.* produced";
137 std::string content =
read_file(outfile);
138 std::regex re(R
"(Total call paths=(\d+))");
140 ASSERT_TRUE(std::regex_search(content, m, re))
141 << "output missing Total call paths= line; content:\n" << content;
142 long paths = std::stol(m[1]);
149 int rc =
run_pin(root_ +
"/tests/obj-intel64/cct_client_mem_only.so",
150 {
"/bin/echo",
"hi"});
152 std::string outfile =
find_newest(root_,
"client.out.");
153 ASSERT_FALSE(outfile.empty());
154 EXPECT_NE(std::string::npos,
read_file(outfile).find(
"Total call paths="));
162 int rc =
run_pin(root_ +
"/tests/obj-intel64/cct_data_centric_client.so",
163 {
"/bin/echo",
"hi"});
165 std::string outfile =
find_newest(root_,
"client.out.");
166 ASSERT_FALSE(outfile.empty());
172 int rc =
run_pin(root_ +
"/tests/obj-intel64/cct_data_centric_client_tree_based.so",
173 {
"/bin/echo",
"hi"});
175 std::string outfile =
find_newest(root_,
"client.out.");
176 ASSERT_FALSE(outfile.empty());
static uint64_t buf[ITERS]
std::string env(const char *name)
std::string find_newest(const std::string &dir, const std::string &prefix)
std::string cctlib_root()
void cleanup(const std::string &dir, const std::string &prefix)
std::string read_file(const std::string &path)
TEST_F(CCTLibIntegration, CctDataCentricClientTreeBasedRunsCleanly)
int run_pin(const std::string &tool, const std::vector< std::string > &args)