mirror of
https://github.com/mhx/dwarfs.git
synced 2025-09-13 06:16:55 -04:00
Make dwarfs_tools test work on Windows
This commit is contained in:
parent
0c3ee8550c
commit
0c85637a06
@ -616,9 +616,7 @@ if(WITH_TESTS)
|
|||||||
gtest_discover_tests(dwarfs_test)
|
gtest_discover_tests(dwarfs_test)
|
||||||
gtest_discover_tests(dwarfs_compat_test)
|
gtest_discover_tests(dwarfs_compat_test)
|
||||||
gtest_discover_tests(dwarfs_badfs_test)
|
gtest_discover_tests(dwarfs_badfs_test)
|
||||||
if(NOT WIN32)
|
|
||||||
gtest_discover_tests(dwarfs_tools_test)
|
gtest_discover_tests(dwarfs_tools_test)
|
||||||
endif()
|
|
||||||
|
|
||||||
target_compile_definitions(dwarfs_compat_test
|
target_compile_definitions(dwarfs_compat_test
|
||||||
PRIVATE TEST_DATA_DIR=\"${CMAKE_SOURCE_DIR}/test\")
|
PRIVATE TEST_DATA_DIR=\"${CMAKE_SOURCE_DIR}/test\")
|
||||||
|
@ -49,6 +49,8 @@
|
|||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include "dwarfs/file_stat.h"
|
||||||
|
|
||||||
#include "test_helpers.h"
|
#include "test_helpers.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -56,17 +58,23 @@ namespace {
|
|||||||
namespace bp = boost::process;
|
namespace bp = boost::process;
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
auto data_archive = fs::path(TEST_DATA_DIR) / "data.tar";
|
auto data_archive = fs::path(TEST_DATA_DIR).make_preferred() / "data.tar";
|
||||||
|
|
||||||
auto tools_dir = fs::path(TOOLS_BIN_DIR);
|
#ifdef _WIN32
|
||||||
auto mkdwarfs_bin = tools_dir / "mkdwarfs";
|
#define EXE_EXT ".exe"
|
||||||
auto fuse3_bin = tools_dir / "dwarfs";
|
#else
|
||||||
auto fuse2_bin = tools_dir / "dwarfs2";
|
#define EXE_EXT ""
|
||||||
auto dwarfsextract_bin = tools_dir / "dwarfsextract";
|
#endif
|
||||||
auto dwarfsck_bin = tools_dir / "dwarfsck";
|
|
||||||
|
|
||||||
auto diff_bin = fs::path(DIFF_BIN);
|
auto tools_dir = fs::path(TOOLS_BIN_DIR).make_preferred();
|
||||||
auto tar_bin = fs::path(TAR_BIN);
|
auto mkdwarfs_bin = tools_dir / "mkdwarfs" EXE_EXT;
|
||||||
|
auto fuse3_bin = tools_dir / "dwarfs" EXE_EXT;
|
||||||
|
auto fuse2_bin = tools_dir / "dwarfs2" EXE_EXT;
|
||||||
|
auto dwarfsextract_bin = tools_dir / "dwarfsextract" EXE_EXT;
|
||||||
|
auto dwarfsck_bin = tools_dir / "dwarfsck" EXE_EXT;
|
||||||
|
|
||||||
|
auto diff_bin = fs::path(DIFF_BIN).make_preferred();
|
||||||
|
auto tar_bin = fs::path(TAR_BIN).make_preferred();
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pid_t get_dwarfs_pid(fs::path const& path) {
|
pid_t get_dwarfs_pid(fs::path const& path) {
|
||||||
@ -80,19 +88,49 @@ pid_t get_dwarfs_pid(fs::path const& path) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool wait_until_file_ready(fs::path const& path,
|
||||||
|
std::chrono::milliseconds timeout) {
|
||||||
|
auto end = std::chrono::steady_clock::now() + timeout;
|
||||||
|
std::error_code ec;
|
||||||
|
while (!fs::exists(path, ec)) {
|
||||||
|
if (ec) {
|
||||||
|
std::cerr << "*** exists: " << ec.message() << "\n";
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
if (std::chrono::steady_clock::now() >= end) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
struct new_process_group : public ::boost::process::detail::handler_base {
|
||||||
|
template <class WindowsExecutor>
|
||||||
|
void on_setup(WindowsExecutor& e [[maybe_unused]]) const {
|
||||||
|
e.creation_flags |= CREATE_NEW_PROCESS_GROUP;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
class subprocess {
|
class subprocess {
|
||||||
public:
|
public:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
subprocess(Args&&... args) {
|
subprocess(std::filesystem::path const& prog, Args&&... args) {
|
||||||
std::vector<std::string> cmdline;
|
std::vector<std::string> cmdline;
|
||||||
(append_arg(cmdline, std::forward<Args>(args)), ...);
|
(append_arg(cmdline, std::forward<Args>(args)), ...);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
c_ = bp::child(bp::args(cmdline), bp::std_in.close(), bp::std_out > out_,
|
c_ = bp::child(prog.string(), bp::args(cmdline), bp::std_in.close(),
|
||||||
bp::std_err > err_, ios_);
|
bp::std_out > out_, bp::std_err > err_, ios_
|
||||||
|
#ifdef _WIN32
|
||||||
|
,
|
||||||
|
new_process_group()
|
||||||
|
#endif
|
||||||
|
);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
std::cerr << "failed to create subprocess: " << folly::join(' ', cmdline)
|
std::cerr << "failed to create subprocess: " << prog << " "
|
||||||
<< "\n";
|
<< folly::join(' ', cmdline) << "\n";
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -233,6 +271,8 @@ class driver_runner {
|
|||||||
process_ = std::make_unique<subprocess>(driver, image, mountpoint,
|
process_ = std::make_unique<subprocess>(driver, image, mountpoint,
|
||||||
std::forward<Args>(args)...);
|
std::forward<Args>(args)...);
|
||||||
process_->run_background();
|
process_->run_background();
|
||||||
|
|
||||||
|
wait_until_file_ready(mountpoint, std::chrono::seconds(5));
|
||||||
#else
|
#else
|
||||||
if (!subprocess::check_run(driver, image, mountpoint,
|
if (!subprocess::check_run(driver, image, mountpoint,
|
||||||
std::forward<Args>(args)...)) {
|
std::forward<Args>(args)...)) {
|
||||||
@ -269,7 +309,7 @@ class driver_runner {
|
|||||||
constexpr int expected_exit_code = SIGINT;
|
constexpr int expected_exit_code = SIGINT;
|
||||||
#endif
|
#endif
|
||||||
process_->interrupt();
|
process_->interrupt();
|
||||||
process_->wait(); // TODO: wait_for?
|
process_->wait();
|
||||||
auto ec = process_->exit_code();
|
auto ec = process_->exit_code();
|
||||||
if (ec != expected_exit_code) {
|
if (ec != expected_exit_code) {
|
||||||
std::cerr << "driver failed to unmount:\nout:\n"
|
std::cerr << "driver failed to unmount:\nout:\n"
|
||||||
@ -328,18 +368,6 @@ class driver_runner {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
bool wait_until_file_ready(fs::path const& path,
|
|
||||||
std::chrono::milliseconds timeout) {
|
|
||||||
auto end = std::chrono::steady_clock::now() + timeout;
|
|
||||||
while (!fs::exists(path)) {
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
||||||
if (std::chrono::steady_clock::now() >= end) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool check_readonly(fs::path const& p, bool readonly = false) {
|
bool check_readonly(fs::path const& p, bool readonly = false) {
|
||||||
auto st = fs::status(p);
|
auto st = fs::status(p);
|
||||||
bool is_writable =
|
bool is_writable =
|
||||||
@ -351,16 +379,25 @@ bool check_readonly(fs::path const& p, bool readonly = false) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
if (::access(p.string().c_str(), W_OK) == 0) {
|
if (::access(p.string().c_str(), W_OK) == 0) {
|
||||||
// access(W_OK) should never succeed
|
// access(W_OK) should never succeed
|
||||||
::perror("access");
|
::perror("access");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t num_hardlinks(fs::path const& p) { return fs::hard_link_count(p); }
|
size_t num_hardlinks(fs::path const& p) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
auto stat = dwarfs::make_file_stat(p);
|
||||||
|
return stat.nlink;
|
||||||
|
#else
|
||||||
|
return fs::hard_link_count(p);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@ -399,8 +436,14 @@ TEST(tools, everything) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> all_options{
|
std::vector<std::string> all_options{
|
||||||
"-s", "-oenable_nlink", "-oreadonly",
|
"-s",
|
||||||
"-omlock=try", "-ono_cache_image", "-ocache_files",
|
#ifndef _WIN32
|
||||||
|
"-oenable_nlink",
|
||||||
|
"-oreadonly",
|
||||||
|
#endif
|
||||||
|
"-omlock=try",
|
||||||
|
"-ono_cache_image",
|
||||||
|
"-ocache_files",
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto const& driver : drivers) {
|
for (auto const& driver : drivers) {
|
||||||
@ -446,11 +489,15 @@ TEST(tools, everything) {
|
|||||||
{
|
{
|
||||||
driver_runner runner(driver, image, mountpoint, args);
|
driver_runner runner(driver, image, mountpoint, args);
|
||||||
|
|
||||||
ASSERT_TRUE(
|
EXPECT_TRUE(
|
||||||
subprocess::check_run(diff_bin, "-qruN", data_dir, mountpoint));
|
subprocess::check_run(diff_bin, "-qruN", data_dir, mountpoint));
|
||||||
|
#ifndef _WIN32
|
||||||
|
// TODO: `tar` on Windows doesn't preserve hardlinks -> use dwarfsextract
|
||||||
EXPECT_EQ(enable_nlink ? 3 : 1,
|
EXPECT_EQ(enable_nlink ? 3 : 1,
|
||||||
num_hardlinks(mountpoint / "format.sh"));
|
num_hardlinks(mountpoint / "format.sh"));
|
||||||
|
// This doesn't really work on Windows (yet)
|
||||||
EXPECT_TRUE(check_readonly(mountpoint / "format.sh", readonly));
|
EXPECT_TRUE(check_readonly(mountpoint / "format.sh", readonly));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
args.push_back("-ooffset=auto");
|
args.push_back("-ooffset=auto");
|
||||||
@ -458,11 +505,15 @@ TEST(tools, everything) {
|
|||||||
{
|
{
|
||||||
driver_runner runner(driver, image_hdr, mountpoint, args);
|
driver_runner runner(driver, image_hdr, mountpoint, args);
|
||||||
|
|
||||||
ASSERT_TRUE(
|
EXPECT_TRUE(
|
||||||
subprocess::check_run(diff_bin, "-qruN", data_dir, mountpoint));
|
subprocess::check_run(diff_bin, "-qruN", data_dir, mountpoint));
|
||||||
|
#ifndef _WIN32
|
||||||
|
// TODO: `tar` on Windows doesn't preserve hardlinks -> use dwarfsextract
|
||||||
EXPECT_EQ(enable_nlink ? 3 : 1,
|
EXPECT_EQ(enable_nlink ? 3 : 1,
|
||||||
num_hardlinks(mountpoint / "format.sh"));
|
num_hardlinks(mountpoint / "format.sh"));
|
||||||
|
// This doesn't really work on Windows (yet)
|
||||||
EXPECT_TRUE(check_readonly(mountpoint / "format.sh", readonly));
|
EXPECT_TRUE(check_readonly(mountpoint / "format.sh", readonly));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -476,6 +527,7 @@ TEST(tools, everything) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::string header;
|
std::string header;
|
||||||
|
|
||||||
EXPECT_TRUE(folly::readFile(header_data.string().c_str(), header));
|
EXPECT_TRUE(folly::readFile(header_data.string().c_str(), header));
|
||||||
|
|
||||||
auto output = subprocess::check_run(dwarfsck_bin, image_hdr, "-H");
|
auto output = subprocess::check_run(dwarfsck_bin, image_hdr, "-H");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user