27 #include <gtest/gtest.h>
31 std::string
env(
const char* n) {
const char* v = getenv(n);
return v ? v :
""; }
33 std::string r =
env(
"CCTLIB_ROOT");
34 return r.empty() ?
"../.." : r;
39 int run_pin(
const std::string& tool,
const std::string& victim,
40 const std::vector<std::string>& extra_args = {}) {
41 std::string pin =
pin_root() +
"/pin";
42 std::vector<char*> argv;
43 argv.push_back(
const_cast<char*
>(pin.c_str()));
44 argv.push_back(
const_cast<char*
>(
"-t"));
45 argv.push_back(
const_cast<char*
>(tool.c_str()));
46 argv.push_back(
const_cast<char*
>(
"--"));
47 argv.push_back(
const_cast<char*
>(victim.c_str()));
48 for (
auto&
a : extra_args) argv.push_back(
const_cast<char*
>(
a.c_str()));
49 argv.push_back(
nullptr);
52 if (pid < 0)
return -1;
54 if (
env(
"CCTLIB_TEST_VERBOSE").empty()) {
55 int devnull = open(
"/dev/null", O_WRONLY);
56 if (devnull >= 0) { dup2(devnull, 1); dup2(devnull, 2); close(devnull); }
58 execv(pin.c_str(), argv.data());
62 if (waitpid(pid, &
status, 0) < 0)
return -1;
64 return -128 - WTERMSIG(
status);
69 std::string cmd =
"ls " + dir +
"/" + prefix +
"* >/dev/null 2>&1";
70 return system(cmd.c_str()) == 0;
74 void cleanup(
const std::string& dir,
const std::string& prefix) {
75 std::string cmd =
"rm -f " + dir +
"/" + prefix +
"*";
76 (void)system(cmd.c_str());
87 {
"deadspy",
"deadspy_client.so",
"deadspy.out." },
88 {
"redspy",
"redspy_client.so",
"redspy.out." },
89 {
"loadspy",
"loadspy_client.so",
"redLoad.out." },
98 {
"exc_simple_throw" },
99 {
"exc_deep_unwind" },
102 {
"exc_dtor_cleanup" },
103 {
"exc_stress_loop" },
104 {
"exc_polymorphic" },
106 {
"exc_uncaught_tn" },
107 {
"exc_ctor_throw" },
108 {
"exc_catch_and_resume" },
110 {
"sig_sigsegv_recover" },
114 :
public ::testing::TestWithParam<std::tuple<ToolSpec, VictimSpec>> {
119 ASSERT_FALSE(
pin_root().empty()) <<
"PIN_ROOT required";
122 ASSERT_EQ(0, chdir(root_.c_str())) <<
"chdir(" << root_ <<
") failed";
127 auto [tool, victim] = GetParam();
137 if (std::string(tool.name) ==
"loadspy" &&
138 std::string(victim.name) ==
"sig_sigsegv_recover") {
139 GTEST_SKIP() <<
"known loadspy fault-safety bug; independent of the"
140 " cctlib exception fix under test";
143 std::string toolPath = root_ +
"/clients/obj-intel64/" + tool.soPath;
144 std::string victimPath = root_ +
"/tests/gtest/obj/apps/exceptions/" + victim.name;
145 ASSERT_EQ(0, access(toolPath.c_str(), F_OK)) << toolPath <<
" missing";
146 ASSERT_EQ(0, access(victimPath.c_str(), F_OK)) << victimPath <<
" missing";
148 cleanup(root_, tool.outPrefix);
149 int rc =
run_pin(toolPath, victimPath);
154 <<
"tool=" << tool.name <<
" victim=" << victim.name <<
" rc=" << rc
155 <<
" -- see repo root for output artifacts";
157 <<
"no " << tool.outPrefix <<
"* file produced by " << tool.name
158 <<
" for " << victim.name;
163 ::testing::Combine(::testing::ValuesIn(
kTools),
165 [](
const testing::TestParamInfo<ExceptionRun::ParamType>& info) {
167 s += std::get<0>(info.param).name;
169 s += std::get<1>(info.param).name;
bool has_output_file(const std::string &dir, const std::string &prefix)
std::string cctlib_root()
std::string env(const char *n)
TEST_P(ExceptionRun, PinExitsCleanlyAndReportIsProduced)
const VictimSpec kVictims[]
INSTANTIATE_TEST_SUITE_P(ToolAndVictim, ExceptionRun, ::testing::Combine(::testing::ValuesIn(kTools), ::testing::ValuesIn(kVictims)), [](const testing::TestParamInfo< ExceptionRun::ParamType > &info) { std::string s;s+=std::get< 0 >(info.param).name;s+="__";s+=std::get< 1 >(info.param).name;return s;})
int run_pin(const std::string &tool, const std::string &victim, const std::vector< std::string > &extra_args={})
void cleanup(const std::string &dir, const std::string &prefix)