mirror of
https://github.com/mhx/dwarfs.git
synced 2025-09-09 04:19:10 -04:00
Tools test now compiles on Windows
This commit is contained in:
parent
e4b642ff0e
commit
3c4730aa69
@ -19,6 +19,8 @@
|
|||||||
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
|
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <future>
|
#include <future>
|
||||||
@ -26,7 +28,9 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifdef _WIN32
|
||||||
|
#include <folly/portability/Windows.h>
|
||||||
|
#else
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -37,11 +41,9 @@
|
|||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_service.hpp>
|
||||||
#include <boost/process.hpp>
|
#include <boost/process.hpp>
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
#include <folly/Conv.h>
|
#include <folly/Conv.h>
|
||||||
#include <folly/FileUtil.h>
|
#include <folly/FileUtil.h>
|
||||||
#include <folly/ScopeGuard.h>
|
#include <folly/String.h>
|
||||||
#include <folly/experimental/TestUtil.h>
|
#include <folly/experimental/TestUtil.h>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
@ -50,20 +52,23 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
auto data_archive = std::filesystem::path(TEST_DATA_DIR) / "data.tar";
|
namespace bp = boost::process;
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
auto tools_dir = std::filesystem::path(TOOLS_BIN_DIR);
|
auto data_archive = fs::path(TEST_DATA_DIR) / "data.tar";
|
||||||
|
|
||||||
|
auto tools_dir = fs::path(TOOLS_BIN_DIR);
|
||||||
auto mkdwarfs_bin = tools_dir / "mkdwarfs";
|
auto mkdwarfs_bin = tools_dir / "mkdwarfs";
|
||||||
auto fuse3_bin = tools_dir / "dwarfs";
|
auto fuse3_bin = tools_dir / "dwarfs";
|
||||||
auto fuse2_bin = tools_dir / "dwarfs2";
|
auto fuse2_bin = tools_dir / "dwarfs2";
|
||||||
auto dwarfsextract_bin = tools_dir / "dwarfsextract";
|
auto dwarfsextract_bin = tools_dir / "dwarfsextract";
|
||||||
auto dwarfsck_bin = tools_dir / "dwarfsck";
|
auto dwarfsck_bin = tools_dir / "dwarfsck";
|
||||||
|
|
||||||
auto diff_bin = std::filesystem::path(DIFF_BIN);
|
auto diff_bin = fs::path(DIFF_BIN);
|
||||||
auto tar_bin = std::filesystem::path(TAR_BIN);
|
auto tar_bin = fs::path(TAR_BIN);
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pid_t get_dwarfs_pid(std::filesystem::path const& path) {
|
pid_t get_dwarfs_pid(fs::path const& path) {
|
||||||
std::array<char, 32> attr_buf;
|
std::array<char, 32> attr_buf;
|
||||||
auto attr_len = ::getxattr(path.c_str(), "user.dwarfs.driver.pid",
|
auto attr_len = ::getxattr(path.c_str(), "user.dwarfs.driver.pid",
|
||||||
attr_buf.data(), attr_buf.size());
|
attr_buf.data(), attr_buf.size());
|
||||||
@ -74,8 +79,6 @@ pid_t get_dwarfs_pid(std::filesystem::path const& path) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace bp = boost::process;
|
|
||||||
|
|
||||||
class subprocess {
|
class subprocess {
|
||||||
public:
|
public:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
@ -83,8 +86,14 @@ class subprocess {
|
|||||||
std::vector<std::string> cmdline;
|
std::vector<std::string> cmdline;
|
||||||
(append_arg(cmdline, std::forward<Args>(args)), ...);
|
(append_arg(cmdline, std::forward<Args>(args)), ...);
|
||||||
|
|
||||||
c_ = bp::child(bp::args(cmdline), bp::std_in.close(), bp::std_out > out_,
|
try {
|
||||||
bp::std_err > err_, ios_);
|
c_ = bp::child(bp::args(cmdline), bp::std_in.close(), bp::std_out > out_,
|
||||||
|
bp::std_err > err_, ios_);
|
||||||
|
} catch (...) {
|
||||||
|
std::cerr << "failed to create subprocess: " << folly::join(' ', cmdline)
|
||||||
|
<< "\n";
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void run() {
|
void run() {
|
||||||
@ -109,7 +118,13 @@ class subprocess {
|
|||||||
pt_.reset();
|
pt_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void interrupt() { ::kill(pid(), SIGINT); }
|
void interrupt() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
::GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid());
|
||||||
|
#else
|
||||||
|
::kill(pid(), SIGINT);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
std::string const& out() const { return outs_; }
|
std::string const& out() const { return outs_; }
|
||||||
|
|
||||||
@ -139,8 +154,7 @@ class subprocess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void
|
static void append_arg(std::vector<std::string>& args, fs::path const& arg) {
|
||||||
append_arg(std::vector<std::string>& args, std::filesystem::path const& arg) {
|
|
||||||
args.emplace_back(arg.string());
|
args.emplace_back(arg.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,8 +184,7 @@ class process_guard {
|
|||||||
|
|
||||||
explicit process_guard(pid_t pid)
|
explicit process_guard(pid_t pid)
|
||||||
: pid_{pid} {
|
: pid_{pid} {
|
||||||
auto proc_dir =
|
auto proc_dir = fs::path("/proc") / folly::to<std::string>(pid);
|
||||||
std::filesystem::path("/proc") / folly::to<std::string>(pid);
|
|
||||||
proc_dir_fd_ = ::open(proc_dir.c_str(), O_DIRECTORY);
|
proc_dir_fd_ = ::open(proc_dir.c_str(), O_DIRECTORY);
|
||||||
|
|
||||||
if (proc_dir_fd_ < 0) {
|
if (proc_dir_fd_ < 0) {
|
||||||
@ -211,9 +224,8 @@ class driver_runner {
|
|||||||
driver_runner() = default;
|
driver_runner() = default;
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
driver_runner(std::filesystem::path const& driver,
|
driver_runner(fs::path const& driver, fs::path const& image,
|
||||||
std::filesystem::path const& image,
|
fs::path const& mountpoint, Args&&... args)
|
||||||
std::filesystem::path const& mountpoint, Args&&... args)
|
|
||||||
: mountpoint_{mountpoint} {
|
: mountpoint_{mountpoint} {
|
||||||
setup_mountpoint(mountpoint);
|
setup_mountpoint(mountpoint);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -230,9 +242,8 @@ class driver_runner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
driver_runner(foreground_t, std::filesystem::path const& driver,
|
driver_runner(foreground_t, fs::path const& driver, fs::path const& image,
|
||||||
std::filesystem::path const& image,
|
fs::path const& mountpoint, Args&&... args)
|
||||||
std::filesystem::path const& mountpoint, Args&&... args)
|
|
||||||
: mountpoint_{mountpoint} {
|
: mountpoint_{mountpoint} {
|
||||||
setup_mountpoint(mountpoint);
|
setup_mountpoint(mountpoint);
|
||||||
process_ = std::make_unique<subprocess>(driver, image, mountpoint,
|
process_ = std::make_unique<subprocess>(driver, image, mountpoint,
|
||||||
@ -251,7 +262,11 @@ class driver_runner {
|
|||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
if (process_) {
|
if (process_) {
|
||||||
#endif
|
#endif
|
||||||
constexpr int expected_exit_code = SIGINT;
|
#ifdef _WIN32
|
||||||
|
constexpr int expected_exit_code = 0;
|
||||||
|
#else
|
||||||
|
constexpr int expected_exit_code = SIGINT;
|
||||||
|
#endif
|
||||||
process_->interrupt();
|
process_->interrupt();
|
||||||
process_->wait(); // TODO: wait_for?
|
process_->wait(); // TODO: wait_for?
|
||||||
auto ec = process_->exit_code();
|
auto ec = process_->exit_code();
|
||||||
@ -268,8 +283,8 @@ class driver_runner {
|
|||||||
subprocess::check_run(find_fusermount(), "-u", mountpoint_);
|
subprocess::check_run(find_fusermount(), "-u", mountpoint_);
|
||||||
mountpoint_.clear();
|
mountpoint_.clear();
|
||||||
return dwarfs_guard_.check_exit(std::chrono::seconds(5));
|
return dwarfs_guard_.check_exit(std::chrono::seconds(5));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -284,7 +299,7 @@ class driver_runner {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
static std::filesystem::path find_fusermount() {
|
static fs::path find_fusermount() {
|
||||||
auto fusermount_bin = dwarfs::test::find_binary("fusermount");
|
auto fusermount_bin = dwarfs::test::find_binary("fusermount");
|
||||||
if (!fusermount_bin) {
|
if (!fusermount_bin) {
|
||||||
fusermount_bin = dwarfs::test::find_binary("fusermount3");
|
fusermount_bin = dwarfs::test::find_binary("fusermount3");
|
||||||
@ -296,26 +311,26 @@ class driver_runner {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void setup_mountpoint(std::filesystem::path const& mp) {
|
static void setup_mountpoint(fs::path const& mp) {
|
||||||
if (std::filesystem::exists(mp)) {
|
if (fs::exists(mp)) {
|
||||||
std::filesystem::remove(mp);
|
fs::remove(mp);
|
||||||
}
|
}
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
std::filesystem::create_directory(mp);
|
fs::create_directory(mp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path mountpoint_;
|
fs::path mountpoint_;
|
||||||
std::unique_ptr<subprocess> process_;
|
std::unique_ptr<subprocess> process_;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
process_guard dwarfs_guard_;
|
process_guard dwarfs_guard_;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
bool wait_until_file_ready(std::filesystem::path const& path,
|
bool wait_until_file_ready(fs::path const& path,
|
||||||
std::chrono::milliseconds timeout) {
|
std::chrono::milliseconds timeout) {
|
||||||
auto end = std::chrono::steady_clock::now() + timeout;
|
auto end = std::chrono::steady_clock::now() + timeout;
|
||||||
while (::access(path.c_str(), F_OK) != 0) {
|
while (!fs::exists(path)) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
if (std::chrono::steady_clock::now() >= end) {
|
if (std::chrono::steady_clock::now() >= end) {
|
||||||
return false;
|
return false;
|
||||||
@ -324,45 +339,38 @@ bool wait_until_file_ready(std::filesystem::path const& path,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_readonly(std::filesystem::path const& p, bool readonly = false) {
|
bool check_readonly(fs::path const& p, bool readonly = false) {
|
||||||
// TODO: std::filesystem
|
auto st = fs::status(p);
|
||||||
struct ::stat buf;
|
bool is_writable =
|
||||||
if (::stat(p.c_str(), &buf) != 0) {
|
(st.permissions() & fs::perms::owner_write) != fs::perms::none;
|
||||||
throw std::runtime_error("could not stat " + p.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_writable = (buf.st_mode & S_IWUSR) != 0;
|
|
||||||
|
|
||||||
if (is_writable == readonly) {
|
if (is_writable == readonly) {
|
||||||
std::cerr << "readonly=" << readonly
|
std::cerr << "readonly=" << readonly << ", st_mode="
|
||||||
<< ", st_mode=" << fmt::format("{0:o}", buf.st_mode) << std::endl;
|
<< fmt::format("{0:o}", uint16_t(st.permissions())) << "\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// TODO
|
||||||
|
#else
|
||||||
if (::access(p.c_str(), W_OK) == 0) {
|
if (::access(p.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;
|
||||||
}
|
}
|
||||||
|
|
||||||
::nlink_t num_hardlinks(std::filesystem::path const& p) {
|
size_t num_hardlinks(fs::path const& p) { return fs::hard_link_count(p); }
|
||||||
// TODO: std::filesystem
|
|
||||||
struct ::stat buf;
|
|
||||||
if (::stat(p.c_str(), &buf) != 0) {
|
|
||||||
throw std::runtime_error("could not stat " + p.string());
|
|
||||||
}
|
|
||||||
return buf.st_nlink;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST(tools, everything) {
|
TEST(tools, everything) {
|
||||||
std::chrono::seconds const timeout{5};
|
std::chrono::seconds const timeout{5};
|
||||||
folly::test::TemporaryDirectory tempdir("dwarfs");
|
folly::test::TemporaryDirectory tempdir("dwarfs");
|
||||||
auto td = std::filesystem::path(tempdir.path().string());
|
auto td = fs::path(tempdir.path().string());
|
||||||
auto image = td / "test.dwarfs";
|
auto image = td / "test.dwarfs";
|
||||||
auto image_hdr = td / "test_hdr.dwarfs";
|
auto image_hdr = td / "test_hdr.dwarfs";
|
||||||
auto data_dir = td / "data";
|
auto data_dir = td / "data";
|
||||||
@ -372,24 +380,24 @@ TEST(tools, everything) {
|
|||||||
ASSERT_TRUE(subprocess::check_run(mkdwarfs_bin, "-i", data_dir, "-o", image,
|
ASSERT_TRUE(subprocess::check_run(mkdwarfs_bin, "-i", data_dir, "-o", image,
|
||||||
"--no-progress"));
|
"--no-progress"));
|
||||||
|
|
||||||
ASSERT_TRUE(std::filesystem::exists(image));
|
ASSERT_TRUE(fs::exists(image));
|
||||||
ASSERT_GT(std::filesystem::file_size(image), 1000);
|
ASSERT_GT(fs::file_size(image), 1000);
|
||||||
|
|
||||||
ASSERT_TRUE(subprocess::check_run(mkdwarfs_bin, "-i", image, "-o", image_hdr,
|
ASSERT_TRUE(subprocess::check_run(mkdwarfs_bin, "-i", image, "-o", image_hdr,
|
||||||
"--no-progress", "--recompress=none",
|
"--no-progress", "--recompress=none",
|
||||||
"--header", header_data));
|
"--header", header_data));
|
||||||
|
|
||||||
ASSERT_TRUE(std::filesystem::exists(image_hdr));
|
ASSERT_TRUE(fs::exists(image_hdr));
|
||||||
ASSERT_GT(std::filesystem::file_size(image_hdr), 1000);
|
ASSERT_GT(fs::file_size(image_hdr), 1000);
|
||||||
|
|
||||||
auto mountpoint = td / "mnt";
|
auto mountpoint = td / "mnt";
|
||||||
auto extracted = td / "extracted";
|
auto extracted = td / "extracted";
|
||||||
auto untared = td / "untared";
|
auto untared = td / "untared";
|
||||||
|
|
||||||
std::vector<std::filesystem::path> drivers;
|
std::vector<fs::path> drivers;
|
||||||
drivers.push_back(fuse3_bin);
|
drivers.push_back(fuse3_bin);
|
||||||
|
|
||||||
if (std::filesystem::exists(fuse2_bin)) {
|
if (fs::exists(fuse2_bin)) {
|
||||||
drivers.push_back(fuse2_bin);
|
drivers.push_back(fuse2_bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,7 +479,7 @@ TEST(tools, everything) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::string header;
|
std::string header;
|
||||||
EXPECT_TRUE(folly::readFile(header_data.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");
|
||||||
|
|
||||||
@ -480,9 +488,9 @@ TEST(tools, everything) {
|
|||||||
EXPECT_EQ(header, *output);
|
EXPECT_EQ(header, *output);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_GT(std::filesystem::file_size(meta_export), 1000);
|
EXPECT_GT(fs::file_size(meta_export), 1000);
|
||||||
|
|
||||||
ASSERT_TRUE(std::filesystem::create_directory(extracted));
|
ASSERT_TRUE(fs::create_directory(extracted));
|
||||||
|
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
subprocess::check_run(dwarfsextract_bin, "-i", image, "-o", extracted));
|
subprocess::check_run(dwarfsextract_bin, "-i", image, "-o", extracted));
|
||||||
@ -493,7 +501,7 @@ TEST(tools, everything) {
|
|||||||
ASSERT_TRUE(subprocess::check_run(dwarfsextract_bin, "-i", image, "-f",
|
ASSERT_TRUE(subprocess::check_run(dwarfsextract_bin, "-i", image, "-f",
|
||||||
"gnutar", "-o", tarfile));
|
"gnutar", "-o", tarfile));
|
||||||
|
|
||||||
ASSERT_TRUE(std::filesystem::create_directory(untared));
|
ASSERT_TRUE(fs::create_directory(untared));
|
||||||
ASSERT_TRUE(subprocess::check_run(tar_bin, "xf", tarfile, "-C", untared));
|
ASSERT_TRUE(subprocess::check_run(tar_bin, "xf", tarfile, "-C", untared));
|
||||||
ASSERT_TRUE(subprocess::check_run(diff_bin, "-qruN", data_dir, untared));
|
ASSERT_TRUE(subprocess::check_run(diff_bin, "-qruN", data_dir, untared));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user