Better debug output in tools test

This commit is contained in:
Marcus Holland-Moritz 2023-07-03 20:39:49 +02:00
parent dc0cd6fcd9
commit 6056aa87c8

View File

@ -262,12 +262,12 @@ struct new_process_group : public ::boost::process::detail::handler_base {
class subprocess { class subprocess {
public: public:
template <typename... Args> template <typename... Args>
subprocess(std::filesystem::path const& prog, Args&&... args) { subprocess(std::filesystem::path const& prog, Args&&... args)
std::vector<std::string> cmdline; : prog_{prog} {
(append_arg(cmdline, std::forward<Args>(args)), ...); (append_arg(cmdline_, std::forward<Args>(args)), ...);
try { try {
c_ = bp::child(prog.string(), bp::args(cmdline), bp::std_in.close(), c_ = bp::child(prog.string(), bp::args(cmdline_), bp::std_in.close(),
bp::std_out > out_, bp::std_err > err_, ios_ bp::std_out > out_, bp::std_err > err_, ios_
#ifdef _WIN32 #ifdef _WIN32
, ,
@ -275,12 +275,20 @@ class subprocess {
#endif #endif
); );
} catch (...) { } catch (...) {
std::cerr << "failed to create subprocess: " << prog << " " std::cerr << "failed to create subprocess: " << cmdline() << "\n";
<< folly::join(' ', cmdline) << "\n";
throw; throw;
} }
} }
std::string cmdline() const {
std::string cmd = prog_.string();
if (!cmdline_.empty()) {
cmd += ' ';
cmd += folly::join(' ', cmdline_);
}
return cmd;
}
void run() { void run() {
ios_.run(); ios_.run();
c_.wait(); c_.wait();
@ -360,6 +368,8 @@ class subprocess {
std::string outs_; std::string outs_;
std::string errs_; std::string errs_;
std::unique_ptr<std::thread> pt_; std::unique_ptr<std::thread> pt_;
std::filesystem::path const prog_;
std::vector<std::string> cmdline_;
}; };
#ifndef _WIN32 #ifndef _WIN32
@ -476,6 +486,14 @@ class driver_runner {
return false; return false;
} }
std::string cmdline() const {
std::string rv;
if (process_) {
rv = process_->cmdline();
}
return rv;
}
~driver_runner() { ~driver_runner() {
if (!mountpoint_.empty()) { if (!mountpoint_.empty()) {
if (!unmount()) { if (!unmount()) {
@ -621,30 +639,39 @@ TEST(tools, end_to_end) {
driver_runner runner(driver_runner::foreground, driver, image, driver_runner runner(driver_runner::foreground, driver, image,
mountpoint); mountpoint);
ASSERT_TRUE(wait_until_file_ready(mountpoint / "format.sh", timeout)); ASSERT_TRUE(wait_until_file_ready(mountpoint / "format.sh", timeout))
<< runner.cmdline();
compare_directories_result cdr; compare_directories_result cdr;
ASSERT_TRUE(compare_directories(fsdata_dir, mountpoint, &cdr)) << cdr; ASSERT_TRUE(compare_directories(fsdata_dir, mountpoint, &cdr))
EXPECT_EQ(cdr.regular_files.size(), 26) << cdr; << runner.cmdline() << ": " << cdr;
EXPECT_EQ(cdr.directories.size(), 19) << cdr; EXPECT_EQ(cdr.regular_files.size(), 26)
EXPECT_EQ(cdr.symlinks.size(), 2) << cdr; << runner.cmdline() << ": " << cdr;
EXPECT_EQ(1, num_hardlinks(mountpoint / "format.sh")); EXPECT_EQ(cdr.directories.size(), 19) << runner.cmdline() << ": " << cdr;
EXPECT_EQ(cdr.symlinks.size(), 2) << runner.cmdline() << ": " << cdr;
EXPECT_EQ(1, num_hardlinks(mountpoint / "format.sh")) << runner.cmdline();
EXPECT_TRUE(fs::is_symlink(unicode_symlink)); EXPECT_TRUE(fs::is_symlink(unicode_symlink)) << runner.cmdline();
EXPECT_EQ(fs::read_symlink(unicode_symlink), unicode_symlink_target); EXPECT_EQ(fs::read_symlink(unicode_symlink), unicode_symlink_target)
EXPECT_TRUE(read_file(unicode_symlink, unicode_file_contents)); << runner.cmdline();
EXPECT_EQ(unicode_file_contents, "unicode\n"); EXPECT_TRUE(read_file(unicode_symlink, unicode_file_contents))
EXPECT_TRUE(read_file(mountpoint / unicode_symlink_target, << runner.cmdline();
unicode_file_contents)); EXPECT_EQ(unicode_file_contents, "unicode\n") << runner.cmdline();
EXPECT_EQ(unicode_file_contents, "unicode\n"); EXPECT_TRUE(
read_file(mountpoint / unicode_symlink_target, unicode_file_contents))
<< runner.cmdline();
EXPECT_EQ(unicode_file_contents, "unicode\n") << runner.cmdline();
EXPECT_TRUE(runner.unmount()); EXPECT_TRUE(runner.unmount()) << runner.cmdline();
} }
{ {
auto const [out, err, ec] = auto const [out, err, ec] =
subprocess::run(driver, image_hdr, mountpoint); subprocess::run(driver, image_hdr, mountpoint);
EXPECT_NE(0, ec) << "stdout:\n" << out << "\nstderr:\n" << err; EXPECT_NE(0, ec) << driver << "\n"
<< "stdout:\n"
<< out << "\nstderr:\n"
<< err;
} }
unsigned const combinations = 1 << all_options.size(); unsigned const combinations = 1 << all_options.size();
@ -670,21 +697,27 @@ TEST(tools, end_to_end) {
{ {
driver_runner runner(driver, image, mountpoint, args); driver_runner runner(driver, image, mountpoint, args);
ASSERT_TRUE(wait_until_file_ready(mountpoint / "format.sh", timeout)); ASSERT_TRUE(wait_until_file_ready(mountpoint / "format.sh", timeout))
EXPECT_TRUE(fs::is_symlink(mountpoint / "foobar")); << runner.cmdline();
EXPECT_TRUE(fs::is_symlink(mountpoint / "foobar")) << runner.cmdline();
EXPECT_EQ(fs::read_symlink(mountpoint / "foobar"), EXPECT_EQ(fs::read_symlink(mountpoint / "foobar"),
fs::path("foo") / "bar"); fs::path("foo") / "bar")
<< runner.cmdline();
compare_directories_result cdr; compare_directories_result cdr;
ASSERT_TRUE(compare_directories(fsdata_dir, mountpoint, &cdr)) << cdr; ASSERT_TRUE(compare_directories(fsdata_dir, mountpoint, &cdr))
EXPECT_EQ(cdr.regular_files.size(), 26) << cdr; << runner.cmdline() << ": " << cdr;
EXPECT_EQ(cdr.directories.size(), 19) << cdr; EXPECT_EQ(cdr.regular_files.size(), 26)
EXPECT_EQ(cdr.symlinks.size(), 2) << cdr; << runner.cmdline() << ": " << cdr;
EXPECT_EQ(cdr.directories.size(), 19)
<< runner.cmdline() << ": " << cdr;
EXPECT_EQ(cdr.symlinks.size(), 2) << runner.cmdline() << ": " << cdr;
#ifndef _WIN32 #ifndef _WIN32
// TODO: https://github.com/winfsp/winfsp/issues/511 // TODO: https://github.com/winfsp/winfsp/issues/511
EXPECT_EQ(enable_nlink ? 3 : 1, EXPECT_EQ(enable_nlink ? 3 : 1, num_hardlinks(mountpoint / "format.sh"))
num_hardlinks(mountpoint / "format.sh")); << runner.cmdline();
// This doesn't really work on Windows (yet) // This doesn't really work on Windows (yet)
EXPECT_TRUE(check_readonly(mountpoint / "format.sh", readonly)); EXPECT_TRUE(check_readonly(mountpoint / "format.sh", readonly))
<< runner.cmdline();
#endif #endif
} }
@ -693,21 +726,27 @@ TEST(tools, end_to_end) {
{ {
driver_runner runner(driver, image_hdr, mountpoint, args); driver_runner runner(driver, image_hdr, mountpoint, args);
ASSERT_TRUE(wait_until_file_ready(mountpoint / "format.sh", timeout)); ASSERT_TRUE(wait_until_file_ready(mountpoint / "format.sh", timeout))
EXPECT_TRUE(fs::is_symlink(mountpoint / "foobar")); << runner.cmdline();
EXPECT_TRUE(fs::is_symlink(mountpoint / "foobar")) << runner.cmdline();
EXPECT_EQ(fs::read_symlink(mountpoint / "foobar"), EXPECT_EQ(fs::read_symlink(mountpoint / "foobar"),
fs::path("foo") / "bar"); fs::path("foo") / "bar")
<< runner.cmdline();
compare_directories_result cdr; compare_directories_result cdr;
ASSERT_TRUE(compare_directories(fsdata_dir, mountpoint, &cdr)) << cdr; ASSERT_TRUE(compare_directories(fsdata_dir, mountpoint, &cdr))
EXPECT_EQ(cdr.regular_files.size(), 26) << cdr; << runner.cmdline() << ": " << cdr;
EXPECT_EQ(cdr.directories.size(), 19) << cdr; EXPECT_EQ(cdr.regular_files.size(), 26)
EXPECT_EQ(cdr.symlinks.size(), 2) << cdr; << runner.cmdline() << ": " << cdr;
EXPECT_EQ(cdr.directories.size(), 19)
<< runner.cmdline() << ": " << cdr;
EXPECT_EQ(cdr.symlinks.size(), 2) << runner.cmdline() << ": " << cdr;
#ifndef _WIN32 #ifndef _WIN32
// TODO: https://github.com/winfsp/winfsp/issues/511 // TODO: https://github.com/winfsp/winfsp/issues/511
EXPECT_EQ(enable_nlink ? 3 : 1, EXPECT_EQ(enable_nlink ? 3 : 1, num_hardlinks(mountpoint / "format.sh"))
num_hardlinks(mountpoint / "format.sh")); << runner.cmdline();
// This doesn't really work on Windows (yet) // This doesn't really work on Windows (yet)
EXPECT_TRUE(check_readonly(mountpoint / "format.sh", readonly)); EXPECT_TRUE(check_readonly(mountpoint / "format.sh", readonly))
<< runner.cmdline();
#endif #endif
} }
} }
@ -750,14 +789,14 @@ TEST(tools, end_to_end) {
#ifdef _WIN32 #ifdef _WIN32
#define EXPECT_EC_UNIX_WIN(ec, unix, windows) \ #define EXPECT_EC_UNIX_WIN(ec, unix, windows) \
EXPECT_TRUE(ec); \ EXPECT_TRUE(ec) << runner.cmdline(); \
EXPECT_EQ(std::system_category(), (ec).category()); \ EXPECT_EQ(std::system_category(), (ec).category()) << runner.cmdline(); \
EXPECT_EQ(windows, (ec).value()) << (ec).message() EXPECT_EQ(windows, (ec).value()) << runner.cmdline() << ": " << (ec).message()
#else #else
#define EXPECT_EC_UNIX_WIN(ec, unix, windows) \ #define EXPECT_EC_UNIX_WIN(ec, unix, windows) \
EXPECT_TRUE(ec); \ EXPECT_TRUE(ec) << runner.cmdline(); \
EXPECT_EQ(std::generic_category(), (ec).category()); \ EXPECT_EQ(std::generic_category(), (ec).category()) << runner.cmdline(); \
EXPECT_EQ(unix, (ec).value()) << (ec).message() EXPECT_EQ(unix, (ec).value()) << runner.cmdline() << ": " << (ec).message()
#endif #endif
TEST(tools, mutating_ops) { TEST(tools, mutating_ops) {
@ -782,32 +821,34 @@ TEST(tools, mutating_ops) {
driver_runner runner(driver_runner::foreground, driver, test_data_dwarfs, driver_runner runner(driver_runner::foreground, driver, test_data_dwarfs,
mountpoint); mountpoint);
ASSERT_TRUE(wait_until_file_ready(mountpoint / "format.sh", timeout)); ASSERT_TRUE(wait_until_file_ready(mountpoint / "format.sh", timeout))
<< runner.cmdline();
// remove (unlink) // remove (unlink)
{ {
std::error_code ec; std::error_code ec;
EXPECT_FALSE(fs::remove(file, ec)); EXPECT_FALSE(fs::remove(file, ec)) << runner.cmdline();
EXPECT_EC_UNIX_WIN(ec, ENOSYS, ERROR_ACCESS_DENIED); EXPECT_EC_UNIX_WIN(ec, ENOSYS, ERROR_ACCESS_DENIED);
} }
{ {
std::error_code ec; std::error_code ec;
EXPECT_FALSE(fs::remove(empty_dir, ec)); EXPECT_FALSE(fs::remove(empty_dir, ec)) << runner.cmdline();
EXPECT_EC_UNIX_WIN(ec, ENOSYS, ERROR_ACCESS_DENIED); EXPECT_EC_UNIX_WIN(ec, ENOSYS, ERROR_ACCESS_DENIED);
} }
{ {
std::error_code ec; std::error_code ec;
EXPECT_FALSE(fs::remove(non_empty_dir, ec)); EXPECT_FALSE(fs::remove(non_empty_dir, ec)) << runner.cmdline();
EXPECT_EC_UNIX_WIN(ec, ENOSYS, ERROR_ACCESS_DENIED); EXPECT_EC_UNIX_WIN(ec, ENOSYS, ERROR_ACCESS_DENIED);
} }
{ {
std::error_code ec; std::error_code ec;
EXPECT_EQ(static_cast<std::uintmax_t>(-1), EXPECT_EQ(static_cast<std::uintmax_t>(-1),
fs::remove_all(non_empty_dir, ec)); fs::remove_all(non_empty_dir, ec))
<< runner.cmdline();
EXPECT_EC_UNIX_WIN(ec, ENOSYS, ERROR_ACCESS_DENIED); EXPECT_EC_UNIX_WIN(ec, ENOSYS, ERROR_ACCESS_DENIED);
} }
@ -862,8 +903,8 @@ TEST(tools, mutating_ops) {
{ {
std::error_code ec; std::error_code ec;
fs::create_symlink(file, name_outside_fs, ec); fs::create_symlink(file, name_outside_fs, ec);
EXPECT_FALSE(ec); // this actually works :) EXPECT_FALSE(ec) << runner.cmdline(); // this actually works :)
EXPECT_TRUE(fs::remove(name_outside_fs, ec)); EXPECT_TRUE(fs::remove(name_outside_fs, ec)) << runner.cmdline();
} }
{ {
@ -875,8 +916,8 @@ TEST(tools, mutating_ops) {
{ {
std::error_code ec; std::error_code ec;
fs::create_directory_symlink(empty_dir, name_outside_fs, ec); fs::create_directory_symlink(empty_dir, name_outside_fs, ec);
EXPECT_FALSE(ec); // this actually works :) EXPECT_FALSE(ec) << runner.cmdline(); // this actually works :)
EXPECT_TRUE(fs::remove(name_outside_fs, ec)); EXPECT_TRUE(fs::remove(name_outside_fs, ec)) << runner.cmdline();
} }
// truncate // truncate
@ -895,6 +936,6 @@ TEST(tools, mutating_ops) {
EXPECT_EC_UNIX_WIN(ec, ENOSYS, ERROR_ACCESS_DENIED); EXPECT_EC_UNIX_WIN(ec, ENOSYS, ERROR_ACCESS_DENIED);
} }
EXPECT_TRUE(runner.unmount()); EXPECT_TRUE(runner.unmount()) << runner.cmdline();
} }
} }