From bf7a57fc55493247a624ecfd65e4d73964e7d8d2 Mon Sep 17 00:00:00 2001 From: SulfurNitride Date: Sun, 12 Apr 2026 02:40:16 -0500 Subject: Remove vendored usvfs and Windows-only usvfs code paths The Linux port uses its own in-process FUSE VFS (FuseConnector), so usvfs was dead weight: libs/usvfs/ was never built, usvfsconnector.cpp was explicitly REMOVE_ITEM'd from the source list, and every call site was already guarded by #ifdef _WIN32 with a working Linux branch (the Windows build is also broken on this branch, since FUSE3 is a hard find_package dependency). - Drop libs/usvfs/ and src/src/usvfsconnector.{cpp,h} - Collapse #ifdef _WIN32 / usvfs include branches in organizercore, mainwindow, settings, util, spawn - Remove getUsvfsVersionString() and the "usvfs: ..." log field - Remove vfs32/64DLLName APPPARAMs (nothing reads them) - Relabel About dialog "usvfs:" row to "VFS: FUSE 3" --- libs/usvfs/test/usvfs_test_runner/CMakeLists.txt | 35 - .../test_file_operations/test_file_operations.cpp | 496 ---------- .../test_file_operations/test_filesystem.cpp | 159 ---- .../test_file_operations/test_filesystem.h | 104 -- .../test_file_operations/test_ntapi.cpp | 488 ---------- .../test_file_operations/test_ntapi.h | 38 - .../test_file_operations/test_ntdll_declarations.h | 157 --- .../test_file_operations/test_w32api.cpp | 370 -------- .../test_file_operations/test_w32api.h | 36 - .../usvfs_test/usvfs_basic_test.cpp | 402 -------- .../usvfs_test/usvfs_basic_test.h | 14 - .../usvfs_test_runner/usvfs_test/usvfs_test.cpp | 242 ----- .../usvfs_test/usvfs_test_base.cpp | 1002 -------------------- .../usvfs_test_runner/usvfs_test/usvfs_test_base.h | 120 --- .../test/usvfs_test_runner/usvfs_test_runner.cpp | 105 -- 15 files changed, 3768 deletions(-) delete mode 100644 libs/usvfs/test/usvfs_test_runner/CMakeLists.txt delete mode 100644 libs/usvfs/test/usvfs_test_runner/test_file_operations/test_file_operations.cpp delete mode 100644 libs/usvfs/test/usvfs_test_runner/test_file_operations/test_filesystem.cpp delete mode 100644 libs/usvfs/test/usvfs_test_runner/test_file_operations/test_filesystem.h delete mode 100644 libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntapi.cpp delete mode 100644 libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntapi.h delete mode 100644 libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntdll_declarations.h delete mode 100644 libs/usvfs/test/usvfs_test_runner/test_file_operations/test_w32api.cpp delete mode 100644 libs/usvfs/test/usvfs_test_runner/test_file_operations/test_w32api.h delete mode 100644 libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_basic_test.cpp delete mode 100644 libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_basic_test.h delete mode 100644 libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test.cpp delete mode 100644 libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test_base.cpp delete mode 100644 libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test_base.h delete mode 100644 libs/usvfs/test/usvfs_test_runner/usvfs_test_runner.cpp (limited to 'libs/usvfs/test/usvfs_test_runner') diff --git a/libs/usvfs/test/usvfs_test_runner/CMakeLists.txt b/libs/usvfs/test/usvfs_test_runner/CMakeLists.txt deleted file mode 100644 index a0a7ca9..0000000 --- a/libs/usvfs/test/usvfs_test_runner/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -cmake_minimum_required(VERSION 3.16) - -find_package(GTest CONFIG REQUIRED) - -# other executables -add_executable(test_file_operations - test_file_operations/test_file_operations.cpp - test_file_operations/test_filesystem.cpp - test_file_operations/test_filesystem.h - test_file_operations/test_ntapi.cpp - test_file_operations/test_ntapi.h - test_file_operations/test_ntdll_declarations.h - test_file_operations/test_w32api.cpp - test_file_operations/test_w32api.h -) -usvfs_set_test_properties(test_file_operations FOLDER usvfs_test_runner) -target_link_libraries(test_file_operations PRIVATE test_utils ntdll) - -add_executable(usvfs_test - usvfs_test/usvfs_basic_test.cpp - usvfs_test/usvfs_basic_test.h - usvfs_test/usvfs_test_base.cpp - usvfs_test/usvfs_test_base.h - usvfs_test/usvfs_test.cpp -) -usvfs_set_test_properties(usvfs_test FOLDER usvfs_test_runner) -usvfs_target_link_usvfs(usvfs_test) -target_link_libraries(usvfs_test PRIVATE test_utils) - -# actual test executable -add_executable(usvfs_test_runner usvfs_test_runner.cpp) -usvfs_set_test_properties(usvfs_test_runner FOLDER usvfs_test_runner) -target_link_libraries(usvfs_test_runner - PRIVATE test_utils GTest::gtest GTest::gtest_main) -add_dependencies(usvfs_test_runner usvfs_test test_file_operations) diff --git a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_file_operations.cpp b/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_file_operations.cpp deleted file mode 100644 index 2135df3..0000000 --- a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_file_operations.cpp +++ /dev/null @@ -1,496 +0,0 @@ -#include -#include - -#include -#include -#include - -#include "test_ntapi.h" -#include "test_w32api.h" -#include - -#define WIN32_LEAN_AND_MEAN -#include - -using usvfs::shared::CodePage; -using usvfs::shared::string_cast; - -void print_usage(const char* myname) -{ - using namespace std; - fprintf(stderr, "usage: %s [] [] ...\n", myname); - fprintf(stderr, - "options and commands are parsed and executed in the order they appear.\n"); - fprintf(stderr, "\nsupported commands:\n"); - fprintf( - stderr, - " -list : lists the given directory and outputs the results.\n"); - fprintf(stderr, " -listcontents : lists the given directory, reading all files " - "and outputs the results.\n"); - fprintf(stderr, - " -read : reads the given file and outputs the results.\n"); - fprintf(stderr, " -overwrite : overwrites the file at the given path " - "with the given line (creating directories if in recursive mode).\n"); - fprintf(stderr, " -deleteoverwrite : shorthand for -delete " - "-overwrite \n"); - fprintf(stderr, - " -rewrite : rewrites the file at the given path with the " - "given line (fails if file doesn't exist; uses read/write access).\n"); - fprintf(stderr, - " -touch : updates last write timestamp of specified file.\n"); - fprintf(stderr, " -touchw : updates last write timestamp using full " - "write permissions.\n"); - fprintf(stderr, " -delete : deletes the given file.\n"); - fprintf(stderr, " -copy : copies the given file.\n"); - fprintf(stderr, " -copyover : copies the given file (replacing existing " - "destination).\n"); - fprintf(stderr, " -rename : renames the given file.\n"); - fprintf(stderr, " -renameover : renames the given file (replacing " - "existing destination).\n"); - fprintf(stderr, " -deleterename : shorthand for -delete -rename " - " .\n"); - fprintf(stderr, - " -move : moves the given file (not supported by ntapi).\n"); - fprintf(stderr, " -moveover : moves the given file (replacing existing " - "destination; not supported by ntapi).\n"); - fprintf( - stderr, - " -deletemove : shorthand for -delete -move .\n"); - fprintf(stderr, " -debug : shows a message box and wait for a debugger " - "to connect.\n"); - fprintf(stderr, "\nsupported options:\n"); - fprintf(stderr, " -out : file to log output to (use \"-\" for the " - "stdout; otherwise path to output should exist).\n"); - fprintf(stderr, " -out+ : similar to -out but appends the file instead " - "of overwriting it.\n"); - fprintf(stderr, " -cout : similar to -out but does not log PID and " - "other info which may change between runs.\n"); - fprintf(stderr, " -cout+ : similar to -cout but appends the file " - "instead of overwriting it.\n"); - fprintf(stderr, " -r : recursively list/create directories.\n"); - fprintf(stderr, - " -r- : don't recursively list/create directories.\n"); - fprintf(stderr, " -basedir : any paths under the basedir will outputed in " - "a relative manner (default is current directory).\n"); - fprintf(stderr, - " -w32api : use regular Win32 API for file access (default).\n"); - fprintf(stderr, - " -ntapi : use lower level ntdll functions for file access.\n"); -} - -class CommandExecuter -{ -public: - CommandExecuter() : m_output(stdout), m_api(&w32api) - { - set_basedir(TestFileSystem::current_directory().string().c_str()); - } - - ~CommandExecuter() - { - if (m_output && m_output != stdout) - fclose(m_output); - } - - FILE* output() const { return m_output; } - - bool file_output() const { return m_output != stdout; } - - // Options: - - void set_output(const char* output_file, bool clean, bool append, const char* cmdline) - { - if (m_output && m_output != stdout) { - fprintf(m_output, "#< Output log closed.\n", output_file); - fclose(m_output); - } - - m_cleanoutput = clean; - m_output = nullptr; - errno_t err = fopen_s(&m_output, output_file, append ? "at" : "wt"); - if (err || !m_output) - test::throw_testWinFuncFailed("fopen_s", output_file, err); - else { - if (m_cleanoutput) - fprintf(m_output, "#> Output log openned for: %s\n", - clean_cmdline_heuristic(cmdline).c_str()); - else - fprintf(m_output, "#> Output log openned for (pid %d): %s\n", - GetCurrentProcessId(), cmdline); - w32api.set_output(m_output, m_cleanoutput); - ntapi.set_output(m_output, m_cleanoutput); - } - } - - bool cleanoutput() const { return m_cleanoutput; } - - void set_recursive(bool recursive) { m_recursive = recursive; } - - void set_basedir(const char* basedir) - { - w32api.set_basepath(basedir); - ntapi.set_basepath(basedir); - } - - void set_ntapi(bool enable) - { - if (enable) - m_api = &ntapi; - else - m_api = &w32api; - } - - // Commands: - - void list(const char* dir, bool read_files) - { - if (debug_pending()) - __debugbreak(); - - list_impl(m_api->real_path(dir), read_files); - } - - void read(const char* path) - { - if (debug_pending()) - __debugbreak(); - - m_api->read_file(m_api->real_path(path)); - } - - void overwrite(const char* path, const char* value) - { - if (debug_pending()) - __debugbreak(); - - const auto& real = real_path_create_if_necessary(path); - - m_api->write_file(real, value, strlen(value), true, - TestFileSystem::write_mode::overwrite); - } - - void rewrite(const char* path, const char* value) - { - if (debug_pending()) - __debugbreak(); - - const auto& real = real_path_create_if_necessary(path); - - // Use read/write access when rewriting to "simulate" the harder case where it is - // not known if the file is going to actually be changed - m_api->write_file(real, value, strlen(value), false, - TestFileSystem::write_mode::manual_truncate, true); - m_api->write_file(real, "\r\n", 2, false, TestFileSystem::write_mode::append); - } - - void touch(const char* path, bool full_write_access) - { - if (debug_pending()) - __debugbreak(); - - const auto& real = real_path_create_if_necessary(path); - - m_api->touch_file(real, full_write_access); - } - - void deletef(const char* path) - { - if (debug_pending()) - __debugbreak(); - - m_api->delete_file(m_api->real_path(path)); - } - - void rename(const char* source, const char* destination, bool replace_existing) - { - if (debug_pending()) - __debugbreak(); - - m_api->copy_file(m_api->real_path(source), m_api->real_path(destination), - replace_existing); - } - - void rename(const char* source, const char* destination, bool replace_existing, - bool allow_copy) - { - if (debug_pending()) - __debugbreak(); - - m_api->rename_file(m_api->real_path(source), m_api->real_path(destination), - replace_existing, allow_copy); - } - - void debug() { m_debug_pending = true; } - - bool debug_pending() - { - if (!m_debug_pending) - return false; - m_debug_pending = false; - if (!IsDebuggerPresent()) - MessageBoxA(NULL, "Connect a debugger and press OK to trigger a breakpoint", - "DEBUG", 0); - return IsDebuggerPresent(); - } - - // Traversal: - - void list_impl(TestFileSystem::path real, bool read_files) - { - std::vector recurse; - { - auto files = m_api->list_directory(real); - fprintf(m_output, ">> Listing directory {%s}:\n", - m_api->relative_path(real).string().c_str()); - for (auto f : files) { - if (f.is_dir()) { - fprintf(m_output, "[%s] DIR (attributes 0x%x)\n", - string_cast(f.name, CodePage::UTF8).c_str(), - f.attributes); - if (m_recursive && f.name != L"." && f.name != L"..") - recurse.push_back(real / f.name); - } else { - fprintf(m_output, "[%s] FILE (attributes 0x%x, %lld bytes)\n", - string_cast(f.name, CodePage::UTF8).c_str(), - f.attributes, f.size); - if (read_files) - m_api->read_file(real / f.name); - } - } - } - for (auto r : recurse) - list_impl(r, read_files); - } - -private: - TestFileSystem::path real_path_create_if_necessary(const char* path) - { - auto real = m_api->real_path(path); - if (m_recursive) - try { - m_api->create_path(real.parent_path()); - } catch (const std::exception& e) { - throw std::runtime_error( - std::format("Failed to create_path [{}] : {}", - m_api->relative_path(real.parent_path()).string(), e.what())); - } - return std::move(real); - } - - std::string clean_cmdline_arg(const char* arg_start, const char* arg_end) - { - if (arg_start == arg_end) - return std::string(); - bool quoted = *arg_start == '\"' && *(arg_end - 1) == '\"'; - const char* last_sep = arg_end; - while (last_sep != arg_start && *last_sep != '\\') - --last_sep; - if (arg_end - arg_start < (quoted ? 5 : 3) || arg_start[0] == '-' || - arg_start[quoted ? 2 : 1] != ':' || last_sep == arg_start) - return std::string(arg_start, arg_end); - std::string res = quoted ? "\"" : ""; - res.append(last_sep + 1, arg_end); - return res; - } - - std::string clean_cmdline_heuristic(const char* cmdline) - { - std::string res; - bool first = true; - while (*cmdline) { - const char* end = strchr(cmdline, ' '); - if (!end) - end = cmdline + strlen(cmdline); - if (first) - first = false; - else - res.push_back(' '); - res += clean_cmdline_arg(cmdline, end); - cmdline = end; - while (*cmdline == ' ') - ++cmdline; - } - return res; - } - - FILE* m_output; - bool m_cleanoutput = false; - bool m_recursive = false; - bool m_debug_pending = false; - - TestFileSystem* m_api; - static TestW32Api w32api; - static TestNtApi ntapi; -}; - -// static -TestW32Api CommandExecuter::w32api(stdout); -TestNtApi CommandExecuter::ntapi(stdout); - -class abort_invalid_argument : std::exception -{}; - -bool verify_args_exist(const char* flag, int params, int index, int count) -{ - if (index + params >= count) { - fprintf(stderr, "ERROR: %s requires %d arguments\n", flag, params); - throw abort_invalid_argument(); - } - return true; -} - -const char* UntouchedCommandLineArguments() -{ - const char* cmd = GetCommandLineA(); - for (; *cmd && *cmd != ' '; ++cmd) { - if (*cmd == '"') { - int escaped = 0; - for (++cmd; *cmd && (*cmd != '"' || escaped % 2 != 0); ++cmd) - escaped = *cmd == '\\' ? escaped + 1 : 0; - } - } - while (*cmd == ' ') - ++cmd; - return cmd; -} - -int main(int argc, char* argv[]) -{ - bool found_commands = false; - CommandExecuter executer; - - TestFileSystem::path exe_path = argv[0]; - std::string exename = exe_path.filename().string(); - std::string cmdline = exename + " " + UntouchedCommandLineArguments(); - fprintf(stdout, "#> process %d started with commandline: %s\n", GetCurrentProcessId(), - cmdline.c_str()); - - for (int ai = 1; ai < argc; ++ai) { - try { - SetLastError(0); - - // options: - if (strcmp(argv[ai], "-out") == 0 && verify_args_exist("-out", 1, ai, argc) || - strcmp(argv[ai], "-out+") == 0 && verify_args_exist("-out+", 1, ai, argc) || - strcmp(argv[ai], "-cout") == 0 && verify_args_exist("-cout", 1, ai, argc) || - strcmp(argv[ai], "-cout+") == 0 && verify_args_exist("-cout+", 1, ai, argc)) { - bool clean = argv[ai][1] == 'c'; - bool append = argv[ai][clean ? 5 : 4] == '+'; - executer.set_output(argv[++ai], clean, append, cmdline.c_str()); - } else if (strcmp(argv[ai], "-r") == 0) - executer.set_recursive(true); - else if (strcmp(argv[ai], "-r-") == 0) - executer.set_recursive(false); - else if (strcmp(argv[ai], "-basedir") == 0 && - verify_args_exist("-basedir", 1, ai, argc)) { - executer.set_basedir(argv[++ai]); - } else if (strcmp(argv[ai], "-w32api") == 0) - executer.set_ntapi(false); - else if (strcmp(argv[ai], "-ntapi") == 0) - executer.set_ntapi(true); - // commands: - else if ((strcmp(argv[ai], "-list") == 0 || - strcmp(argv[ai], "-listcontents") == 0) && - verify_args_exist("-list", 1, ai, argc)) { - bool contents = strcmp(argv[ai], "-listcontents") == 0; - executer.list(argv[++ai], contents); - found_commands = true; - } else if (strcmp(argv[ai], "-read") == 0 && - verify_args_exist("-read", 1, ai, argc)) { - executer.read(argv[++ai]); - found_commands = true; - } else if (strcmp(argv[ai], "-overwrite") == 0 && - verify_args_exist("-overwrite", 2, ai, argc) || - strcmp(argv[ai], "-deleteoverwrite") == 0 && - verify_args_exist("-deleteoverwrite", 2, ai, argc)) { - if (argv[ai][1] == 'd') - executer.deletef(argv[ai + 1]); - executer.overwrite(argv[ai + 1], argv[ai + 2]); - ++ ++ai; - found_commands = true; - } else if (strcmp(argv[ai], "-rewrite") == 0 && - verify_args_exist("-rewrite", 2, ai, argc)) { - executer.rewrite(argv[ai + 1], argv[ai + 2]); - ++ ++ai; - found_commands = true; - } else if (strcmp(argv[ai], "-touch") == 0 && - verify_args_exist("-touch", 1, ai, argc) || - strcmp(argv[ai], "-touchw") == 0 && - verify_args_exist("-touchw", 1, ai, argc)) { - bool write_access = argv[ai][6] == 'w'; - executer.touch(argv[++ai], write_access); - found_commands = true; - } else if (strcmp(argv[ai], "-delete") == 0 && - verify_args_exist("-delete", 1, ai, argc)) { - executer.deletef(argv[++ai]); - found_commands = true; - } else if (strcmp(argv[ai], "-copy") == 0 && - verify_args_exist("-copy", 2, ai, argc) || - strcmp(argv[ai], "-copyover") == 0 && - verify_args_exist("-copyover", 2, ai, argc)) { - bool over = argv[ai][5] == 'o'; - executer.rename(argv[ai + 1], argv[ai + 2], over); - ++ ++ai; - found_commands = true; - } else if (strcmp(argv[ai], "-rename") == 0 && - verify_args_exist("-rename", 2, ai, argc) || - strcmp(argv[ai], "-renameover") == 0 && - verify_args_exist("-renameover", 2, ai, argc) || - strcmp(argv[ai], "-deleterename") == 0 && - verify_args_exist("-deleterename", 2, ai, argc) || - strcmp(argv[ai], "-move") == 0 && - verify_args_exist("-move", 2, ai, argc) || - strcmp(argv[ai], "-moveover") == 0 && - verify_args_exist("-moveover", 2, ai, argc) || - strcmp(argv[ai], "-deletemove") == 0 && - verify_args_exist("-deletemove", 2, ai, argc)) { - bool del = argv[ai][1] == 'd'; - bool move = argv[ai][del ? 7 : 1] == 'm'; - bool over = !del && argv[ai][move ? 5 : 7] == 'o'; - if (del) - executer.deletef(argv[ai + 2]); - executer.rename(argv[ai + 1], argv[ai + 2], over, move); - ++ ++ai; - found_commands = true; - } else if (strcmp(argv[ai], "-debug") == 0) { - executer.debug(); - } else { - if (executer.file_output()) - fprintf(executer.output(), "ERROR: invalid argument {%s}\n", argv[ai]); - fprintf(stderr, "ERROR: invalid argument {%s}\n", argv[ai]); - return 1; - } - } catch (const abort_invalid_argument&) { - return 1; - } -#if 1 // just a convient way to not catch exception when debugging - catch (const std::exception& e) { - if (executer.file_output()) - fprintf(executer.output(), "ERROR: %hs\n", e.what()); - fprintf(stderr, "ERROR: %hs\n", e.what()); - return 1; - } catch (...) { - if (executer.file_output()) - fprintf(executer.output(), "ERROR: unknown exception"); - fprintf(stderr, "ERROR: unknown exception\n"); - return 1; - } -#endif - } - - if (!found_commands) { - print_usage(exename.c_str()); - return 2; - } - - if (executer.file_output()) - if (executer.cleanoutput()) - fprintf(executer.output(), "#< %s ended properly.\n", exename.c_str()); - else - fprintf(executer.output(), "#< %s ended properly in process %d.\n", - exename.c_str(), GetCurrentProcessId()); - fprintf(stdout, "#< %s ended properly in process %d.\n", exename.c_str(), - GetCurrentProcessId()); - - return 0; -} diff --git a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_filesystem.cpp b/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_filesystem.cpp deleted file mode 100644 index dcfd5a1..0000000 --- a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_filesystem.cpp +++ /dev/null @@ -1,159 +0,0 @@ - -#include "test_filesystem.h" -#include -#define WIN32_LEAN_AND_MEAN -#include - -using test::throw_testWinFuncFailed; - -bool TestFileSystem::FileInformation::is_dir() const -{ - return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; -} - -bool TestFileSystem::FileInformation::is_file() const -{ - return (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0; -} - -TestFileSystem::TestFileSystem(FILE* output) : m_output(output) {} - -TestFileSystem::path TestFileSystem::current_directory() -{ - DWORD res = GetCurrentDirectoryW(0, NULL); - if (!res) - throw_testWinFuncFailed("GetCurrentDirectory", res); - std::wstring buf(res + 1, '\0'); - res = GetCurrentDirectoryW(buf.length(), &buf[0]); - if (!res || res >= buf.length()) - throw_testWinFuncFailed("GetCurrentDirectory", res); - buf.resize(res); - return buf; -} - -TestFileSystem::path TestFileSystem::relative_path(path full_path) -{ - return test::path_as_relative(m_basepath, full_path); -} - -// static -const char* TestFileSystem::write_operation_name(write_mode mode) -{ - switch (mode) { - case write_mode::manual_truncate: - return "Writing file (by open & truncate)"; - case write_mode::truncate: - return "Truncating file"; - case write_mode::create: - return "Creating file"; - case write_mode::overwrite: - return "Overwriting file"; - case write_mode::opencreate: - return "Opening/Creating file"; - case write_mode::append: - return "Appending file"; - } - return "Unknown write operation?!"; -} - -// static -const char* TestFileSystem::rename_operation_name(bool replace_existing, - bool allow_copy) -{ - if (allow_copy) - return replace_existing ? "Moving file over" : "Moving file"; - else - return replace_existing ? "Renaming file over" : "Renaming file"; -} - -void TestFileSystem::print_operation(const char* operation, const path& target) -{ - if (m_output) - fprintf(m_output, "# (%s) %s {%s}\n", id(), operation, - relative_path(target).string().c_str()); -} - -void TestFileSystem::print_operation(const char* operation, const path& source, - const path& target) -{ - if (m_output) - fprintf(m_output, "# (%s) %s {%s} {%s}\n", id(), operation, - relative_path(source).string().c_str(), - relative_path(target).string().c_str()); -} - -static inline void print_op_with_result(FILE* output, const char* prefix, - const char* operation, const uint32_t* result, - DWORD* last_error, const char* opt_arg) -{ - if (output) { - fprintf(output, "%s%s", prefix, operation); - if (opt_arg) - fprintf(output, " %s", opt_arg); - if (result) - fprintf(output, " returned %u (0x%x)", *result, *result); - if (last_error) - fprintf(output, " last error %u (0x%x)", *last_error, *last_error); - fprintf(output, "\n"); - } -} - -void TestFileSystem::print_result(const char* operation, uint32_t result, - bool with_last_error, const char* opt_arg, - bool hide_result) -{ - if (m_output) { - DWORD last_error = GetLastError(); - std::string prefix = "# ("; - prefix += id(); - prefix += ") "; - print_op_with_result(m_output, prefix.c_str(), operation, - hide_result ? nullptr : &result, - with_last_error ? &last_error : nullptr, opt_arg); - SetLastError(last_error); - } -} - -void TestFileSystem::print_error(const char* operation, uint32_t result, - bool with_last_error, const char* opt_arg) -{ - DWORD last_error = with_last_error ? GetLastError() : 0; - print_op_with_result(stderr, "ERROR: ", operation, &result, - with_last_error ? &last_error : nullptr, opt_arg); - if (m_output && m_output != stdout) - print_op_with_result(m_output, "ERROR: ", operation, &result, - with_last_error ? &last_error : nullptr, opt_arg); -} - -void TestFileSystem::print_write_success(const void* data, std::size_t size, - std::size_t written) -{ - if (m_output) { - fprintf(m_output, "# Successfully written %u bytes ", - static_cast(written)); - // heuristics to print nicer one liners: - if (size == 1 && reinterpret_cast(data)[0] == '\n' || - size == 2 && reinterpret_cast(data)[0] == '\r' && - reinterpret_cast(data)[1] == '\n') - fprintf(m_output, ""); - else { - fprintf(m_output, "{"); - if (size && reinterpret_cast(data)[size - 1] == '\n') - --size; - if (data) - fwrite(data, 1, size, m_output); - else if (size) - fwrite("NULL?!", 1, 6, m_output); - fprintf(m_output, "}"); - } - fprintf(output(), "\n"); - } -} - -uint32_t TestFileSystem::clean_attributes(uint32_t attr) -{ - if (m_cleanoutput) - return attr & ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); - else - return attr; -} diff --git a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_filesystem.h b/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_filesystem.h deleted file mode 100644 index 3a5f53b..0000000 --- a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_filesystem.h +++ /dev/null @@ -1,104 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -class TestFileSystem -{ -public: - static constexpr auto FILE_CONTENTS_PRINT_PREFIX = "== "; - - typedef std::filesystem::path path; - typedef std::FILE FILE; - - static path current_directory(); - - TestFileSystem(FILE* output); - - void set_output(FILE* output, bool clean) - { - m_output = output; - m_cleanoutput = clean; - } - - // base path used to trim outputs (which is important so we can compare tests ran at - // different base paths) - void set_basepath(const char* path) { m_basepath = real_path(path); } - - // returns the path relative to the base path - path relative_path(path full_path); - - virtual const char* id() = 0; - - virtual path real_path(const char* abs_or_rel_path) = 0; - - struct FileInformation - { - std::wstring name; - uint32_t attributes; - uint64_t size; - - FileInformation(const std::wstring& iname, uint32_t iattributes, uint64_t isize) - : name(iname), attributes(iattributes), size(isize) - {} - - bool is_dir() const; - bool is_file() const; - }; - typedef std::vector FileInfoList; - - virtual FileInfoList list_directory(const path& directory_path) = 0; - - virtual void create_path(const path& directory_path) = 0; - - virtual void read_file(const path& file_path) = 0; - - enum class write_mode - { - manual_truncate, - truncate, - create, - overwrite, - opencreate, - append - }; - virtual void write_file(const path& file_path, const void* data, std::size_t size, - bool add_new_line, write_mode mode, - bool rw_access = false) = 0; - - virtual void touch_file(const path& file_path, bool full_write_access = false) = 0; - - virtual void delete_file(const path& file_path) = 0; - - virtual void copy_file(const path& source_path, const path& destination_path, - bool replace_existing) = 0; - - virtual void rename_file(const path& source_path, const path& destination_path, - bool replace_existing, bool allow_copy) = 0; - -protected: - FILE* output() { return m_output; } - bool cleanoutput() const { return m_cleanoutput; } - static const char* write_operation_name(write_mode mode); - static const char* rename_operation_name(bool replace_existing, bool allow_copy); - -public: // mainly for derived class (but also used by helper classes like SafeHandle so - // public) - void print_operation(const char* operation, const path& target); - void print_operation(const char* operation, const path& source, const path& target); - void print_result(const char* operation, uint32_t result, - bool with_last_error = false, const char* opt_arg = nullptr, - bool hide_result = false); - void print_error(const char* operation, uint32_t result, bool with_last_error = false, - const char* opt_arg = nullptr); - void print_write_success(const void* data, std::size_t size, std::size_t written); - - uint32_t clean_attributes(uint32_t attr); - -private: - FILE* m_output; - bool m_cleanoutput = false; - path m_basepath; -}; diff --git a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntapi.cpp b/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntapi.cpp deleted file mode 100644 index 34966b5..0000000 --- a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntapi.cpp +++ /dev/null @@ -1,488 +0,0 @@ - -#include "test_ntapi.h" -#include -#include -#include -#include - -#define WIN32_LEAN_AND_MEAN -#include -#include -#include - -#include "test_ntdll_declarations.h" - -class TestNtApi::SafeHandle -{ -public: - SafeHandle(TestFileSystem* tfs, HANDLE handle = NULL) : m_handle(handle), m_tfs(tfs) - {} - SafeHandle(const SafeHandle&) = delete; - SafeHandle(SafeHandle&& other) : m_handle(other.m_handle), m_tfs(other.m_tfs) - { - other.m_handle = nullptr; - } - - operator HANDLE() { return m_handle; } - operator PHANDLE() { return &m_handle; } - - bool valid() const { return m_handle != NULL; } - - ~SafeHandle() - { - if (m_handle) { - NTSTATUS status = NtClose(m_handle); - if (m_tfs) - m_tfs->print_result("NtClose", status); - if (!NT_SUCCESS(status)) - if (m_tfs) - m_tfs->print_error("NtClose", status); - else - std::fprintf(stderr, "NtClose failed : 0x%lx", status); - m_handle = NULL; - } - } - -private: - HANDLE m_handle; - TestFileSystem* m_tfs; -}; - -const char* TestNtApi::id() -{ - return "Nt"; -} - -TestNtApi::path TestNtApi::real_path(const char* abs_or_rel_path) -{ - if (!abs_or_rel_path || !abs_or_rel_path[0]) - return path(); - - static constexpr char nt_path_prefix[] = "\\??\\"; - static constexpr wchar_t nt_path_prefix_w[] = L"\\??\\"; - - bool path_dos = strncmp(abs_or_rel_path, nt_path_prefix, strlen(nt_path_prefix)) == 0; - bool path_has_drive = abs_or_rel_path[1] == ':'; - bool path_unc = abs_or_rel_path[0] == '\\' && abs_or_rel_path[1] == '\\'; - bool path_absolute = path_has_drive || abs_or_rel_path[0] == '\\'; - - path result; - if (!path_dos) { - if (!path_unc) - result.assign(nt_path_prefix_w); - if (!path_absolute) - result /= current_directory(); - else if (!path_has_drive && !path_unc) - // if "absolute" path but without a drive letter (i.e. \windows) - // the take the drive from the current directory: (i.e. "C:") - result /= current_directory().root_name(); - } - - int result_size = 0; - for (auto r : result) - ++result_size; - - // now append abs_or_rel_path, handling ".." and "." properly: - path arp{abs_or_rel_path}; - int base_size = path_unc ? 3 : 4; - for (auto p : arp) { - if (p == "..") { - if (result_size > base_size) { // refuse to remove top level element (i.e. - // \??\C:\ which is 4 elements) - result.remove_filename(); - --result_size; - } - } else if (!p.empty() && p != ".") { - result /= p; - ++result_size; - } - } - - return result; -} - -TestNtApi::SafeHandle TestNtApi::open_directory(const path& directory_path, bool create, - bool allow_non_existence, long* pstatus) -{ - print_operation(create ? "Creating directory" : "Openning directory", directory_path); - - UNICODE_STRING unicode_path; - RtlInitUnicodeString(&unicode_path, directory_path.c_str()); - - OBJECT_ATTRIBUTES attributes; - InitializeObjectAttributes(&attributes, &unicode_path, OBJ_CASE_INSENSITIVE, NULL, - NULL); - - SafeHandle dir(this); - IO_STATUS_BLOCK iosb; - NTSTATUS status = NtCreateFile( - dir, FILE_LIST_DIRECTORY | FILE_TRAVERSE | SYNCHRONIZE, &attributes, &iosb, NULL, - FILE_ATTRIBUTE_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - create ? FILE_OPEN_IF : FILE_OPEN, - FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); - - print_result("NtCreateFile", status); - - if (pstatus) - *pstatus = status; - if ((status == STATUS_OBJECT_NAME_NOT_FOUND || - status == STATUS_OBJECT_PATH_NOT_FOUND) && - allow_non_existence) - return NULL; - if (!NT_SUCCESS(status)) - throw test::FuncFailed("NtCreateFile", status); - if (!NT_SUCCESS(iosb.Status)) - throw test::FuncFailed("NtCreateFile", "bad iosb.Status", iosb.Status); - - return dir; -} - -TestFileSystem::FileInfoList TestNtApi::list_directory(const path& directory_path) -{ - SafeHandle dir = open_directory(directory_path, false); - - print_operation("Querying directory", directory_path); - - FileInfoList files; - while (true) { - char buf[4096]{0}; - IO_STATUS_BLOCK iosb; - - NTSTATUS status = - NtQueryDirectoryFile(dir, NULL, NULL, NULL, &iosb, buf, sizeof(buf), - MyFileBothDirectoryInformation, FALSE, NULL, FALSE); - print_result("NtQueryDirectoryFile", status); - - if (status == STATUS_NO_MORE_FILES) - break; - if (!NT_SUCCESS(status)) - throw test::FuncFailed("NtQueryDirectoryFile", status); - if (!NT_SUCCESS(iosb.Status)) - throw test::FuncFailed("NtQueryDirectoryFile", "bad iosb.Status", iosb.Status); - if (iosb.Information == 0) // This shouldn't happend unless the filename (not full - // path) is larger then sizeof(buf) - throw test::FuncFailed("NtQueryDirectoryFile", "buffer too small", - iosb.Information); - - PFILE_BOTH_DIR_INFORMATION info = reinterpret_cast(buf); - while (true) { - files.push_back(FileInformation( - std::wstring(info->FileName, - info->FileNameLength / sizeof(info->FileName[0])), - clean_attributes(info->FileAttributes), info->EndOfFile.QuadPart)); - if (info->NextEntryOffset) - info = reinterpret_cast( - reinterpret_cast(info) + info->NextEntryOffset); - else - break; - } - } - - return files; -} - -void TestNtApi::create_path(const path& directory_path) -{ - // sanity and guaranteed recursion end: - if (!directory_path.has_relative_path()) - throw std::runtime_error("Refusing to create non-existing top level path"); - - // if directory already exists all is good - NTSTATUS status; - if (open_directory(directory_path, false, true, &status).valid()) - return; - - if (status != STATUS_OBJECT_NAME_NOT_FOUND) // STATUS_OBJECT_NAME_NOT_FOUND means - // parent directory already exists - create_path(directory_path - .parent_path()); // otherwise create parent directory (recursively) - - open_directory(directory_path, true); -} - -void TestNtApi::read_file(const path& file_path) -{ - print_operation("Reading file", file_path); - - UNICODE_STRING unicode_path; - RtlInitUnicodeString(&unicode_path, file_path.c_str()); - - OBJECT_ATTRIBUTES attributes; - InitializeObjectAttributes(&attributes, &unicode_path, OBJ_CASE_INSENSITIVE, NULL, - NULL); - - SafeHandle file(this); - IO_STATUS_BLOCK iosb; - NTSTATUS status = NtOpenFile(file, GENERIC_READ | SYNCHRONIZE, &attributes, &iosb, - FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT); - print_result("NtOpenFile", status); - - if (!NT_SUCCESS(status)) - throw test::FuncFailed("NtOpenFile", status); - if (!NT_SUCCESS(iosb.Status)) - throw test::FuncFailed("NtOpenFile", "bad iosb.Status", iosb.Status); - - uint32_t total = 0; - bool ends_with_newline = true; - bool pending_prefix = true; - while (true) { - char buf[4096]; - - memset(&iosb, 0, sizeof(iosb)); - status = NtReadFile(file, NULL, NULL, NULL, &iosb, buf, sizeof(buf), NULL, NULL); - print_result("NtReadFile", status); - if (status == STATUS_END_OF_FILE) - break; - if (!NT_SUCCESS(status)) - throw test::FuncFailed("NtReadFile", status); - - total += iosb.Information; - char* begin = buf; - char* end = begin + iosb.Information; - while (begin != end) { - if (pending_prefix) { - if (output()) - fwrite(FILE_CONTENTS_PRINT_PREFIX, 1, strlen(FILE_CONTENTS_PRINT_PREFIX), - output()); - pending_prefix = false; - } - bool skip_newline = false; - char* print_end = reinterpret_cast(std::memchr(begin, '\n', end - begin)); - if (print_end) { - pending_prefix = true; - if (print_end > begin && *(print_end - 1) == '\r') { - // convert \r\n => \n: - *(print_end - 1) = '\n'; - skip_newline = true; - } else // only a '\n' so just print it - ++print_end; - } else { - print_end = end; - if (print_end > begin && *(print_end - 1) == '\r') { - // buffer ends with \r so skip it under the hope it will be followed with a \n - --print_end; - skip_newline = true; - } - } - if (output()) - fwrite(begin, 1, print_end - begin, output()); - ends_with_newline = print_end > begin && *(print_end - 1) == '\n'; - begin = print_end; - if (skip_newline) - ++begin; - } - if (output() && !ends_with_newline) { - fwrite("\n", 1, 1, output()); - ends_with_newline = true; - } - } - if (output()) { - fprintf(output(), "# Successfully read %u bytes.\n", total); - } -} - -void TestNtApi::write_file(const path& file_path, const void* data, std::size_t size, - bool add_new_line, write_mode mode, bool rw_access) -{ - print_operation(write_operation_name(mode), file_path); - - UNICODE_STRING unicode_path; - RtlInitUnicodeString(&unicode_path, file_path.c_str()); - - OBJECT_ATTRIBUTES attributes; - InitializeObjectAttributes(&attributes, &unicode_path, OBJ_CASE_INSENSITIVE, NULL, - NULL); - - ACCESS_MASK access = GENERIC_WRITE | SYNCHRONIZE; - ULONG disposition = FILE_OPEN; - switch (mode) { - case write_mode::truncate: - disposition = FILE_OVERWRITE; - break; - case write_mode::create: - disposition = FILE_CREATE; - break; - case write_mode::overwrite: - disposition = FILE_SUPERSEDE; - break; - case write_mode::opencreate: - disposition = FILE_OPEN_IF; - break; - case write_mode::append: - disposition = FILE_OPEN_IF; - access = FILE_APPEND_DATA | SYNCHRONIZE; - break; - } - if (rw_access) - access |= GENERIC_READ; - - SafeHandle file(this); - IO_STATUS_BLOCK iosb; - NTSTATUS status = - NtCreateFile(file, access, &attributes, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, 0, - disposition, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); - print_result("NtCreateFile", status); - - if (!NT_SUCCESS(status)) - throw test::FuncFailed("NtCreateFile", status); - if (!NT_SUCCESS(iosb.Status)) - throw test::FuncFailed("NtCreateFile", "bad iosb.Status", iosb.Status); - - if (mode == write_mode::manual_truncate) { - FILE_END_OF_FILE_INFORMATION eofinfo{0}; - status = NtSetInformationFile(file, &iosb, &eofinfo, sizeof(eofinfo), - MyFileEndOfFileInformation); - print_result("NtSetInformationFile", status, false, "EOF"); - - if (!NT_SUCCESS(status)) - throw test::FuncFailed("NtSetInformationFile", status); - if (!NT_SUCCESS(iosb.Status)) - throw test::FuncFailed("NtSetInformationFile", "bad iosb.Status", iosb.Status); - } - - // finally write the data: - size_t total = 0; - - if (data) { - status = NtWriteFile(file, NULL, NULL, NULL, &iosb, const_cast(data), - static_cast(size), NULL, NULL); - print_result("NtWriteFile", status); - if (!NT_SUCCESS(status)) - throw test::FuncFailed("NtWriteFile", status); - if (!NT_SUCCESS(iosb.Status)) - throw test::FuncFailed("NtWriteFile", "bad iosb.Status", iosb.Status); - total += iosb.Information; - - if (add_new_line) { - char buffer[] = "\r\n"; - status = NtWriteFile(file, NULL, NULL, NULL, &iosb, buffer, 2, NULL, NULL); - print_result("NtWriteFile", status); - if (!NT_SUCCESS(status)) - throw test::FuncFailed("NtWriteFile", status); - if (!NT_SUCCESS(iosb.Status)) - throw test::FuncFailed("NtWriteFile", "bad iosb.Status", iosb.Status); - total += iosb.Information; - } - } - - print_write_success(data, size, total); -} - -void TestNtApi::touch_file(const path& file_path, bool full_write_access) -{ - print_operation("Touching file", file_path); - - SYSTEMTIME st; - GetSystemTime(&st); - FILETIME ft; - if (!SystemTimeToFileTime(&st, &ft)) - test::throw_testWinFuncFailed("SystemTimeToFileTime"); - - UNICODE_STRING unicode_path; - RtlInitUnicodeString(&unicode_path, file_path.c_str()); - - OBJECT_ATTRIBUTES attributes; - InitializeObjectAttributes(&attributes, &unicode_path, OBJ_CASE_INSENSITIVE, NULL, - NULL); - - SafeHandle file(this); - IO_STATUS_BLOCK iosb; - auto share_all = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - auto access = - (full_write_access ? GENERIC_WRITE : FILE_WRITE_ATTRIBUTES) | SYNCHRONIZE; - NTSTATUS status = - NtCreateFile(file, access, &attributes, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, - share_all, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); - print_result("NtCreateFile", status); - - if (!NT_SUCCESS(status)) - throw test::FuncFailed("NtCreateFile", status); - if (!NT_SUCCESS(iosb.Status)) - throw test::FuncFailed("NtCreateFile", "bad iosb.Status", iosb.Status); - - FILE_BASIC_INFORMATION basicinfo{0}; - basicinfo.LastWriteTime.LowPart = ft.dwLowDateTime; - basicinfo.LastWriteTime.HighPart = ft.dwHighDateTime; - status = NtSetInformationFile(file, &iosb, &basicinfo, sizeof(basicinfo), - MyFileBasicInformation); - print_result("NtSetInformationFile", status, false, "Basic"); - - if (!NT_SUCCESS(status)) - throw test::FuncFailed("NtSetInformationFile", status); - if (!NT_SUCCESS(iosb.Status)) - throw test::FuncFailed("NtSetInformationFile", "bad iosb.Status", iosb.Status); -} - -void TestNtApi::delete_file(const path& file_path) -{ - print_operation("Deleting file", file_path); - - UNICODE_STRING unicode_path; - RtlInitUnicodeString(&unicode_path, file_path.c_str()); - - OBJECT_ATTRIBUTES attributes; - InitializeObjectAttributes(&attributes, &unicode_path, OBJ_CASE_INSENSITIVE, NULL, - NULL); - - NTSTATUS status = NtDeleteFile(&attributes); - print_result("NtCreateFile", status); - - if (!NT_SUCCESS(status)) - throw test::FuncFailed("NtDeleteFile", status); -} - -void TestNtApi::copy_file(const path& source_path, const path& destination_path, - bool replace_existing) -{ - throw test::FuncFailed("copy_file", "ntapi does not support file copy"); -} - -void TestNtApi::rename_file(const path& source_path, const path& destination_path, - bool replace_existing, bool allow_copy) -{ - if (allow_copy) - throw test::FuncFailed("rename_file", "ntapi does not support file move"); - - print_operation(rename_operation_name(replace_existing, allow_copy), source_path, - destination_path); - - UNICODE_STRING unicode_path; - RtlInitUnicodeString(&unicode_path, source_path.c_str()); - - OBJECT_ATTRIBUTES attributes; - InitializeObjectAttributes(&attributes, &unicode_path, OBJ_CASE_INSENSITIVE, NULL, - NULL); - - SafeHandle file(this); - IO_STATUS_BLOCK iosb; - NTSTATUS status = NtCreateFile(file, FILE_READ_ATTRIBUTES | DELETE | SYNCHRONIZE, - &attributes, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); - print_result("NtCreateFile", status); - - if (!NT_SUCCESS(status)) - throw test::FuncFailed("NtCreateFile", status); - if (!NT_SUCCESS(iosb.Status)) - throw test::FuncFailed("NtCreateFile", "bad iosb.Status", iosb.Status); - - bool dest_full_path = source_path.parent_path() != destination_path.parent_path(); - std::wstring dest = dest_full_path ? destination_path : destination_path.filename(); - std::vector buf(sizeof(FILE_RENAME_INFORMATION) + - sizeof(wchar_t) * dest.length()); - FILE_RENAME_INFORMATION* rename = - reinterpret_cast(buf.data()); - rename->ReplaceIfExists = replace_existing ? TRUE : FALSE; - rename->FileNameLength = sizeof(wchar_t) * dest.length(); - memcpy(&rename->FileName[0], dest.data(), sizeof(wchar_t) * dest.length()); - - status = - NtSetInformationFile(file, &iosb, rename, buf.size(), MyFileRenameInformation); - print_result("NtSetInformationFile", status, false, - dest_full_path ? "rename full path" : "rename filename"); - - if (!NT_SUCCESS(status)) - throw test::FuncFailed("NtSetInformationFile", status); - if (!NT_SUCCESS(iosb.Status)) - throw test::FuncFailed("NtSetInformationFile", "bad iosb.Status", iosb.Status); -} diff --git a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntapi.h b/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntapi.h deleted file mode 100644 index fc6434e..0000000 --- a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntapi.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "test_filesystem.h" - -class TestNtApi : public TestFileSystem -{ -public: - TestNtApi(FILE* output) : TestFileSystem(output) {} - - path real_path(const char* abs_or_rel_path) override; - - FileInfoList list_directory(const path& directory_path) override; - - void create_path(const path& directory_path) override; - - void read_file(const path& file_path) override; - - void write_file(const path& file_path, const void* data, std::size_t size, - bool add_new_line, write_mode mode, bool rw_access = false) override; - - void touch_file(const path& file_path, bool full_write_access = false) override; - - void delete_file(const path& file_path) override; - - void copy_file(const path& source_path, const path& destination_path, - bool replace_existing) override; - - void rename_file(const path& source_path, const path& destination_path, - bool replace_existing, bool allow_copy) override; - - const char* id() override; - -private: - class SafeHandle; - - SafeHandle open_directory(const path& directory_path, bool create, - bool allow_non_existence = false, long* pstatus = nullptr); -}; diff --git a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntdll_declarations.h b/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntdll_declarations.h deleted file mode 100644 index e3799ac..0000000 --- a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntdll_declarations.h +++ /dev/null @@ -1,157 +0,0 @@ -#pragma once - -#define STATUS_NO_MORE_FILES 0x80000006 -#define STATUS_END_OF_FILE 0xC0000011 -#define STATUS_OBJECT_NAME_NOT_FOUND 0xC0000034 -#define STATUS_OBJECT_PATH_NOT_FOUND 0xC000003A - -#define FILE_WRITE_TO_END_OF_FILE 0xffffffff -#define FILE_USE_FILE_POINTER_POSITION 0xfffffffe - -#define InitializeObjectAttributes(p, n, a, r, s) \ - { \ - (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ - (p)->RootDirectory = r; \ - (p)->Attributes = a; \ - (p)->ObjectName = n; \ - (p)->SecurityDescriptor = s; \ - (p)->SecurityQualityOfService = NULL; \ - } - -// winternl.h of course defines a joke FILE_INFORMATION_CLASS (why?!) -// so added MY_ to avoid name collision but this is FILE_INFORMATION_CLASS - -typedef enum _MY_FILE_INFORMATION_CLASS -{ - MyFileDirectoryInformation = 1, - MyFileFullDirectoryInformation, - MyFileBothDirectoryInformation, - MyFileBasicInformation, - MyFileStandardInformation, - MyFileInternalInformation, - MyFileEaInformation, - MyFileAccessInformation, - MyFileNameInformation, - MyFileRenameInformation, - MyFileLinkInformation, - MyFileNamesInformation, - MyFileDispositionInformation, - MyFilePositionInformation, - MyFileFullEaInformation, - MyFileModeInformation, - MyFileAlignmentInformation, - MyFileAllInformation, - MyFileAllocationInformation, - MyFileEndOfFileInformation, - MyFileAlternateNameInformation, - MyFileStreamInformation, - MyFilePipeInformation, - MyFilePipeLocalInformation, - MyFilePipeRemoteInformation, - MyFileMailslotQueryInformation, - MyFileMailslotSetInformation, - MyFileCompressionInformation, - MyFileObjectIdInformation, - MyFileCompletionInformation, - MyFileMoveClusterInformation, - MyFileQuotaInformation, - MyFileReparsePointInformation, - MyFileNetworkOpenInformation, - MyFileAttributeTagInformation, - MyFileTrackingInformation, - MyFileIdBothDirectoryInformation, - MyFileIdFullDirectoryInformation, - MyFileValidDataLengthInformation, - MyFileShortNameInformation, - MyFileIoCompletionNotificationInformation, - MyFileIoStatusBlockRangeInformation, - MyFileIoPriorityHintInformation, - MyFileSfioReserveInformation, - MyFileSfioVolumeInformation, - MyFileHardLinkInformation, - MyFileProcessIdsUsingFileInformation, - MyFileNormalizedNameInformation, - MyFileNetworkPhysicalNameInformation, - MyFileIdGlobalTxDirectoryInformation, - MyFileIsRemoteDeviceInformation, - MyFileUnusedInformation, - MyFileNumaNodeInformation, - MyFileStandardLinkInformation, - MyFileRemoteProtocolInformation, - MyFileRenameInformationBypassAccessCheck, - MyFileLinkInformationBypassAccessCheck, - MyFileVolumeNameInformation, - MyFileIdInformation, - MyFileIdExtdDirectoryInformation, - MyFileReplaceCompletionInformation, - MyFileHardLinkFullIdInformation, - MyFileIdExtdBothDirectoryInformation, - MyFileDispositionInformationEx, - MyFileRenameInformationEx, - MyFileRenameInformationExBypassAccessCheck, - MyFileMaximumInformation -} MY_FILE_INFORMATION_CLASS, - *PMY_FILE_INFORMATION_CLASS; - -typedef struct _FILE_BOTH_DIR_INFORMATION -{ - ULONG NextEntryOffset; - ULONG FileIndex; - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - LARGE_INTEGER EndOfFile; - LARGE_INTEGER AllocationSize; - ULONG FileAttributes; - ULONG FileNameLength; - ULONG EaSize; - CCHAR ShortNameLength; - WCHAR ShortName[12]; - WCHAR FileName[1]; -} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; - -typedef struct _FILE_BASIC_INFORMATION -{ - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - ULONG FileAttributes; -} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; - -typedef struct _FILE_END_OF_FILE_INFORMATION -{ - LARGE_INTEGER EndOfFile; -} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; - -typedef struct _FILE_RENAME_INFORMATION -{ - BOOLEAN ReplaceIfExists; - HANDLE RootDirectory; - ULONG FileNameLength; - WCHAR FileName[1]; -} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION; - -extern "C" __kernel_entry NTSTATUS NTAPI NtQueryDirectoryFile( - IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, - IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, - IN ULONG Length, IN MY_FILE_INFORMATION_CLASS FileInformationClass, - IN BOOLEAN ReturnSingleEntry, IN PUNICODE_STRING FileName, IN BOOLEAN RestartScan); - -extern "C" __kernel_entry NTSTATUS NTAPI -NtReadFile(IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, - IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID Buffer, - IN ULONG Length, IN PLARGE_INTEGER ByteOffset, IN PULONG Key); - -extern "C" __kernel_entry NTSTATUS NTAPI -NtWriteFile(IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, - IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID Buffer, - IN ULONG Length, IN PLARGE_INTEGER ByteOffset, IN PULONG Key); - -extern "C" __kernel_entry NTSTATUS NTAPI NtSetInformationFile( - IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID FileInformation, - IN ULONG Length, IN MY_FILE_INFORMATION_CLASS FileInformationClass); - -extern "C" __kernel_entry NTSTATUS NTAPI -NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes); diff --git a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_w32api.cpp b/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_w32api.cpp deleted file mode 100644 index 372a6f3..0000000 --- a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_w32api.cpp +++ /dev/null @@ -1,370 +0,0 @@ - -#include "test_w32api.h" -#include -#include -#include - -#define WIN32_LEAN_AND_MEAN -#include - -using test::throw_testWinFuncFailed; - -class TestW32Api::SafeHandle -{ -public: - SafeHandle(TestFileSystem* tfs, HANDLE handle = NULL) : m_handle(handle), m_tfs(tfs) - {} - SafeHandle(const SafeHandle&) = delete; - SafeHandle(SafeHandle&& other) : m_handle(other.m_handle), m_tfs(other.m_tfs) - { - other.m_handle = nullptr; - } - - operator HANDLE() { return m_handle; } - operator PHANDLE() { return &m_handle; } - uint32_t result_for_print() - { - return static_cast(reinterpret_cast(m_handle)); - } - - bool valid() const { return m_handle != INVALID_HANDLE_VALUE; } - - ~SafeHandle() - { - if (m_handle != INVALID_HANDLE_VALUE) { - BOOL res = CloseHandle(m_handle); - if (m_tfs) - m_tfs->print_result("CloseHandle", res, true); - if (!res) - if (m_tfs) - m_tfs->print_error("CloseHandle", res, true); - else - std::fprintf(stderr, "CloseHandle failed : %d", GetLastError()); - m_handle = NULL; - } - } - -private: - HANDLE m_handle; - TestFileSystem* m_tfs; -}; - -class TestW32Api::SafeFindHandle -{ -public: - SafeFindHandle(TestFileSystem* tfs, HANDLE handle = NULL) - : m_handle(handle), m_tfs(tfs) - {} - SafeFindHandle(const SafeFindHandle&) = delete; - SafeFindHandle(SafeFindHandle&& other) : m_handle(other.m_handle), m_tfs(other.m_tfs) - { - other.m_handle = nullptr; - } - - operator HANDLE() { return m_handle; } - operator PHANDLE() { return &m_handle; } - uint32_t result_for_print() - { - return static_cast(reinterpret_cast(m_handle)); - } - - bool valid() const { return m_handle != INVALID_HANDLE_VALUE; } - - ~SafeFindHandle() - { - if (m_handle != INVALID_HANDLE_VALUE) { - BOOL res = FindClose(m_handle); - if (m_tfs) - m_tfs->print_result("CloseHandle", res, true); - if (!res) - if (m_tfs) - m_tfs->print_error("CloseHandle", res, true); - else - std::fprintf(stderr, "CloseHandle failed : %d", GetLastError()); - m_handle = NULL; - } - } - -private: - HANDLE m_handle; - TestFileSystem* m_tfs; -}; - -const char* TestW32Api::id() -{ - return "W32"; -} - -TestW32Api::path TestW32Api::real_path(const char* abs_or_rel_path) -{ - if (!abs_or_rel_path || !abs_or_rel_path[0]) - return path(); - - char buf[1024]; - size_t res = GetFullPathNameA(abs_or_rel_path, _countof(buf), buf, NULL); - if (!res || res >= _countof(buf)) - throw_testWinFuncFailed("GetFullPathNameA", res); - return buf; -} - -TestFileSystem::FileInfoList TestW32Api::list_directory(const path& directory_path) -{ - print_operation("Querying directory", directory_path); - - WIN32_FIND_DATA fd; - SafeFindHandle find(this, FindFirstFileW((directory_path / L"*").c_str(), &fd)); - print_result("FindFirstFileW", 0, true, nullptr, true); - if (!find.valid()) - throw_testWinFuncFailed("FindFirstFileW"); - - FileInfoList files; - while (true) { - files.push_back( - FileInformation(fd.cFileName, clean_attributes(fd.dwFileAttributes), - fd.nFileSizeHigh * (MAXDWORD + 1) + fd.nFileSizeLow)); - BOOL res = FindNextFileW(find, &fd); - print_result("FindNextFileW", res, true); - if (!res) - break; - } - - return files; -} - -void TestW32Api::create_path(const path& directory_path) -{ - // sanity and guaranteed recursion end: - if (!directory_path.has_relative_path()) - throw std::runtime_error("Refusing to create non-existing top level path"); - - print_operation("Checking directory", directory_path); - - DWORD attr = GetFileAttributesW(directory_path.c_str()); - DWORD err = GetLastError(); - print_result("GetFileAttributesW", clean_attributes(attr), true); - if (attr != INVALID_FILE_ATTRIBUTES) { - if (attr & FILE_ATTRIBUTE_DIRECTORY) - return; // if directory already exists all is good - else - throw std::runtime_error("path exists but not a directory"); - } - if (err != ERROR_FILE_NOT_FOUND && err != ERROR_PATH_NOT_FOUND) - throw_testWinFuncFailed("GetFileAttributesW"); - - if (err != ERROR_FILE_NOT_FOUND) // ERROR_FILE_NOT_FOUND means parent directory - // already exists - create_path(directory_path - .parent_path()); // otherwise create parent directory (recursively) - - print_operation("Creating directory", directory_path); - - BOOL res = CreateDirectoryW(directory_path.c_str(), NULL); - print_result("CreateDirectoryW", res, true); - if (!res) - throw_testWinFuncFailed("CreateDirectoryW"); -} - -void TestW32Api::read_file(const path& file_path) -{ - print_operation("Reading file", file_path); - - SafeHandle file(this, CreateFileW(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)); - print_result("CreateFileW", 0, true, nullptr, true); - if (!file.valid()) - throw_testWinFuncFailed("CreateFileW"); - - uint32_t total = 0; - bool ends_with_newline = true; - bool pending_prefix = true; - while (true) { - char buf[4096]; - - DWORD read = 0; - BOOL res = ReadFile(file, buf, sizeof(buf), &read, NULL); - print_result("ReadFile", res, true); - if (!res) - throw_testWinFuncFailed("ReadFile"); - if (!read) // eof - break; - - total += read; - char* begin = buf; - char* end = begin + read; - while (begin != end) { - if (pending_prefix) { - if (output()) - fwrite(FILE_CONTENTS_PRINT_PREFIX, 1, strlen(FILE_CONTENTS_PRINT_PREFIX), - output()); - pending_prefix = false; - } - bool skip_newline = false; - char* print_end = reinterpret_cast(std::memchr(begin, '\n', end - begin)); - if (print_end) { - pending_prefix = true; - if (print_end > begin && *(print_end - 1) == '\r') { - // convert \r\n => \n: - *(print_end - 1) = '\n'; - skip_newline = true; - } else // only a '\n' so just print it - ++print_end; - } else { - print_end = end; - if (print_end > begin && *(print_end - 1) == '\r') { - // buffer ends with \r so skip it under the hope it will be followed with a \n - --print_end; - skip_newline = true; - } - } - if (output()) - fwrite(begin, 1, print_end - begin, output()); - ends_with_newline = print_end > begin && *(print_end - 1) == '\n'; - begin = print_end; - if (skip_newline) - ++begin; - } - if (output() && !ends_with_newline) { - fwrite("\n", 1, 1, output()); - ends_with_newline = true; - } - } - if (output()) { - fprintf(output(), "# Successfully read %u bytes.\n", total); - } -} - -void TestW32Api::write_file(const path& file_path, const void* data, std::size_t size, - bool add_new_line, write_mode mode, bool rw_access) -{ - print_operation(write_operation_name(mode), file_path); - - ACCESS_MASK access = GENERIC_WRITE; - DWORD disposition = OPEN_EXISTING; - switch (mode) { - case write_mode::truncate: - disposition = TRUNCATE_EXISTING; - break; - case write_mode::create: - disposition = CREATE_NEW; - break; - case write_mode::overwrite: - disposition = CREATE_ALWAYS; - break; - case write_mode::opencreate: - disposition = OPEN_ALWAYS; - break; - case write_mode::append: - disposition = OPEN_ALWAYS; - access = FILE_APPEND_DATA; - break; - } - if (rw_access) - access |= GENERIC_READ; - - SafeHandle file(this, CreateFile(file_path.c_str(), access, 0, NULL, disposition, - FILE_ATTRIBUTE_NORMAL, NULL)); - print_result("CreateFileW", 0, true, nullptr, true); - if (!file.valid()) - throw_testWinFuncFailed("CreateFile"); - - if (mode == write_mode::manual_truncate) { - BOOL res = SetEndOfFile(file); - print_result("SetEndOfFile", res, true); - if (!res) - throw_testWinFuncFailed("SetEndOfFile"); - } - - if (mode == write_mode::append) { - DWORD res = SetFilePointer(file, 0, NULL, FILE_END); - print_result("SetFilePointer(FILE_END)", res, true); - if (res == INVALID_SET_FILE_POINTER) - throw_testWinFuncFailed("SetEndOfFile"); - } - - size_t total = 0; - - if (data) { - // finally write the data: - DWORD written = 0; - BOOL res = WriteFile(file, data, static_cast(size), &written, NULL); - print_result("WriteFile", written, true); - if (!res) - throw_testWinFuncFailed("WriteFile"); - total += written; - - if (add_new_line) { - res = WriteFile(file, "\r\n", 2, &written, NULL); - print_result("WriteFile", written, true, ""); - if (!res) - throw_testWinFuncFailed("WriteFile"); - total += written; - } - } - - print_write_success(data, size, total); -} - -void TestW32Api::touch_file(const path& file_path, bool full_write_access) -{ - print_operation("Touching file", file_path); - - SYSTEMTIME st; - GetSystemTime(&st); - FILETIME ft; - if (!SystemTimeToFileTime(&st, &ft)) - throw_testWinFuncFailed("SystemTimeToFileTime"); - - auto share_all = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - auto access = full_write_access ? GENERIC_WRITE : FILE_WRITE_ATTRIBUTES; - SafeHandle file(this, CreateFile(file_path.c_str(), access, share_all, NULL, - OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)); - print_result("CreateFileW", 0, true, nullptr, true); - if (!file.valid()) - throw_testWinFuncFailed("CreateFile"); - - BOOL res = SetFileTime(file, nullptr, nullptr, &ft); - print_result("SetFileTime", res, true); - if (!res) - throw_testWinFuncFailed("SetFileTime"); -} - -void TestW32Api::delete_file(const path& file_path) -{ - print_operation("Deleting file", file_path); - - BOOL res = DeleteFileW(file_path.c_str()); - print_result("DeleteFileW", res, true); - if (!res) - throw_testWinFuncFailed("DeleteFileW"); -} - -void TestW32Api::copy_file(const path& source_path, const path& destination_path, - bool replace_existing) -{ - print_operation(replace_existing ? "Copy file over" : "Copy file", source_path, - destination_path); - - BOOL res = - CopyFileW(source_path.c_str(), destination_path.c_str(), !replace_existing); - print_result("CopyFileW", res, true); - if (!res) - throw_testWinFuncFailed("CopyFileW"); -} - -void TestW32Api::rename_file(const path& source_path, const path& destination_path, - bool replace_existing, bool allow_copy) -{ - print_operation(rename_operation_name(replace_existing, allow_copy), source_path, - destination_path); - - DWORD flags = 0; - if (replace_existing) - flags |= MOVEFILE_REPLACE_EXISTING; - if (allow_copy) - flags |= MOVEFILE_COPY_ALLOWED; - - BOOL res = MoveFileExW(source_path.c_str(), destination_path.c_str(), flags); - print_result("MoveFileExW", res, true); - if (!res) - throw_testWinFuncFailed("MoveFileExW"); -} diff --git a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_w32api.h b/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_w32api.h deleted file mode 100644 index cab8e54..0000000 --- a/libs/usvfs/test/usvfs_test_runner/test_file_operations/test_w32api.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "test_filesystem.h" - -class TestW32Api : public TestFileSystem -{ -public: - TestW32Api(FILE* output) : TestFileSystem(output) {} - - path real_path(const char* abs_or_rel_path) override; - - FileInfoList list_directory(const path& directory_path) override; - - void create_path(const path& directory_path) override; - - void read_file(const path& file_path) override; - - void write_file(const path& file_path, const void* data, std::size_t size, - bool add_new_line, write_mode mode, bool rw_access = false) override; - - void touch_file(const path& file_path, bool full_write_access = false) override; - - void delete_file(const path& file_path) override; - - void copy_file(const path& source_path, const path& destination_path, - bool replace_existing) override; - - void rename_file(const path& source_path, const path& destination_path, - bool replace_existing, bool allow_copy) override; - - const char* id() override; - -private: - class SafeHandle; - class SafeFindHandle; -}; diff --git a/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_basic_test.cpp b/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_basic_test.cpp deleted file mode 100644 index c5fb3a1..0000000 --- a/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_basic_test.cpp +++ /dev/null @@ -1,402 +0,0 @@ -#include "usvfs_basic_test.h" - -const char* usvfs_basic_test::scenario_name() -{ - return SCENARIO_NAME; -} - -bool usvfs_basic_test::scenario_run() -{ - // Note: For regression purposes we don't really need to verify the results of most - // our operations as the usvfs_test_base postmortem_check will verify the final state. - // We still also verify the results here because: - // A. In some cases a later step may change the results. - // B. It is easier to understand and maintain the test when the important checks are - // together with - // their related operations. - // C. For open issues the verifications here serve as a "documentation" of the issue - // (i.e. not having - // proper copy_on_write, etc.). - - // Cases not covered by the test: - // - When a "temporary" virtualized directory is created (meaning the directory is - // created only to "shadow" - // a real directory) and is then emptied. This needs to be tested within the same - // prcoess and across different processes. - - ops_list(LR"(.)", true, true); - - // test proper path creation under overwrite when a virtualized folder is written to: - - verify_source_existance(LR"(overwrite\mfolder1)", false); - verify_source_existance(LR"(overwrite\mfolder2)", false); - verify_source_existance(LR"(overwrite\mfolder3)", false); - verify_source_existance(LR"(overwrite\mfolder4)", false); - - ops_overwrite(LR"(mfolder1\newfolder1\newfile1.txt)", - R"(newfile1.txt nonrecursive overwrite subfolder)", false); - verify_source_existance(LR"(overwrite\mfolder1\newfolder1\newfile1.txt)"); - ops_overwrite(LR"(mfolder1\newfile1.txt)", R"(newfile1.txt nonrecursive overwrite)", - false); - ops_read(LR"(mfolder1\newfile1.txt)"); - - ops_overwrite(LR"(mfolder2\newfile2.txt)", R"(newfile2.txt recursive overwrite)", - true); - ops_read(LR"(mfolder2\newfile2.txt)"); - verify_source_contents(LR"(overwrite\mfolder2\newfile2.txt)", - R"(newfile2.txt recursive overwrite)"); - ops_overwrite(LR"(mfolder2\newfile2.txt\fail)", - R"(newfile2.txt is a file so folder creation should fail)", true, - false); - verify_source_contents(LR"(overwrite\mfolder2\newfile2.txt)", - R"(newfile2.txt recursive overwrite)"); - ops_overwrite(LR"(mfolder2\mfile.txt\fail)", - R"(mfile.txt is a file so folder creation should fail)", true, false); - verify_source_existance(LR"(overwrite\mfolder2\mfile.txt)", false); - - ops_overwrite(LR"(mfolder3\newfolder3\newfile3.txt)", - R"(newfile3.txt recursive overwrite)", true); - ops_read(LR"(mfolder3\newfolder3\newfile3.txt)"); - verify_source_contents(LR"(overwrite\mfolder3\newfolder3\newfile3.txt)", - R"(newfile3.txt recursive overwrite)"); - // repeat mfolder3\newfolder3 test as that folder now exists in overwrite and that - // changes things - ops_overwrite(LR"(mfolder3\newfolder3\newfile3e.txt)", - R"(newfile3e.txt recursive overwrite)", true); - ops_read(LR"(mfolder3\newfolder3\newfile3e.txt)"); - verify_source_contents(LR"(overwrite\mfolder3\newfolder3\newfile3e.txt)", - R"(newfile3e.txt recursive overwrite)"); - - ops_overwrite(LR"(mfolder4\newfolder4\d\e\e\p\newfile4.txt)", - R"(newfile4.txt recursive overwrite)", true); - ops_read(LR"(mfolder4\newfolder4\d\e\e\p\newfile4.txt)"); - verify_source_contents(LR"(overwrite\mfolder4\newfolder4\d\e\e\p\newfile4.txt)", - R"(newfile4.txt recursive overwrite)"); - // repeat mfolder4\newfolder4\d\e\e\p test as that folder now exists in overwrite and - // that changes things - ops_overwrite(LR"(mfolder4\newfolder4\d\e\e\p\newfile4e.txt)", - R"(newfile4e.txt recursive overwrite)", true); - ops_read(LR"(mfolder4\newfolder4\d\e\e\p\newfile4e.txt)"); - verify_source_contents(LR"(overwrite\mfolder4\newfolder4\d\e\e\p\newfile4e.txt)", - R"(newfile4e.txt recursive overwrite)"); - // and finally verify also non-recursive works - ops_overwrite(LR"(mfolder4\newfolder4\d\e\e\p\newfile4enr.txt)", - R"(newfile4enr.txt nonrecursive overwrite)", false); - ops_read(LR"(mfolder4\newfolder4\d\e\e\p\newfile4enr.txt)"); - verify_source_contents(LR"(overwrite\mfolder4\newfolder4\d\e\e\p\newfile4enr.txt)", - R"(newfile4enr.txt nonrecursive overwrite)"); - // finally check an intermediate folder: - ops_overwrite(LR"(mfolder4\newfolder4\d\e\epnewfile4r.txt)", - R"(epnewfile4r.txt recursive overwrite)", true); - ops_read(LR"(mfolder4\newfolder4\d\e\epnewfile4r.txt)"); - verify_source_contents(LR"(overwrite\mfolder4\newfolder4\d\e\epnewfile4r.txt)", - R"(epnewfile4r.txt recursive overwrite)"); - ops_overwrite(LR"(mfolder4\newfolder4\d\e\epnewfile4.txt)", - R"(epnewfile4.txt nonrecursive overwrite)", false); - ops_read(LR"(mfolder4\newfolder4\d\e\epnewfile4.txt)"); - verify_source_contents(LR"(overwrite\mfolder4\newfolder4\d\e\epnewfile4.txt)", - R"(epnewfile4.txt nonrecursive overwrite)"); - - verify_mount_existance(LR"(rfolder\rcopyme4.txt)"); - verify_source_existance(LR"(overwrite\mfolder4\newfolder4p)", false); - ops_copy(LR"(rfolder\rcopyme4.txt)", LR"(mfolder4\newfolder4p\rcopyme4.txt)", true); - verify_source_existance(LR"(overwrite\mfolder4\newfolder4p\rcopyme4.txt)", true); - verify_source_existance(LR"(mod4\mfolder4\mfile.txt)"); - verify_source_existance(LR"(overwrite\mfolder4\mfile.txt)", false); - ops_copy(LR"(rfolder\rcopyme4.txt)", LR"(mfolder4\rcopyme4.txt)", false); - verify_source_existance(LR"(overwrite\mfolder4\rcopyme4.txt)"); - - verify_source_contents(LR"(overwrite\mfolder4\newfolder4\d\e\e\p\newfile4.txt)", - R"(newfile4.txt recursive overwrite)"); - // repeat mfolder4\newfolder4\d\e\e\p test as that folder now exists in overwrite and - // that changes things - ops_overwrite(LR"(mfolder4\newfolder4\d\e\e\p\newfile4e.txt)", - R"(newfile4e.txt recursive overwrite)", true); - ops_read(LR"(mfolder4\newfolder4\d\e\e\p\newfile4e.txt)"); - verify_source_contents(LR"(overwrite\mfolder4\newfolder4\d\e\e\p\newfile4e.txt)", - R"(newfile4e.txt recursive overwrite)"); - // and finally verify also non-recursive works - ops_overwrite(LR"(mfolder4\newfolder4\d\e\e\p\newfile4enr.txt)", - R"(newfile4enr.txt nonrecursive overwrite)", false); - ops_read(LR"(mfolder4\newfolder4\d\e\e\p\newfile4enr.txt)"); - verify_source_contents(LR"(overwrite\mfolder4\newfolder4\d\e\e\p\newfile4enr.txt)", - R"(newfile4enr.txt nonrecursive overwrite)"); - // finally check an intermediate folder: - ops_overwrite(LR"(mfolder4\newfolder4\d\e\epnewfile4r.txt)", - R"(epnewfile4r.txt recursive overwrite)", true); - ops_read(LR"(mfolder4\newfolder4\d\e\epnewfile4r.txt)"); - verify_source_contents(LR"(overwrite\mfolder4\newfolder4\d\e\epnewfile4r.txt)", - R"(epnewfile4r.txt recursive overwrite)"); - ops_overwrite(LR"(mfolder4\newfolder4\d\e\epnewfile4.txt)", - R"(epnewfile4.txt nonrecursive overwrite)", false); - ops_read(LR"(mfolder4\newfolder4\d\e\epnewfile4.txt)"); - verify_source_contents(LR"(overwrite\mfolder4\newfolder4\d\e\epnewfile4.txt)", - R"(epnewfile4.txt nonrecursive overwrite)"); - - // test copy on write/delete against source "mod": - - ops_touch(LR"(root0.txt)"); - verify_source_existance(LR"(overwrite\root0.txt)", false); - ops_touch(LR"(root1.txt)"); - verify_source_existance(LR"(overwrite\root1.txt)", false); - ops_touch(LR"(root2.txt)"); - verify_source_existance(LR"(overwrite\root1.txt)", false); - ops_touch(LR"(mod1.txt)"); - verify_source_existance(LR"(overwrite\mod1.txt)", false); - ops_touch(LR"(mfolder1\mfile.txt)"); - verify_source_existance(LR"(overwrite\mfolder1\mfile.txt)", false); - - ops_touch(LR"(root0w.txt)", true); - verify_source_existance(LR"(overwrite\root0w.txt)", false); - ops_touch(LR"(root1w.txt)", true); - verify_source_existance(LR"(overwrite\root1w.txt)", false); - ops_touch(LR"(root2w.txt)", true); - verify_source_existance(LR"(overwrite\root1w.txt)", false); - ops_touch(LR"(mod1w.txt)", true); - verify_source_existance(LR"(overwrite\mod1w.txt)", false); - ops_touch(LR"(mfolder1\mfilew.txt)", true); - verify_source_existance(LR"(overwrite\mfolder1\mfilew.txt)", false); - - { - const auto& old_contents = source_contents(LR"(mod4\mfolder4\mfileoverwrite.txt)"); - verify_source_contents(LR"(mod4\mfolder4\mfileoverwrite.txt)", - old_contents.c_str()); - ops_overwrite(LR"(mfolder4\mfileoverwrite.txt)", - R"(mfolder4\mfileoverwrite.txt overwrite)", false); - ops_read(LR"(mfolder4\mfileoverwrite.txt)"); - if (bool protect_virtualized = false) { - verify_source_contents(LR"(mod4\mfolder4\mfileoverwrite.txt)", - old_contents.c_str()); - verify_source_contents(LR"(overwrite\mfolder4\mfileoverwrite.txt)", - R"(mfolder4\mfileoverwrite.txt overwrite)"); - } else { - verify_source_contents(LR"(mod4\mfolder4\mfileoverwrite.txt)", - R"(mfolder4\mfileoverwrite.txt overwrite)"); - verify_source_existance(LR"(overwrite\mfolder4\mfileoverwrite.txt)", false); - } - } - - { - const auto& old_contents = source_contents(LR"(mod4\mfolder4\mfilerewrite.txt)"); - verify_source_contents(LR"(mod4\mfolder4\mfilerewrite.txt)", old_contents.c_str()); - ops_rewrite(LR"(mfolder4\mfilerewrite.txt)", - R"(mfolder4\mfilerewrite.txt rewrite)"); - ops_read(LR"(mfolder4\mfilerewrite.txt)"); - if (auto copy_on_readwrite_implemented = false) { - verify_source_contents(LR"(mod4\mfolder4\mfilerewrite.txt)", - old_contents.c_str()); - verify_source_contents(LR"(overwrite\mfolder4\mfilerewrite.txt)", - R"(mfolder4\mfilerewrite.txt rewrite)"); - } else { - verify_source_contents(LR"(mod4\mfolder4\mfilerewrite.txt)", - R"(mfolder4\mfilerewrite.txt rewrite)"); - verify_source_existance(LR"(overwrite\mfolder4\mfilerewrite.txt)", false); - } - } - - { - const auto& old_contents = source_contents(LR"(mod4\mfolder4\mfilemoveover.txt)"); - verify_source_contents(LR"(mod4\mfolder4\mfilemoveover.txt)", old_contents.c_str()); - ops_overwrite(LR"(mfolder4\temp_mfilemoveover.txt)", - R"(mfolder4\mfilemoveover.txt overwrite)", false); - verify_source_contents(LR"(overwrite\mfolder4\temp_mfilemoveover.txt)", - R"(mfolder4\mfilemoveover.txt overwrite)"); - ops_rename(LR"(mfolder4\temp_mfilemoveover.txt)", LR"(mfolder4\mfilemoveover.txt)", - true); - ops_read(LR"(mfolder4\mfilemoveover.txt)"); - verify_source_existance(LR"(overwrite\mfolder4\temp_mfilemoveover.txt)", false); - if (bool protect_virtualized = false) { - verify_source_contents(LR"(mod4\mfolder4\mfilemoveover.txt)", - old_contents.c_str()); - verify_source_contents(LR"(overwrite\mfolder4\mfilemoveover.txt)", - R"(mfolder4\mfilemoveover.txt overwrite)"); - } else { - verify_source_contents(LR"(mod4\mfolder4\mfilemoveover.txt)", - R"(mfolder4\mfilemoveover.txt overwrite)"); - verify_source_existance(LR"(overwrite\mfolder4\mfilemoveover.txt)", false); - } - } - - { - const auto& old_contents = - source_contents(LR"(mod4\mfolder4\mfiledeletewrite.txt)"); - verify_source_contents(LR"(mod4\mfolder4\mfiledeletewrite.txt)", - old_contents.c_str()); - ops_deleteoverwrite(LR"(mfolder4\mfiledeletewrite.txt)", - R"(mfolder4\mfiledeletewrite.txt overwrite)", false); - ops_read(LR"(mfolder4\mfiledeletewrite.txt)"); - if (bool protect_virtualized = false) { - verify_source_contents(LR"(overwrite\mfolder4\mfiledeletewrite.txt)", - R"(mfolder4\mfiledeletewrite.txt overwrite)"); - if (auto proper_delete_implemented = false) - verify_source_contents(LR"(mod4\mfolder4\mfiledeletewrite.txt)", - old_contents.c_str()); - else - verify_source_existance(LR"(mod4\mfolder4\mfiledeletewrite.txt)", false); - } else { - verify_source_contents(LR"(mod4\mfolder4\mfiledeletewrite.txt)", - R"(mfolder4\mfiledeletewrite.txt overwrite)"); - verify_source_existance(LR"(overwrite\mfolder4\mfiledeletewrite.txt)", false); - } - } - - { - const auto& old_contents = - source_contents(LR"(mod4\mfolder4\mfiledeletewrite2p.txt)"); - verify_source_contents(LR"(mod4\mfolder4\mfiledeletewrite2p.txt)", - old_contents.c_str()); - ops_delete(LR"(mfolder4\mfiledeletewrite2p.txt)"); - ops_overwrite(LR"(mfolder4\mfiledeletewrite2p.txt)", - R"(mfolder4\mfiledeletewrite2p.txt overwrite)", false); - ops_read(LR"(mfolder4\mfiledeletewrite2p.txt)"); - if (bool protect_virtualized_or_track_deleted_only_in_current_process = true) { - verify_source_contents(LR"(overwrite\mfolder4\mfiledeletewrite2p.txt)", - R"(mfolder4\mfiledeletewrite2p.txt overwrite)"); - if (auto proper_delete_implemented = false) - verify_source_contents(LR"(mod4\mfolder4\mfiledeletewrite2p.txt)", - old_contents.c_str()); - else - verify_source_existance(LR"(mod4\mfolder4\mfiledeletewrite2p.txt)", false); - } else { - verify_source_contents(LR"(mod4\mfolder4\mfiledeletewrite2p.txt)", - R"(mfolder4\mfiledeletewrite2p.txt overwrite)"); - verify_source_existance(LR"(overwrite\mfolder4\mfiledeletewrite2p.txt)", false); - } - } - - { - const auto& old_contents = source_contents(LR"(mod4\mfolder4\mfiledeletemove.txt)"); - verify_source_contents(LR"(mod4\mfolder4\mfiledeletemove.txt)", - old_contents.c_str()); - ops_overwrite(LR"(mfolder4\temp_mfiledeletemove.txt)", - R"(mfolder4\mfiledeletemove.txt overwrite)", false); - verify_source_contents(LR"(overwrite\mfolder4\temp_mfiledeletemove.txt)", - R"(mfolder4\mfiledeletemove.txt overwrite)"); - ops_deleterename(LR"(mfolder4\temp_mfiledeletemove.txt)", - LR"(mfolder4\mfiledeletemove.txt)"); - ops_read(LR"(mfolder4\mfiledeletemove.txt)"); - verify_source_existance(LR"(overwrite\mfolder4\temp_mfiledeletemove.txt)", false); - if (bool protect_virtualized = false) { - verify_source_contents(LR"(overwrite\mfolder4\mfiledeletemove.txt)", - R"(mfolder4\mfiledeletemove.txt overwrite)"); - if (auto proper_delete_implemented = false) - verify_source_contents(LR"(mod4\mfolder4\mfiledeletemove.txt)", - old_contents.c_str()); - else - verify_source_existance(LR"(mod4\mfolder4\mfiledeletemove.txt)", false); - } else { - verify_source_contents(LR"(mod4\mfolder4\mfiledeletemove.txt)", - R"(mfolder4\mfiledeletemove.txt overwrite)"); - verify_source_existance(LR"(overwrite\mfolder4\mfiledeletemove.txt)", false); - } - } - - { - const auto& old_contents = - source_contents(LR"(mod4\mfolder4\mfiledeletemove2p.txt)"); - verify_source_contents(LR"(mod4\mfolder4\mfiledeletemove2p.txt)", - old_contents.c_str()); - ops_delete(LR"(mfolder4\mfiledeletemove2p.txt)"); - ops_overwrite(LR"(mfolder4\temp_mfiledeletemove2p.txt)", - R"(mfolder4\mfiledeletemove2p.txt overwrite)", false); - verify_source_contents(LR"(overwrite\mfolder4\temp_mfiledeletemove2p.txt)", - R"(mfolder4\mfiledeletemove2p.txt overwrite)"); - ops_rename(LR"(mfolder4\temp_mfiledeletemove2p.txt)", - LR"(mfolder4\mfiledeletemove2p.txt)", false); - ops_read(LR"(mfolder4\mfiledeletemove2p.txt)"); - verify_source_existance(LR"(overwrite\mfolder4\temp_mfiledeletemove2p.txt)", false); - if (bool protect_virtualized_or_track_deleted_only_in_current_process = true) { - verify_source_contents(LR"(overwrite\mfolder4\mfiledeletemove2p.txt)", - R"(mfolder4\mfiledeletemove2p.txt overwrite)"); - if (auto proper_delete_implemented = false) - verify_source_contents(LR"(mod4\mfolder4\mfiledeletemove2p.txt)", - old_contents.c_str()); - else - verify_source_existance(LR"(mod4\mfolder4\mfiledeletemove2p.txt)", false); - } else { - verify_source_contents(LR"(mod4\mfolder4\mfiledeletemove2p.txt)", - R"(mfolder4\mfiledeletemove2p.txt overwrite)"); - verify_source_existance(LR"(overwrite\mfolder4\mfiledeletemove2p.txt)", false); - } - } - - // test copy on write/delete/move against original mount files: - - { - const auto& old_contents = mount_contents(LR"(rfolder\rfilerewrite.txt)"); - ops_rewrite(LR"(rfolder\rfilerewrite.txt)", R"(rfolder\rfilerewrite.txt rewrite)"); - ops_read(LR"(rfolder\rfilerewrite.txt)"); - if (auto copy_on_readwrite_implemented = false) { - verify_mount_contents(LR"(rfolder\rfilerewrite.txt)", old_contents.c_str()); - verify_source_contents(LR"(overwrite\rfolder\rfilerewrite.txt)", - R"(rfolder\rfilerewrite.txt rewrite)"); - } else { - verify_mount_contents(LR"(rfolder\rfilerewrite.txt)", - R"(rfolder\rfilerewrite.txt rewrite)"); - verify_source_existance(LR"(overwrite\rfolder\rfilerewrite.txt)", false); - } - } - ops_overwrite(LR"(rfolder\rfilerewrite.txt\fail)", - R"(rfilerewrite.txt is a file so folder creation should fail)", true, - false); - verify_mount_existance( - LR"(rfolder\rfilerewrite.txt)"); // verifies its a file and not a directory - if (auto copy_on_readwrite_implemented = false) - verify_source_existance( - LR"(overwrite\rfolder\rfilerewrite.txt)"); // verifies its a file and not a - // directory - else - verify_source_existance(LR"(overwrite\rfolder\rfilerewrite.txt)", false); - ops_overwrite(LR"(rfolder\rfile0.txt\fail)", - R"(rfile0.txt is a file so folder creation should fail)", true, false); - verify_mount_existance( - LR"(rfolder\rfile0.txt)"); // verifies its a file and not a directory - - { - const auto& old_contents = mount_contents(LR"(rfolder\rfiledeletewrite.txt)"); - ops_deleteoverwrite(LR"(rfolder\rfiledeletewrite.txt)", - R"(rfolder\rfiledeletewrite.txt overwrite)", false); - ops_read(LR"(rfolder\rfiledeletewrite.txt)"); - if (bool protect_virtualized = false) { - verify_source_contents(LR"(overwrite\rfolder\rfiledeletewrite.txt)", - R"(rfolder\rfiledeletewrite.txt overwrite)"); - if (auto proper_delete_implemented = false) - verify_mount_contents(LR"(rfolder\rfiledeletewrite.txt)", old_contents.c_str()); - else - verify_mount_existance(LR"(rfolder\rfiledeletewrite.txt)", false); - } else { - verify_mount_contents(LR"(rfolder\rfiledeletewrite.txt)", - R"(rfolder\rfiledeletewrite.txt overwrite)"); - verify_source_existance(LR"(overwrite\rfolder\rfiledeletewrite.txt)", false); - } - } - - { - const auto& old_contents = mount_contents(LR"(rfolder\rfiledelete.txt)"); - ops_delete(LR"(rfolder\rfiledelete.txt)"); - ops_read(LR"(rfolder\rfiledelete.txt)", false); - if (auto proper_delete_implemented = false) - verify_mount_contents(LR"(rfolder\rfiledelete.txt)", old_contents.c_str()); - else - verify_mount_existance(LR"(rfolder\rfiledelete.txt)", false); - } - - { - const auto& old_contents = mount_contents(LR"(rfolder\rfileoldname.txt)"); - ops_rename(LR"(rfolder\rfileoldname.txt)", LR"(rfolder\rfilenewname.txt)", false, - false); - ops_read(LR"(rfolder\rfileoldname.txt)", false); - ops_read(LR"(rfolder\rfilenewname.txt)"); - verify_source_contents(LR"(overwrite\rfolder\rfilenewname.txt)", - old_contents.c_str()); - verify_mount_existance(LR"(rfolder\rfilenewname.txt)", false); - if (auto copy_on_move_implemented = false) - verify_mount_contents(LR"(rfolder\rfileoldname.txt)", old_contents.c_str()); - else - verify_mount_existance(LR"(rfolder\rfileoldname.txt)", false); - } - - ops_list(LR"(.)", true, true); - - return true; -} diff --git a/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_basic_test.h b/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_basic_test.h deleted file mode 100644 index bec81f2..0000000 --- a/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_basic_test.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "usvfs_test_base.h" - -class usvfs_basic_test : public usvfs_test_base -{ -public: - static constexpr auto SCENARIO_NAME = "basic"; - - usvfs_basic_test(const usvfs_test_options& options) : usvfs_test_base(options) {} - - virtual const char* scenario_name(); - virtual bool scenario_run(); -}; diff --git a/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test.cpp b/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test.cpp deleted file mode 100644 index e6e6bb1..0000000 --- a/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test.cpp +++ /dev/null @@ -1,242 +0,0 @@ - -#include -#include - -#include -#include -#include - -#include "usvfs_basic_test.h" -#include - -void print_usage(const std::wstring& exe_name, const std::wstring& test_name) -{ - using namespace std; - wcerr << "usage: " << exe_name << " [] [: