Improve CliTest running of the file system

This commit is contained in:
Sebastian Messmer 2018-09-07 19:54:01 -07:00
parent cef6b13317
commit afad6ee465

View File

@ -60,23 +60,41 @@ public:
} }
void EXPECT_RUN_ERROR(const std::vector<std::string>& args, const char* message, cryfs::ErrorCode errorCode) { void EXPECT_RUN_ERROR(const std::vector<std::string>& args, const char* message, cryfs::ErrorCode errorCode) {
cpputils::CaptureStderrRAII capturedStderr; FilesystemOutput filesystem_output = _run_filesystem(args, boost::none);
int exit_code = run(args);
capturedStderr.EXPECT_MATCHES(message); EXPECT_EQ(exitCode(errorCode), filesystem_output.exit_code);
EXPECT_EQ(exitCode(errorCode), exit_code); EXPECT_TRUE(std::regex_search(filesystem_output.stderr_, std::regex(message, std::regex::basic)));
} }
void EXPECT_RUN_SUCCESS(const std::vector<std::string>& args, const boost::filesystem::path &mountDir) { void EXPECT_RUN_SUCCESS(const std::vector<std::string>& args, const boost::filesystem::path &mountDir) {
//TODO Make this work when run in background //TODO Make this work when run in background
ASSERT(std::find(args.begin(), args.end(), string("-f")) != args.end(), "Currently only works if run in foreground"); ASSERT(std::find(args.begin(), args.end(), string("-f")) != args.end(), "Currently only works if run in foreground");
bool unmount_success = false;
std::thread unmountThread([&mountDir, &unmount_success] { FilesystemOutput filesystem_output = _run_filesystem(args, mountDir);
auto start = std::chrono::steady_clock::now();
EXPECT_EQ(0, filesystem_output.exit_code);
EXPECT_TRUE(std::regex_search(filesystem_output.stdout_, std::regex("Mounting filesystem")));
}
struct FilesystemOutput final {
int exit_code;
std::string stdout_;
std::string stderr_;
};
FilesystemOutput _run_filesystem(const std::vector<std::string>& args, const boost::optional<boost::filesystem::path>& mountDirForUnmounting) {
std::future<FilesystemOutput> filesystem_output = std::async(std::launch::async, [this, &args] {
testing::internal::CaptureStdout();
testing::internal::CaptureStderr();
int exit_code = run(args);
return FilesystemOutput {exit_code, testing::internal::GetCapturedStdout(), testing::internal::GetCapturedStderr()};
});
if (mountDirForUnmounting.is_initialized()) {
boost::filesystem::path mountDir = *mountDirForUnmounting;
std::future<bool> unmount_success = std::async(std::launch::async, [&mountDir] {
int returncode = -1; int returncode = -1;
while (returncode != 0) { while (returncode != 0) {
if (std::chrono::steady_clock::now() - start > std::chrono::seconds(10)) {
return; // keep unmount_success = false
}
#if defined(__APPLE__) #if defined(__APPLE__)
returncode = cpputils::Subprocess::call(std::string("umount ") + mountDir.string().c_str() + " 2>/dev/null").exitcode; returncode = cpputils::Subprocess::call(std::string("umount ") + mountDir.string().c_str() + " 2>/dev/null").exitcode;
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
@ -89,18 +107,20 @@ public:
returncode = cpputils::Subprocess::call(std::string("fusermount -u ") + mountDir.string().c_str() + " 2>/dev/null").exitcode; returncode = cpputils::Subprocess::call(std::string("fusermount -u ") + mountDir.string().c_str() + " 2>/dev/null").exitcode;
#endif #endif
} }
unmount_success = true; return true;
}); });
testing::internal::CaptureStdout();
run(args);
std::string _stdout = testing::internal::GetCapturedStdout();
unmountThread.join();
EXPECT_TRUE(unmount_success); if(std::future_status::ready != unmount_success.wait_for(std::chrono::seconds(10))) {
throw std::runtime_error("Unmount thread didn't finish");
}
EXPECT_TRUE(unmount_success.get()); // this also re-throws any potential exceptions
}
// For some reason, the following doesn't seem to work in MSVC. Possibly because of the multiline string? if(std::future_status::ready != filesystem_output.wait_for(std::chrono::seconds(10))) {
// EXPECT_THAT(testing::internal::GetCapturedStdout(), testing::MatchesRegex(".*Mounting filesystem.*")); throw std::runtime_error("Filesystem thread didn't finish");
EXPECT_TRUE(std::regex_search(_stdout, std::regex(".*Mounting filesystem.*"))); }
return filesystem_output.get();
} }
}; };