impl::temp_dir::temp_dir(const atf::fs::path& p) { atf::auto_array< char > buf(new char[p.str().length() + 1]); std::strcpy(buf.get(), p.c_str()); if (::mkdtemp(buf.get()) == NULL) throw system_error(IMPL_NAME "::temp_dir::temp_dir(" + p.str() + ")", "mkdtemp(3) failed", errno); m_path.reset(new atf::fs::path(buf.get())); }
void atf_check::print_diff(const atf::fs::path &p1, const atf::fs::path &p2) const { std::string cmd("diff -u \"" + p1.str() + "\" \"" + p2.str() + "\" >&2"); int exitcode = std::system(cmd.c_str()); if (!WIFEXITED(exitcode)) std::cerr << "Failed to run diff(3)" << std::endl; if (WEXITSTATUS(exitcode) != 1) std::cerr << "Error while running diff(3)" << std::endl; }
int tp::run_tc(const std::string& tcarg) { const std::pair< std::string, tc_part > fields = process_tcarg(tcarg); impl::tc* tc = find_tc(init_tcs(), fields.first); if (!atf::env::has("__RUNNING_INSIDE_ATF_RUN") || atf::env::get( "__RUNNING_INSIDE_ATF_RUN") != "internal-yes-value") { std::cerr << m_prog_name << ": WARNING: Running test cases without " "atf-run(1) is unsupported\n"; std::cerr << m_prog_name << ": WARNING: No isolation nor timeout " "control is being applied; you may get unexpected failures; see " "atf-test-case(4)\n"; } try { switch (fields.second) { case BODY: tc->run(m_resfile.str()); break; case CLEANUP: tc->run_cleanup(); break; default: UNREACHABLE; } return EXIT_SUCCESS; } catch (const std::runtime_error& e) { std::cerr << "ERROR: " << e.what() << "\n"; return EXIT_FAILURE; } }
void tp::handle_srcdir(void) { if (m_srcdir_arg.empty()) { m_srcdir = atf::fs::path(m_argv0).branch_path(); if (m_srcdir.leaf_name() == ".libs") m_srcdir = m_srcdir.branch_path(); } else m_srcdir = atf::fs::path(m_srcdir_arg); if (!atf::fs::exists(m_srcdir / m_prog_name)) throw std::runtime_error("Cannot find the test program in the " "source directory `" + m_srcdir.str() + "'"); if (!m_srcdir.is_absolute()) m_srcdir = m_srcdir.to_absolute(); m_vars["srcdir"] = m_srcdir.str(); }
static bool compare_files(const atf::fs::path& p1, const atf::fs::path& p2) { bool equal = false; std::ifstream f1(p1.c_str()); if (!f1) throw std::runtime_error("Failed to open " + p1.str()); std::ifstream f2(p2.c_str()); if (!f2) throw std::runtime_error("Failed to open " + p1.str()); for (;;) { char buf1[512], buf2[512]; f1.read(buf1, sizeof(buf1)); if (f1.bad()) throw std::runtime_error("Failed to read from " + p1.str()); f2.read(buf2, sizeof(buf2)); if (f2.bad()) throw std::runtime_error("Failed to read from " + p1.str()); std::cout << "1 read: " << f1.gcount() << "\n"; std::cout << "2 read: " << f2.gcount() << "\n"; if ((f1.gcount() == 0) && (f2.gcount() == 0)) { equal = true; break; } if ((f1.gcount() != f2.gcount()) || (std::memcmp(buf1, buf2, f1.gcount()) != 0)) { break; } } return equal; }
atf::fs::path impl::change_directory(const atf::fs::path& dir) { atf::fs::path olddir = get_current_dir(); if (olddir != dir) { if (::chdir(dir.c_str()) == -1) throw system_error(IMPL_NAME "::chdir(" + dir.str() + ")", "chdir(2) failed", errno); } return olddir; }
void build_check_cxx_o_aux(const atf::fs::path& sfile, const char* failmsg, const bool expect_pass) { std::vector< std::string > optargs; optargs.push_back("-I" + atf::config::get("atf_includedir")); optargs.push_back("-Wall"); optargs.push_back("-Werror"); const bool result = atf::check::build_cxx_o( sfile.str(), "test.o", atf::process::argv_array(optargs)); if ((expect_pass && !result) || (!expect_pass && result)) ATF_FAIL(failmsg); }
static void cat_file(const atf::fs::path& path) { std::ifstream stream(path.c_str()); if (!stream) throw std::runtime_error("Failed to open " + path.str()); stream >> std::noskipws; std::istream_iterator< char > begin(stream), end; std::ostream_iterator< char > out(std::cerr); std::copy(begin, end, out); stream.close(); }
static void cleanup_aux_dir(const atf::fs::path& p, const atf::fs::file_info& fi, bool erase) { if (erase && ((fi.get_mode() & S_IRWXU) != S_IRWXU)) { int retries = max_retries; retry_chmod: if (chmod(p.c_str(), fi.get_mode() | S_IRWXU) == -1) { if (retries > 0) { retries--; ::sleep(retry_delay_in_seconds); goto retry_chmod; } else { throw atf::system_error(IMPL_NAME "::cleanup(" + p.str() + ")", "chmod(2) failed", errno); } } } std::set< std::string > subdirs; { bool ok = false; int retries = max_retries; while (!ok) { INV(retries > 0); try { const atf::fs::directory d(p); subdirs = d.names(); ok = true; } catch (const atf::system_error& e) { retries--; if (retries == 0) throw e; ::sleep(retry_delay_in_seconds); } } INV(ok); } for (std::set< std::string >::const_iterator iter = subdirs.begin(); iter != subdirs.end(); iter++) { const std::string& name = *iter; if (name != "." && name != "..") cleanup_aux(p / name, fi.get_device(), erase); } }
impl::test_case_result impl::read_test_case_result(const atf::fs::path& results_path) { std::ifstream results_file(results_path.c_str()); if (!results_file) throw std::runtime_error("Failed to open " + results_path.str()); std::string line, extra_line; std::getline(results_file, line); if (!results_file.good()) throw std::runtime_error("Results file is empty"); while (std::getline(results_file, extra_line).good()) line += "<<NEWLINE UNEXPECTED>>" + extra_line; results_file.close(); return detail::parse_test_case_result(line); }
static bool grep_file(const atf::fs::path& path, const std::string& regexp) { std::ifstream stream(path.c_str()); if (!stream) throw std::runtime_error("Failed to open " + path.str()); bool found = false; std::string line; while (!found && std::getline(stream, line).good()) { if (atf::text::match(line, regexp)) found = true; } stream.close(); return found; }
static void do_unmount(const atf::fs::path& in_path) { // At least, FreeBSD's unmount(2) requires the path to be absolute. // Let's make it absolute in all cases just to be safe that this does // not affect other systems. const atf::fs::path& abs_path = in_path.is_absolute() ? in_path : in_path.to_absolute(); #if defined(HAVE_UNMOUNT) int retries = max_retries; retry_unmount: if (unmount(abs_path.c_str(), 0) == -1) { if (errno == EBUSY && retries > 0) { retries--; ::sleep(retry_delay_in_seconds); goto retry_unmount; } else { throw atf::system_error(IMPL_NAME "::cleanup(" + in_path.str() + ")", "unmount(2) failed", errno); } } #else // We could use umount(2) instead if it was available... but // trying to do so under, e.g. Linux, is a nightmare because we // also have to update /etc/mtab to match what we did. It is // satf::fser to just leave the system-specific umount(8) tool deal // with it, at least for now. const atf::fs::path prog("umount"); atf::process::argv_array argv("umount", abs_path.c_str(), NULL); atf::process::status s = atf::process::exec(prog, argv, atf::process::stream_inherit(), atf::process::stream_inherit()); if (!s.exited() || s.exitstatus() != EXIT_SUCCESS) throw std::runtime_error("Call to unmount failed"); #endif }
int tp::run_tc(const std::string& tcarg) { const std::pair< std::string, tc_part > fields = process_tcarg(tcarg); impl::tc* tc = find_tc(init_tcs(), fields.first); try { switch (fields.second) { case BODY: tc->run(m_resfile.str()); break; case CLEANUP: tc->run_cleanup(); break; default: UNREACHABLE; } return EXIT_SUCCESS; } catch (const std::runtime_error& e) { std::cerr << "ERROR: " << e.what() << "\n"; return EXIT_FAILURE; } }