25 #include <gtest/gtest.h>
29 std::string
env(
const char* name) {
const char* v = getenv(name);
return v ? v :
""; }
30 std::string
cctlib_root() { std::string r =
env(
"CCTLIB_ROOT");
return r.empty() ?
"../.." : r; }
33 int run_pin(
const std::string& tool,
const std::vector<std::string>& args) {
34 std::string pin =
pin_root() +
"/pin";
35 std::vector<char*> argv;
36 argv.push_back(
const_cast<char*
>(pin.c_str()));
37 argv.push_back(
const_cast<char*
>(
"-t"));
38 argv.push_back(
const_cast<char*
>(tool.c_str()));
39 argv.push_back(
const_cast<char*
>(
"--"));
40 for (
auto&
a : args) argv.push_back(
const_cast<char*
>(
a.c_str()));
41 argv.push_back(
nullptr);
44 if (pid < 0)
return -1;
46 if (!
env(
"CCTLIB_TEST_VERBOSE").size()) {
47 int devnull = open(
"/dev/null", O_WRONLY);
48 if (devnull >= 0) { dup2(devnull, 1); dup2(devnull, 2); close(devnull); }
50 execv(pin.c_str(), argv.data());
54 if (waitpid(pid, &
status, 0) < 0)
return -1;
59 std::string
find_newest(
const std::string& dir,
const std::string& prefix) {
60 std::string cmd =
"ls -t " + dir +
"/" + prefix +
"* 2>/dev/null | head -1";
61 FILE* p = popen(cmd.c_str(),
"r");
63 char buf[4096]; std::string out;
64 if (fgets(
buf,
sizeof(
buf), p)) out =
buf;
66 if (!out.empty() && out.back() ==
'\n') out.pop_back();
70 std::ifstream in(path); std::stringstream ss; ss << in.rdbuf();
return ss.str();
72 void cleanup(
const std::string& dir,
const std::string& prefix) {
73 std::string cmd =
"rm -f " + dir +
"/" + prefix +
"*"; (void)system(cmd.c_str());
77 std::regex re(R
"(Total redundant bytes = ([\d.]+)\s*%)");
79 if (!std::regex_search(content, m, re))
return -1;
80 return std::stod(m[1]);
88 ASSERT_FALSE(
pin_root().empty()) <<
"PIN_ROOT required";
89 tool_ = root_ +
"/clients/obj-intel64/loadspy_client.so";
90 ASSERT_EQ(0, access(tool_.c_str(), F_OK)) << tool_ <<
" missing";
91 ASSERT_EQ(0, chdir(root_.c_str())) <<
"chdir failed";
97 int rc =
run_pin(tool_, {victim});
98 EXPECT_EQ(0, rc) <<
"loadspy on " << victim <<
" returned " << rc;
99 std::string out =
find_newest(root_,
"redLoad.out.");
100 EXPECT_FALSE(out.empty()) <<
"no redLoad.out.* file";
106 double pct = run_and_parse_pct(
"/bin/ls");
108 EXPECT_LT(pct, 100.0);
121 double tp = run_and_parse_pct(root_ +
"/tests/gtest/obj/apps/loadspy_tp_simple");
122 double tn = run_and_parse_pct(root_ +
"/tests/gtest/obj/apps/loadspy_tn_simple");
125 EXPECT_GT(tp, tn + 0.3)
126 <<
"TP=" << tp <<
"% TN=" << tn <<
"%";
132 cleanup(root_,
"redLoad.out.");
133 int rc =
run_pin(tool_, {root_ +
"/tests/gtest/obj/apps/loadspy_tp_simple"});
135 std::string out =
find_newest(root_,
"redLoad.out.");
136 ASSERT_FALSE(out.empty());
137 std::string cmd =
"grep -c 'load8:.*loadspy_tp_simple.c' " + out;
138 FILE* p = popen(cmd.c_str(),
"r");
139 ASSERT_NE(p,
nullptr);
140 char buf[64]; std::string s;
143 long hits = s.empty() ? 0 : std::stol(s);
154 public ::testing::WithParamInterface<const char*> {};
160 double tn = run_and_parse_pct(root_ +
"/tests/gtest/obj/apps/loadspy_tn_simple");
161 double isa = run_and_parse_pct(root_ +
"/tests/gtest/obj/apps/isa/" + std::string(GetParam()));
164 EXPECT_GT(isa, tn + 0.3)
165 <<
"victim=" << GetParam() <<
" isa=" << isa <<
"% tn=" << tn <<
"%";
170 cleanup(root_,
"redLoad.out.");
171 int rc =
run_pin(tool_, {root_ +
"/tests/gtest/obj/apps/isa/" + std::string(GetParam())});
173 std::string out =
find_newest(root_,
"redLoad.out.");
174 ASSERT_FALSE(out.empty());
175 std::string cmd = std::string(
"grep -c '") + GetParam() +
".c' " + out;
176 FILE* p = popen(cmd.c_str(),
"r");
177 ASSERT_NE(p,
nullptr);
178 char buf[64]; std::string s;
181 long hits = s.empty() ? 0 : std::stol(s);
190 "loadspy_repmovs_tp",
191 "loadspy_cross_page_tp",
192 "loadspy_mixed_widths_tp"
194 [](
const testing::TestParamInfo<const char*>& info) {
195 return std::string(info.param);
double run_and_parse_pct(const std::string &victim)
static uint64_t buf[ITERS]
std::string cctlib_root()
std::string find_newest(const std::string &dir, const std::string &prefix)
double parse_first_redundant_pct(const std::string &content)
void cleanup(const std::string &dir, const std::string &prefix)
INSTANTIATE_TEST_SUITE_P(IsaBreadth, LoadspyIsa, ::testing::Values("loadspy_sse16_tp", "loadspy_avx32_tp", "loadspy_repmovs_tp", "loadspy_cross_page_tp", "loadspy_mixed_widths_tp"), [](const testing::TestParamInfo< const char * > &info) { return std::string(info.param);})
std::string env(const char *name)
TEST_P(LoadspyIsa, AttributionInReport)
TEST_F(LoadspyIntegration, TPReportAttributesToLoad8)
std::string read_file(const std::string &path)
int run_pin(const std::string &tool, const std::vector< std::string > &args)