diff --git a/test/dwarfs_tools.cpp b/test/dwarfs_tools.cpp index d831d7c3..1ea5afd2 100644 --- a/test/dwarfs_tools.cpp +++ b/test/dwarfs_tools.cpp @@ -26,11 +26,13 @@ #include #include +#ifndef _WIN32 #include #include #include #include #include +#endif #include #include @@ -60,6 +62,7 @@ auto dwarfsck_bin = tools_dir / "dwarfsck"; auto diff_bin = std::filesystem::path(DIFF_BIN); auto tar_bin = std::filesystem::path(TAR_BIN); +#ifndef _WIN32 pid_t get_dwarfs_pid(std::filesystem::path const& path) { std::array attr_buf; auto attr_len = ::getxattr(path.c_str(), "user.dwarfs.driver.pid", @@ -69,6 +72,7 @@ pid_t get_dwarfs_pid(std::filesystem::path const& path) { } return folly::to(std::string_view(attr_buf.data(), attr_len)); } +#endif namespace bp = boost::process; @@ -105,6 +109,8 @@ class subprocess { pt_.reset(); } + void interrupt() { ::kill(pid(), SIGINT); } + std::string const& out() const { return outs_; } std::string const& err() const { return errs_; } @@ -157,6 +163,7 @@ class subprocess { std::unique_ptr pt_; }; +#ifndef _WIN32 class process_guard { public: process_guard() = default; @@ -194,37 +201,89 @@ class process_guard { pid_t pid_{-1}; int proc_dir_fd_{-1}; }; +#endif class driver_runner { public: - driver_runner() - : fusermount_{find_fusermount()} {} + struct foreground_t {}; + static constexpr foreground_t foreground = foreground_t(); + + driver_runner() = default; template driver_runner(std::filesystem::path const& driver, std::filesystem::path const& image, std::filesystem::path const& mountpoint, Args&&... args) - : fusermount_{find_fusermount()} - , mountpoint_{mountpoint} { + : mountpoint_{mountpoint} { + setup_mountpoint(mountpoint); +#ifdef _WIN32 + process_ = std::make_unique(driver, image, mountpoint, + std::forward(args)...); + process_->run_background(); +#else if (!subprocess::check_run(driver, image, mountpoint, std::forward(args)...)) { throw std::runtime_error("error running " + driver.string()); } - auto dwarfs_pid = get_dwarfs_pid(mountpoint); - dwarfs_guard_ = process_guard(dwarfs_pid); + dwarfs_guard_ = process_guard(get_dwarfs_pid(mountpoint)); +#endif + } + + template + driver_runner(foreground_t, std::filesystem::path const& driver, + std::filesystem::path const& image, + std::filesystem::path const& mountpoint, Args&&... args) + : mountpoint_{mountpoint} { + setup_mountpoint(mountpoint); + process_ = std::make_unique(driver, image, mountpoint, +#ifndef _WIN32 + "-f", +#endif + std::forward(args)...); + process_->run_background(); +#ifndef _WIN32 + dwarfs_guard_ = process_guard(process_->pid()); +#endif + } + + bool unmount() { + if (!mountpoint_.empty()) { +#ifndef _WIN32 + if (process_) { +#endif + constexpr int expected_exit_code = SIGINT; + process_->interrupt(); + process_->wait(); // TODO: wait_for? + auto ec = process_->exit_code(); + if (ec != expected_exit_code) { + std::cerr << "driver failed to unmount:\nout:\n" + << process_->out() << "err:\n" + << process_->err() << "exit code: " << ec << "\n"; + } + process_.reset(); + mountpoint_.clear(); + return ec == expected_exit_code; +#ifndef _WIN32 + } else { + subprocess::check_run(find_fusermount(), "-u", mountpoint_); + mountpoint_.clear(); + return dwarfs_guard_.check_exit(std::chrono::seconds(5)); +#endif + } + } + return false; } ~driver_runner() { - subprocess::check_run(fusermount_, "-u", mountpoint_); - EXPECT_TRUE(dwarfs_guard_.check_exit(std::chrono::seconds(5))); - } - - static bool umount(std::filesystem::path const& mountpoint) { - return static_cast( - subprocess::check_run(find_fusermount(), "-u", mountpoint)); + if (!mountpoint_.empty()) { + if (!unmount()) { + ::abort(); + } + } } private: +#ifndef _WIN32 static std::filesystem::path find_fusermount() { auto fusermount_bin = dwarfs::test::find_binary("fusermount"); if (!fusermount_bin) { @@ -235,10 +294,22 @@ class driver_runner { } return *fusermount_bin; } +#endif - std::filesystem::path const fusermount_; - std::filesystem::path const mountpoint_; + static void setup_mountpoint(std::filesystem::path const& mp) { + if (std::filesystem::exists(mp)) { + std::filesystem::remove(mp); + } +#ifndef _WIN32 + std::filesystem::create_directory(mp); +#endif + } + + std::filesystem::path mountpoint_; + std::unique_ptr process_; +#ifndef _WIN32 process_guard dwarfs_guard_; +#endif }; bool wait_until_file_ready(std::filesystem::path const& path, @@ -315,8 +386,6 @@ TEST(tools, everything) { auto extracted = td / "extracted"; auto untared = td / "untared"; - ASSERT_TRUE(std::filesystem::create_directory(mountpoint)); - std::vector drivers; drivers.push_back(fuse3_bin); @@ -331,18 +400,15 @@ TEST(tools, everything) { for (auto const& driver : drivers) { { - auto p = subprocess(driver, image, mountpoint, "-f"); - p.run_background(); + driver_runner runner(driver_runner::foreground, driver, image, + mountpoint); ASSERT_TRUE(wait_until_file_ready(mountpoint / "format.sh", timeout)); ASSERT_TRUE( subprocess::check_run(diff_bin, "-qruN", data_dir, mountpoint)); EXPECT_EQ(1, num_hardlinks(mountpoint / "format.sh")); - driver_runner::umount(mountpoint); - p.wait(); - - EXPECT_EQ(p.exit_code(), 0); + EXPECT_TRUE(runner.unmount()); } {