aboutsummaryrefslogtreecommitdiff
path: root/libs/usvfs/test/usvfs_test_runner/test_file_operations
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-04-12 02:40:16 -0500
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-04-12 02:40:16 -0500
commitbf7a57fc55493247a624ecfd65e4d73964e7d8d2 (patch)
tree0a4b2d6123672768187a5ab863e63cd3f21bb319 /libs/usvfs/test/usvfs_test_runner/test_file_operations
parente0fb66428a9b78b4c326df8d7e30429a5b271d74 (diff)
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"
Diffstat (limited to 'libs/usvfs/test/usvfs_test_runner/test_file_operations')
-rw-r--r--libs/usvfs/test/usvfs_test_runner/test_file_operations/test_file_operations.cpp496
-rw-r--r--libs/usvfs/test/usvfs_test_runner/test_file_operations/test_filesystem.cpp159
-rw-r--r--libs/usvfs/test/usvfs_test_runner/test_file_operations/test_filesystem.h104
-rw-r--r--libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntapi.cpp488
-rw-r--r--libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntapi.h38
-rw-r--r--libs/usvfs/test/usvfs_test_runner/test_file_operations/test_ntdll_declarations.h157
-rw-r--r--libs/usvfs/test/usvfs_test_runner/test_file_operations/test_w32api.cpp370
-rw-r--r--libs/usvfs/test/usvfs_test_runner/test_file_operations/test_w32api.h36
8 files changed, 0 insertions, 1848 deletions
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 <cstdio>
-#include <stdexcept>
-
-#include <boost/filesystem.hpp>
-#include <boost/type_traits.hpp>
-#include <winapi.h>
-
-#include "test_ntapi.h"
-#include "test_w32api.h"
-#include <test_helpers.h>
-
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-
-using usvfs::shared::CodePage;
-using usvfs::shared::string_cast;
-
-void print_usage(const char* myname)
-{
- using namespace std;
- fprintf(stderr, "usage: %s [<options>] <command> [<command params>] ...\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 <dir> : lists the given directory and outputs the results.\n");
- fprintf(stderr, " -listcontents <dir> : lists the given directory, reading all files "
- "and outputs the results.\n");
- fprintf(stderr,
- " -read <file> : reads the given file and outputs the results.\n");
- fprintf(stderr, " -overwrite <file> <string> : overwrites the file at the given path "
- "with the given line (creating directories if in recursive mode).\n");
- fprintf(stderr, " -deleteoverwrite <file> <string> : shorthand for -delete <file> "
- "-overwrite <file> <string>\n");
- fprintf(stderr,
- " -rewrite <file> <string> : 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 <file> : updates last write timestamp of specified file.\n");
- fprintf(stderr, " -touchw <file> : updates last write timestamp using full "
- "write permissions.\n");
- fprintf(stderr, " -delete <file> : deletes the given file.\n");
- fprintf(stderr, " -copy <src> <dst> : copies the given file.\n");
- fprintf(stderr, " -copyover <src> <dst> : copies the given file (replacing existing "
- "destination).\n");
- fprintf(stderr, " -rename <src> <dst> : renames the given file.\n");
- fprintf(stderr, " -renameover <src> <dst> : renames the given file (replacing "
- "existing destination).\n");
- fprintf(stderr, " -deleterename <src> <dst> : shorthand for -delete <dst> -rename "
- "<src> <dst>.\n");
- fprintf(stderr,
- " -move <src> <dst> : moves the given file (not supported by ntapi).\n");
- fprintf(stderr, " -moveover <src> <dst> : moves the given file (replacing existing "
- "destination; not supported by ntapi).\n");
- fprintf(
- stderr,
- " -deletemove <src> <dst> : shorthand for -delete <dst> -move <src> <dst>.\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> : file to log output to (use \"-\" for the "
- "stdout; otherwise path to output should exist).\n");
- fprintf(stderr, " -out+ <file> : similar to -out but appends the file instead "
- "of overwriting it.\n");
- fprintf(stderr, " -cout <file> : similar to -out but does not log PID and "
- "other info which may change between runs.\n");
- fprintf(stderr, " -cout+ <file> : 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 <dir> : 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<TestFileSystem::path> 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<std::string>(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<std::string>(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 <test_helpers.h>
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-
-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<unsigned>(written));
- // heuristics to print nicer one liners:
- if (size == 1 && reinterpret_cast<const char*>(data)[0] == '\n' ||
- size == 2 && reinterpret_cast<const char*>(data)[0] == '\r' &&
- reinterpret_cast<const char*>(data)[1] == '\n')
- fprintf(m_output, "<newline>");
- else {
- fprintf(m_output, "{");
- if (size && reinterpret_cast<const char*>(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 <cstdio>
-#include <filesystem>
-#include <string>
-#include <vector>
-
-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<FileInformation> 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 <cstdio>
-#include <cstring>
-#include <test_helpers.h>
-#include <vector>
-
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-#include <Winternl.h>
-#include <stdio.h>
-
-#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<PFILE_BOTH_DIR_INFORMATION>(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<PFILE_BOTH_DIR_INFORMATION>(
- reinterpret_cast<char*>(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<char*>(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<void*>(data),
- static_cast<ULONG>(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<char> buf(sizeof(FILE_RENAME_INFORMATION) +
- sizeof(wchar_t) * dest.length());
- FILE_RENAME_INFORMATION* rename =
- reinterpret_cast<FILE_RENAME_INFORMATION*>(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 <cstdio>
-#include <cstring>
-#include <test_helpers.h>
-
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-
-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<uint32_t>(reinterpret_cast<uintptr_t>(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<uint32_t>(reinterpret_cast<uintptr_t>(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<char*>(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<DWORD>(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, "<new line>");
- 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;
-};