diff options
Diffstat (limited to 'libs/usvfs/test/usvfs_test_runner/usvfs_test')
5 files changed, 0 insertions, 1780 deletions
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 <iostream> -#include <memory> - -#include <boost/filesystem.hpp> -#include <boost/type_traits.hpp> -#include <winapi.h> - -#include "usvfs_basic_test.h" -#include <stringcast.h> - -void print_usage(const std::wstring& exe_name, const std::wstring& test_name) -{ - using namespace std; - wcerr << "usage: " << exe_name << " [<options>] <scenario>[:<label>]" << endl; - wcerr << "available options:" << endl; - wcerr << " -ops32 : force 32bit file opertations process (default is same " - "bitness)." - << endl; - wcerr << " -ops64 : force 64bit file opertations process (default is same " - "bitness)." - << endl; - wcerr << " -opsexe <file> : full path to file operations executable (overrides " - "-ops32/64)." - << endl; - wcerr << " -opsarg <arg> : adds argument to the start of all file operations." - << endl; - wcerr << " -fixture <dir> : fixture dir (default is test\\fixtures\\" << test_name - << "\\<scenario>)." << endl; - wcerr << " -mapping <file> : mapping file (default is <fixture " - "dir>\\vfs_mappings.txt)." - << endl; - wcerr << " -temp <dir> : temp dir (default is test\\temp\\" << test_name - << "\\<scenario>_<label>)." << endl; - wcerr << " -mount <dir> : mount dir (default is <temp dir>\\mount)." << endl; - wcerr << " -source <dir> : source dir (default is <temp dir>\\source)." << endl; - wcerr << " -out <file> : output file (default is <temp " - "dir>\\<scenario>_<label>.log)." - << endl; - wcerr << " -usvfslog <file> : output file (default is <temp " - "dir>\\<scenario>_<label>_usvfs.log)." - << endl; - wcerr << " -forcetemprecursivedelete : decimate temp dir even if doesn't look like a " - "temp dir." - << endl; - wcerr << endl; - wcerr << "note: if <label> is ommited the current platform (x86/x64) is used." - << endl; - wcerr << "note: mount and source dirs should not exist or be empty directories. if " - "either of them" - << endl; - wcerr << "is not given, the temp dir is first recusrively deleted. to protect " - "against accidents a" - << endl; - wcerr << "heuristic is used to verify the temp dir only has entires which this test " - "creates." - << endl; - wcerr << "-forcetemprecursivedelete can be used to circumvent this heuristic." - << endl; -} - -usvfs_test_base* find_scenario(const std::string& scenario, - const usvfs_test_options& options) -{ - if (scenario == usvfs_basic_test::SCENARIO_NAME) - return new usvfs_basic_test(options); - else - return nullptr; -} - -bool verify_args_exist(const wchar_t* flag, int params, int index, int count) -{ - if (index + params >= count) { - std::wcerr << flag << L" requires " << params << L" arguments" << std::endl; - return false; - } else - return true; -} - -bool verify_file(const test::path& file) -{ - bool is_dir = false; - if (!winapi::ex::wide::fileExists(file.c_str(), &is_dir) || is_dir) { - std::wcerr << L"File does not exist: " << file << std::endl; - return false; - } else - return true; -} - -bool verify_dir(const test::path& dir) -{ - bool is_dir = false; - if (!winapi::ex::wide::fileExists(dir.c_str(), &is_dir) || !is_dir) { - std::wcerr << L"Directory does not exist: " << dir << std::endl; - return false; - } else - return true; -} - -std::wstring get_env_var(const wchar_t* var) -{ - using namespace std; - size_t size = GetEnvironmentVariableW(var, nullptr, 0); - if (size) { - std::wstring value(size, L'\0'); - size = GetEnvironmentVariableW(var, &value[0], static_cast<DWORD>(value.size())); - if (size && size < value.size()) { - value.resize(size); - return value; - } - } - wcerr << L"GetEnvironmentVariableW(" << var << L") failed result=" << size - << L" error=" << GetLastError() << endl; - return wstring(); -} - -bool set_env_var(const wchar_t* var, const std::wstring& value) -{ - if (SetEnvironmentVariableW(var, value.c_str())) - return true; - std::wcerr << L"SetEnvironmentVariableW(" << var << L"," << value - << L") failed error=" << GetLastError() << std::endl; - return false; -} - -int wmain(int argc, wchar_t* argv[]) -{ - using namespace std; - using namespace test; - - const wchar_t* label = nullptr; - wstring scenario; - path temp; - usvfs_test_options options; - - for (int ai = 1; ai < argc; ++ai) { - if (wcscmp(argv[ai], L"-ops32") == 0) - options.set_ops32(); - else if (wcscmp(argv[ai], L"-ops64") == 0) - options.set_ops64(); - else if (wcscmp(argv[ai], L"-opsexe") == 0) { - if (!verify_args_exist(L"-opsexe", 1, ai, argc)) - return 1; - options.opsexe = argv[++ai]; - if (!verify_file(options.opsexe)) - return 1; - } else if (wcscmp(argv[ai], L"-opsarg") == 0) { - if (!verify_args_exist(L"-opsarg", 1, ai, argc)) - return 1; - options.add_ops_options(argv[++ai]); - } else if (wcscmp(argv[ai], L"-fixture") == 0) { - if (!verify_args_exist(L"-fixture", 1, ai, argc)) - return 1; - options.fixture = argv[++ai]; - if (!verify_dir(options.fixture)) - return 1; - } else if (wcscmp(argv[ai], L"-mapping") == 0) { - if (!verify_args_exist(L"-mapping", 1, ai, argc)) - return 1; - options.mapping = argv[++ai]; - if (!verify_file(options.mapping)) - return 1; - } else if (wcscmp(argv[ai], L"-temp") == 0) { - if (!verify_args_exist(L"-temp", 1, ai, argc)) - return 1; - options.mount = argv[++ai]; - } else if (wcscmp(argv[ai], L"-mount") == 0) { - if (!verify_args_exist(L"-mount", 1, ai, argc)) - return 1; - options.mount = argv[++ai]; - } else if (wcscmp(argv[ai], L"-source") == 0) { - if (!verify_args_exist(L"-source", 1, ai, argc)) - return 1; - options.source = argv[++ai]; - } else if (wcscmp(argv[ai], L"-out") == 0) { - if (!verify_args_exist(L"-out", 1, ai, argc)) - return 1; - options.output = argv[++ai]; - } else if (wcscmp(argv[ai], L"-usvfslog") == 0) { - if (!verify_args_exist(L"-usvfslog", 1, ai, argc)) - return 1; - options.usvfs_log = argv[++ai]; - } else if (wcscmp(argv[ai], L"-forcetemprecursivedelete") == 0) - options.force_temp_cleanup = true; - else if (argv[ai][0] == '-') { - wcerr << L"Unknown option " << argv[ai] << endl; - return 1; - } else if (!scenario.empty()) { - wcerr << L"Multiple scenarios can not be specified: " << scenario.c_str() << L", " - << argv[ai] << endl; - return 1; - } else { - label = wcschr(argv[ai], ':'); - if (label) { - scenario = std::wstring(static_cast<const wchar_t*>(argv[ai]), label); - ++label; // skip the ':' - } else - scenario = argv[ai]; - - if (scenario.empty()) { - wcerr << L"Scenario name can not be empty!" << endl; - return 1; - } - } - } - - path test_name{"usvfs_test"}; - - if (scenario.empty()) { - print_usage(path(argv[0]).stem(), test_name); - return 1; - } - - options.fill_defaults(test_name, scenario, label); - - unique_ptr<usvfs_test_base> test{find_scenario( - usvfs::shared::string_cast<std::string>(scenario, usvfs::shared::CodePage::UTF8), - options)}; - if (!test) { - wcerr << L"ERROR: Unknown scenario specified: " << scenario.c_str() << endl; - return 2; - } - - auto dllPath = path_of_usvfs_lib(platform_dependant_executable("usvfs", "dll")); - ScopedLoadLibrary loadDll(dllPath.c_str()); - if (!loadDll) { - wcerr << L"ERROR: failed to load usvfs dll: " << dllPath.c_str() << L", " - << GetLastError() << endl; - return 3; - } - - // In order for bin\usvfs_proxy_x??.exe to find the lib\usvfs_x??.dll file we add the - // lib folder to our path: - std::wstring env_path = get_env_var(L"Path"); - if (env_path.empty() || - !set_env_var(L"Path", dllPath.parent_path().wstring() + L";" + env_path)) { - wcerr << L"ERROR: failed to add usvfs dll directory to path" << endl; - return 3; - } - - return test->run(path(argv[0]).stem()); -} diff --git a/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test_base.cpp b/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test_base.cpp deleted file mode 100644 index bfa391e..0000000 --- a/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test_base.cpp +++ /dev/null @@ -1,1002 +0,0 @@ - -#include "usvfs_test_base.h" -#include <boost/filesystem.hpp> -#include <boost/type_traits.hpp> -#include <cctype> -#include <cerrno> -#include <chrono> -#include <future> -#include <iostream> -#include <stringcast.h> -#include <thread> -#include <unordered_set> -#include <usvfs.h> -#include <vector> -#include <winapi.h> - -using test::throw_testWinFuncFailed; - -// usvfs_test_options class: - -void usvfs_test_options::fill_defaults(const path& test_name, - const std::wstring& scenario, - const wchar_t* label) -{ - using namespace test; - - std::wstring lbl; - if (label) - lbl = label; - -#ifdef _WIN64 - set_ops64(); - if (!label) - lbl = L"x64"; -#else - set_ops32(); - if (!label) - lbl = L"x86"; -#endif - - std::wstring scenario_label = scenario; - if (!lbl.empty()) { - scenario_label += L"_"; - scenario_label += lbl; - } - - if (fixture.empty()) - fixture = path_of_test_fixtures(test_name / scenario); - - if (mapping.empty()) - mapping = fixture / DEFAULT_MAPPING; - - if (temp.empty()) { - temp = path_of_test_temp(test_name / scenario_label); - } - - if (mount.empty()) { - mount = temp / MOUNT_DIR; - temp_cleanup = true; - } - - if (source.empty()) { - source = temp / SOURCE_DIR; - temp_cleanup = true; - } - - if (output.empty()) { - output = temp / scenario_label; - output += ".log"; - } - - if (usvfs_log.empty()) { - usvfs_log = temp / scenario_label; - usvfs_log += "_usvfs.log"; - } -} - -void usvfs_test_options::set_ops32() -{ - if (opsexe.empty()) - opsexe = test::path_of_test_bin(L"test_file_operations_x86.exe"); -} - -void usvfs_test_options::set_ops64() -{ - if (opsexe.empty()) - opsexe = test::path_of_test_bin(L"test_file_operations_x64.exe"); -} - -void usvfs_test_options::add_ops_options(const std::wstring& options) -{ - if (!ops_options.empty()) - ops_options += L" "; - ops_options += options; -} - -// usvfs_connector helper class: - -class usvfs_connector -{ -public: - using path = test::path; - - usvfs_connector(const usvfs_test_options& options) - : m_usvfs_log(test::ScopedFILE::open(options.usvfs_log, L"wt")), - m_exit_future(m_exit_signal.get_future()) - { - winapi::ex::wide::createPath(options.usvfs_log.parent_path().c_str()); - - std::wcout << "Connecting VFS..." << std::endl; - - std::unique_ptr<usvfsParameters, decltype(&usvfsFreeParameters)> parameters{ - usvfsCreateParameters(), &usvfsFreeParameters}; - - usvfsSetInstanceName(parameters.get(), "usvfs_test"); - usvfsSetDebugMode(parameters.get(), false); - usvfsSetLogLevel(parameters.get(), LogLevel::Debug); - usvfsSetCrashDumpType(parameters.get(), CrashDumpsType::None); - usvfsSetCrashDumpPath(parameters.get(), ""); - - usvfsInitLogging(false); - usvfsCreateVFS(parameters.get()); - - m_log_thread = std::thread(&usvfs_connector::usvfs_logger, this); - } - - ~usvfs_connector() - { - usvfsDisconnectVFS(); - m_exit_signal.set_value(); - m_log_thread.join(); - } - - enum class map_type - { - none, // the mapping_reader uses this value but will never pass it to the - // usvfs_connector (which ignored such entries) - dir, - dircreate, - file - }; - - struct mapping - { - mapping(map_type itype, std::wstring isource, std::wstring idestination) - : type(itype), source(isource), destination(idestination) - {} - - map_type type; - path source; - path destination; - }; - - using mappings_list = std::vector<mapping>; - - void updateMapping(const mappings_list& mappings, const usvfs_test_options& options, - FILE* log) - { - using namespace std; - using namespace usvfs::shared; - - fprintf(log, "Updating VFS mappings:\n"); - - usvfsClearVirtualMappings(); - - for (const auto& map : mappings) { - const string& source = - usvfs_test_base::SOURCE_LABEL + - test::path_as_relative(options.source, map.source).string(); - const string& destination = - usvfs_test_base::MOUNT_LABEL + - test::path_as_relative(options.mount, map.destination).string(); - switch (map.type) { - case map_type::dir: - fprintf(log, " mapdir: %s => %s\n", source.c_str(), destination.c_str()); - usvfsVirtualLinkDirectoryStatic(map.source.c_str(), map.destination.c_str(), - LINKFLAG_RECURSIVE); - break; - - case map_type::dircreate: - fprintf(log, " mapdircreate: %s => %s\n", source.c_str(), destination.c_str()); - usvfsVirtualLinkDirectoryStatic(map.source.c_str(), map.destination.c_str(), - LINKFLAG_CREATETARGET | LINKFLAG_RECURSIVE); - break; - - case map_type::file: - fprintf(log, " mapfile: %s => %s\n", source.c_str(), destination.c_str()); - usvfsVirtualLinkFile(map.source.c_str(), map.destination.c_str(), - LINKFLAG_RECURSIVE); - break; - } - } - - fprintf(log, "\n"); - } - - static DWORD spawn(wchar_t* commandline) - { - using namespace usvfs::shared; - - STARTUPINFO si{0}; - si.cb = sizeof(si); - PROCESS_INFORMATION pi{0}; - - if (!usvfsCreateProcessHooked(NULL, commandline, NULL, NULL, FALSE, 0, NULL, NULL, - &si, &pi)) - throw_testWinFuncFailed( - "CreateProcessHooked", - string_cast<std::string>(commandline, CodePage::UTF8).c_str()); - - WaitForSingleObject(pi.hProcess, INFINITE); - - DWORD exit = 99; - if (!GetExitCodeProcess(pi.hProcess, &exit)) { - test::WinFuncFailedGenerator failed; - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - throw failed("GetExitCodeProcess"); - } - - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - - return exit; - } - - void usvfs_logger() - { - fprintf(m_usvfs_log, "usvfs_test usvfs logger started:\n"); - fflush(m_usvfs_log); - - constexpr size_t size = 1024; - char buf[size + 1]{0}; - int noLogCycles = 0; - std::chrono::milliseconds wait_for; - do { - if (usvfsGetLogMessages(buf, size, false)) { - fwrite(buf, 1, strlen(buf), m_usvfs_log); - fwrite("\n", 1, 1, m_usvfs_log); - fflush(m_usvfs_log); - noLogCycles = 0; - } else - ++noLogCycles; - if (noLogCycles) - wait_for = std::chrono::milliseconds(std::min(40, noLogCycles) * 5); - else - wait_for = std::chrono::milliseconds(0); - } while (m_exit_future.wait_for(wait_for) == std::future_status::timeout); - - while (usvfsGetLogMessages(buf, size, false)) { - fwrite(buf, 1, strlen(buf), m_usvfs_log); - fwrite("\n", 1, 1, m_usvfs_log); - } - - fprintf(m_usvfs_log, "usvfs log closed.\n"); - m_usvfs_log.close(); - } - -private: - test::ScopedFILE m_usvfs_log; - std::thread m_log_thread; - std::promise<void> m_exit_signal; - std::shared_future<void> m_exit_future; -}; - -// mappings_reader - -class mappings_reader -{ -public: - using path = test::path; - using string = std::string; - using wstring = std::wstring; - using map_type = usvfs_connector::map_type; - using mapping = usvfs_connector::mapping; - using mappings_list = usvfs_connector::mappings_list; - - mappings_reader(const path& mount_base, const path& source_base) - : m_mount_base(mount_base), m_source_base(source_base) - {} - - mappings_list read(const path& mapfile) - { - const auto map = test::ScopedFILE::open(mapfile, L"rt"); - mappings_list mappings; - - char line[1024]; - while (!feof(map)) { - // read one line: - if (!fgets(line, _countof(line), map)) - if (feof(map)) - break; - else - throw_testWinFuncFailed("fgets", "reading mappings"); - - if (empty_line(line)) - continue; - - if (start_nesting(line, "mapdir")) - m_nesting = map_type::dir; - else if (start_nesting(line, "mapdircreate")) - m_nesting = map_type::dircreate; - else if (start_nesting(line, "mapfile")) - m_nesting = map_type::file; - else if (!isspace(*line)) // mapping sources should be indented and we already - // check all the mapping directives - throw test::FuncFailed("mappings_reader::read", "invalid mappings file line", - line); - else { - const auto& source_rel = trimmed_wide_string(line); - mappings.push_back(mapping(m_nesting, m_source_base / source_rel, m_mount)); - } - } - - return mappings; - } - - bool start_nesting(const char* line, const char* directive) - { - // check if line starts with directive and if so skip it: - auto dlen = strlen(directive); - auto after = line + dlen; - if (strncmp(directive, line, dlen) == 0 && (!*after || isspace(*after))) { - m_mount = m_mount_base; - const auto& mount_rel = trimmed_wide_string(after); - if (!mount_rel.empty()) - m_mount /= mount_rel; - return true; - } else - return false; - } - - static wstring trimmed_wide_string(const char* in) - { - while (std::isspace(*in)) - ++in; - auto end = in; - end += strlen(end); - while (end > in && std::isspace(*(end - 1))) - --end; - return usvfs::shared::string_cast<wstring>(string(in, end), - usvfs::shared::CodePage::UTF8); - } - - static bool empty_line(const char* line) - { - for (; *line; ++line) { - if (*line == '#') // comment, ignore rest of line - return true; - else if (!std::isspace(*line)) - return false; - } - return true; - } - -private: - path m_mount_base; - path m_source_base; - path m_mount; - map_type m_nesting = map_type::none; -}; - -// usvfs_test_base class: - -void usvfs_test_base::cleanup_temp() -{ - using namespace test; - using namespace winapi::ex::wide; - - bool isDir = false; - if (!m_o.temp_cleanup || !fileExists(m_o.temp.c_str(), &isDir)) - return; - - if (!isDir) { - if (m_o.force_temp_cleanup) - delete_file(m_o.temp); - else - throw FuncFailed("cleanup_temp", "temp exists but is a file", - m_o.temp.string().c_str()); - } else { - std::vector<wstring> cleanfiles; - std::vector<wstring> cleandirs; - std::vector<wstring> otherdirs; - bool output_file = false; - for (auto f : quickFindFiles(m_o.temp.c_str(), L"*")) - if (f.fileName == L"." || f.fileName == L"..") - continue; - else if ((f.attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - if (f.fileName == m_o.output.filename()) - output_file = true; - cleanfiles.push_back(f.fileName); - } else if (f.fileName == SOURCE_DIR || f.fileName == MOUNT_DIR) - cleandirs.push_back(f.fileName); - else - otherdirs.push_back(f.fileName); - if (!cleanfiles.empty() || !cleandirs.empty() || !otherdirs.empty()) { - if (!m_o.force_temp_cleanup && !otherdirs.empty()) - throw FuncFailed("cleanup_temp", - "Refusing to clean temp dir with non-mount/source directories " - "(clean manually and rerun)", - m_o.temp.string().c_str()); - if (!m_o.force_temp_cleanup && cleandirs.empty() && !output_file) - throw FuncFailed("cleanup_temp", - "Refusing to clean temp dir with no directories and no output " - "log (clean manually and rerun)", - m_o.temp.string().c_str()); - std::wcout << "Cleaning previous temp dir: " << m_o.temp.c_str() << std::endl; - for (auto f : cleanfiles) - delete_file(m_o.temp / f); - for (auto d : cleandirs) - recursive_delete_files(m_o.temp / d); - for (auto d : otherdirs) - recursive_delete_files(m_o.temp / d); - } - } -} - -void usvfs_test_base::copy_fixture() -{ - using namespace test; - using namespace winapi::ex::wide; - - path fmount = m_o.fixture / MOUNT_DIR; - path fsource = m_o.fixture / SOURCE_DIR; - - bool isDir = false; - if (!fileExists(fmount.c_str(), &isDir) || !isDir) - throw FuncFailed("copy_fixture", "fixtures dir does not exist", - fmount.string().c_str()); - if (!fileExists(fsource.c_str(), &isDir) || !isDir) - throw FuncFailed("copy_fixture", "fixtures dir does not exist", - fsource.string().c_str()); - if (fileExists(m_o.mount.c_str(), &isDir)) - throw FuncFailed("copy_fixture", "source dir already exists", - m_o.mount.string().c_str()); - if (fileExists(m_o.source.c_str(), &isDir)) - throw FuncFailed("copy_fixture", "source dir already exists", - m_o.source.string().c_str()); - - std::wcout << "Copying fixture: " << m_o.fixture << std::endl; - recursive_copy_files(fmount, m_o.mount, false); - recursive_copy_files(fsource, m_o.source, false); -} - -bool usvfs_test_base::postmortem_check() -{ - path gold_output = m_o.fixture / m_o.output.filename(); - - { - const auto& log = output(); - - path mount_gold = MOUNT_DIR; - mount_gold += POSTMORTEM_SUFFIX; - path source_gold = SOURCE_DIR; - source_gold += POSTMORTEM_SUFFIX; - - bool is_dir = false; - if (!winapi::ex::wide::fileExists(m_o.mount.c_str(), &is_dir) || !is_dir) { - fprintf(log, " ERROR: mount directory does not exist?!\n"); - return false; - } - if (!winapi::ex::wide::fileExists(m_o.source.c_str(), &is_dir) || !is_dir) { - fprintf(log, " ERROR: source directory does not exist?!\n"); - return false; - } - if (!winapi::ex::wide::fileExists((m_o.fixture / mount_gold).c_str(), &is_dir) || - !is_dir) { - fprintf(log, " ERROR: fixtures golden mount does not exist: %s\n", - mount_gold.string().c_str()); - return false; - } - if (!winapi::ex::wide::fileExists((m_o.fixture / source_gold).c_str(), &is_dir) || - !is_dir) { - fprintf(log, " ERROR: fixtures golden source does not exist: %s\n", - mount_gold.string().c_str()); - return false; - } - if (!winapi::ex::wide::fileExists(gold_output.c_str(), &is_dir) || is_dir) { - fprintf(log, " ERROR: golden scenario output does not exist: %s\n", - gold_output.filename().string().c_str()); - return false; - } - - fprintf(log, "postmortem check of %s against golden %s...\n", - m_o.mount.filename().string().c_str(), mount_gold.string().c_str()); - bool mount_check = - recursive_compare_dirs(path(), m_o.fixture / mount_gold, m_o.mount, log); - - fprintf(log, "postmortem check of %s against golden %s...\n", - m_o.source.filename().string().c_str(), source_gold.string().c_str()); - bool source_check = - recursive_compare_dirs(path(), m_o.fixture / source_gold, m_o.source, log); - - if (mount_check && source_check) - fprintf(log, "postmortem check successful.\n"); - else { - fprintf(log, "ERROR: postmortem check failed!\n"); - return false; - } - } // close output before comparing it - - // don't print anything more to the output (except maybe errors), - // so that the final output can be copied as is to the fixtures (when updating the - // golden version) - - // block remove 2024/06/07 - one would need to regenerate a gold output for this but - // I am not sure this is still relevant - // - // if (!test::compare_files(gold_output, m_o.output, false)) { - // fprintf(output(), "ERROR: output does not match gold output: %s\n", - // m_o.output.filename().string().c_str()); return false; - //} - - return true; -} - -bool usvfs_test_base::recursive_compare_dirs(path rel_path, path gold_base, - path result_base, FILE* log) -{ - path result_full = result_base / rel_path; - path gold_full = gold_base / rel_path; - - std::unordered_set<std::wstring> gold_dirs; - std::unordered_set<std::wstring> gold_files; - for (const auto& f : winapi::ex::wide::quickFindFiles(gold_full.c_str(), L"*")) { - if (f.fileName == L"." || f.fileName == L"..") - continue; - if (f.attributes & FILE_ATTRIBUTE_DIRECTORY) - gold_dirs.insert(f.fileName); - else - gold_files.insert(f.fileName); - } - - bool all_good = true; - - std::vector<std::wstring> recurse; - for (const auto& f : winapi::ex::wide::quickFindFiles(result_full.c_str(), L"*")) { - if (f.fileName == L"." || f.fileName == L"..") - continue; - if (f.attributes & FILE_ATTRIBUTE_DIRECTORY) { - const auto& find = gold_dirs.find(f.fileName); - if (find != gold_dirs.end()) { - gold_dirs.erase(find); - recurse.push_back(f.fileName); - } else { - fprintf(log, " unexpected directory found: %s%s\n", MOUNT_LABEL, - (rel_path / f.fileName).string().c_str()); - all_good = false; - } - } else { - const auto& find = gold_files.find(f.fileName); - if (find != gold_files.end()) { - gold_files.erase(find); - if (!test::compare_files(gold_full / f.fileName, result_full / f.fileName, - false)) { - fprintf(log, " file contents differs: %s%s\n", MOUNT_LABEL, - (rel_path / f.fileName).string().c_str()); - all_good = false; - } - } else { - fprintf(log, " unexpected file found: %s%s\n", MOUNT_LABEL, - (rel_path / f.fileName).string().c_str()); - all_good = false; - } - } - } - - for (auto d : gold_dirs) { - fprintf(log, " expected directory not found: %s%s\n", MOUNT_LABEL, - (rel_path / d).string().c_str()); - all_good = false; - } - - for (auto f : gold_files) { - fprintf(log, " expected file not found: %s%s\n", MOUNT_LABEL, - (rel_path / f).string().c_str()); - all_good = false; - } - - for (auto r : recurse) - all_good &= recursive_compare_dirs(rel_path / r, gold_base, result_base, log); - - return all_good; -} - -test::ScopedFILE usvfs_test_base::output() -{ - auto log = test::ScopedFILE::open(m_o.output, m_clean_output ? L"wt" : L"at"); - m_clean_output = false; - return log; -} - -void usvfs_test_base::clean_output() -{ - using namespace std; - - errno_t err; - auto in = test::ScopedFILE::open(m_o.output, L"rt", err); - if (err == ENOENT) { - wcerr << L"warning: no " << m_o.output << L" to clean." << endl; - return; - } else if (err || !in) - throw_testWinFuncFailed("_wfopen_s", m_o.output.string().c_str(), err); - - path clean = m_o.output.parent_path() / m_o.output.stem(); - clean += OUTPUT_CLEAN_SUFFIX; - clean += m_o.output.extension(); - - auto out = test::ScopedFILE::open(clean, L"wt"); - wcout << L"Cleaning " << m_o.output << " to " << clean << endl; - - char line[1024]; - while (!feof(in)) { - // read one line: - if (!fgets(line, _countof(line), in)) - if (feof(in)) - break; - else - throw_testWinFuncFailed("fgets", "reading output"); - if (*line == '#') - continue; - - // in order for the clean output to compare cleanly between run with different - // options we clean out things like the platform and the ops log name (which - // contians the scenario label): - - char* platform = line; - while (platform) { - char* platform_x86 = strstr(platform, "x86"); - char* platform_x64 = strstr(platform, "x64"); - if (platform_x86 && platform_x64) - platform = std::min(platform_x86, platform_x64); - else if (platform_x86) - platform = platform_x86; - else if (platform_x64) - platform = platform_x64; - else - platform = nullptr; - if (platform) { - platform[1] = platform[2] = '?'; - platform += 3; - } - } - - char* cout_end = strstr(line, "-cout+ "); - char* cout_log_end = nullptr; - if (cout_end) { - cout_end += strlen("-cout+ "); - cout_log_end = strchr(cout_end, ' '); - } - if (cout_log_end && cout_log_end > cout_end) { - cout_end[0] = '?'; - if (cout_log_end > cout_end + 1) - memmove(cout_end + 1, cout_log_end, strlen(cout_log_end) + 1); - } - - fputs(line, out); - } -} - -int usvfs_test_base::run(const std::wstring& exe_name) -{ - using namespace usvfs::shared; - using namespace std; - - int res = run_impl(exe_name); - try { - clean_output(); - } catch (const exception& e) { - wcerr << "CERROR: " << string_cast<wstring>(e.what(), CodePage::UTF8).c_str() - << endl; - } catch (...) { - wcerr << "CERROR: unknown exception" << endl; - } - if (!res) - wcout << "scenario " << scenario_name() << " PASSED." << endl; - else - wcerr << "scenario " << scenario_name() << " FAILED!" << endl; - return res; -} - -int usvfs_test_base::run_impl(const std::wstring& exe_name) -{ - using namespace usvfs::shared; - using namespace std; - - try { - winapi::ex::wide::createPath(m_o.output.parent_path().c_str()); - - // we read mappings first only because it is "non-destructive" but might raise an - // error if mappings invalid - auto mappings = mappings_reader(m_o.mount, m_o.source).read(m_o.mapping); - - cleanup_temp(); - log_settings(exe_name); - copy_fixture(); - - usvfs_connector usvfs(m_o); - { - const auto& log = output(); - usvfs.updateMapping(mappings, m_o, log); - - fprintf(log, "running scenario %s:\n\n", scenario_name()); - } - auto res = scenario_run(); - { - const auto& log = output(); - if (res) - fprintf(log, "\nscenario ended successfully!\n\n"); - else - fprintf(log, "\nscenario failed miserably.\n"); - } - - if (!res) - return 7; - - if (!postmortem_check()) - return 8; - - return 0; - } -#if 1 // just a convient way to not catch exception when debugging - catch (const exception& e) { - try { - wcerr << "ERROR: " << string_cast<wstring>(e.what(), CodePage::UTF8).c_str() - << endl; - fprintf(output(), "ERROR: %s\n", e.what()); - } catch (const exception& e) { - wcerr << "ERROR^2: " << string_cast<wstring>(e.what(), CodePage::UTF8).c_str() - << endl; - } catch (...) { - wcerr << "ERROR^2: unknown exception" << endl; - } - } catch (...) { - try { - wcerr << "ERROR: unknown exception" << endl; - fprintf(output(), "ERROR: unknown exception\n"); - } catch (const exception& e) { - wcerr << "ERROR^2: " << string_cast<wstring>(e.what(), CodePage::UTF8).c_str() - << endl; - } catch (...) { - wcerr << "ERROR^2: unknown exception" << endl; - } - } -#else - catch (bool) { - } -#endif - return 9; // exception -} - -void usvfs_test_base::log_settings(const std::wstring& exe_name) -{ - using namespace usvfs::shared; - fprintf(output(), "%s %s started with %s%s%s\n\n", - string_cast<std::string>(exe_name).c_str(), scenario_name(), - m_o.opsexe.filename().string().c_str(), m_o.ops_options.empty() ? "" : " ", - string_cast<std::string>(m_o.ops_options).c_str()); -} - -void usvfs_test_base::ops_list(const path& rel_path, bool recursive, bool with_contents, - bool should_succeed, const wstring& additional_args) -{ - wstring cmd = recursive ? L"-r -list" : L"-list"; - if (with_contents) - cmd += L"contents"; - run_ops(should_succeed, cmd, rel_path, additional_args); -} - -void usvfs_test_base::ops_read(const path& rel_path, bool should_succeed, - const wstring& additional_args) -{ - run_ops(should_succeed, L"-read", rel_path, additional_args); -} - -void usvfs_test_base::ops_rewrite(const path& rel_path, const char* contents, - bool should_succeed, const wstring& additional_args) -{ - using namespace usvfs::shared; - run_ops(should_succeed, L"-rewrite", rel_path, additional_args, - L"\"" + string_cast<wstring>(contents, CodePage::UTF8) + L"\""); -} - -void usvfs_test_base::ops_overwrite(const path& rel_path, const char* contents, - bool recursive, bool should_succeed, - const wstring& additional_args) -{ - using namespace usvfs::shared; - run_ops(should_succeed, recursive ? L"-r -overwrite" : L"-overwrite", rel_path, - additional_args, - L"\"" + string_cast<wstring>(contents, CodePage::UTF8) + L"\""); -} - -void usvfs_test_base::ops_touch(const path& rel_path, bool full_write_access, - bool should_succeed, const wstring& additional_args) -{ - run_ops(should_succeed, full_write_access ? L"-touchw" : L"-touch", rel_path, - additional_args); -} - -void usvfs_test_base::ops_deleteoverwrite(const path& rel_path, const char* contents, - bool recursive, bool should_succeed, - const wstring& additional_args) -{ - using namespace usvfs::shared; - run_ops(should_succeed, recursive ? L"-r -deleteoverwrite" : L"-deleteoverwrite", - rel_path, additional_args, - L"\"" + string_cast<wstring>(contents, CodePage::UTF8) + L"\""); -} - -void usvfs_test_base::ops_delete(const path& rel_path, bool should_succeed, - const wstring& additional_args) -{ - run_ops(should_succeed, L"-delete", rel_path, additional_args); -} - -void usvfs_test_base::ops_copy(const path& src_rel_path, const path& dest_rel_path, - bool replace, bool should_succeed, - const wstring& additional_args) -{ - run_ops(should_succeed, replace ? L"-copyover" : L"-copy", src_rel_path, - additional_args, wstring(), dest_rel_path); -} - -void usvfs_test_base::ops_rename(const path& src_rel_path, const path& dest_rel_path, - bool replace, bool allow_copy, bool should_succeed, - const wstring& additional_args) -{ - wstring command = allow_copy ? L"-move" : L"-rename"; - if (replace) - command += L"over"; - run_ops(should_succeed, command, src_rel_path, additional_args, wstring(), - dest_rel_path); -} - -void usvfs_test_base::ops_deleterename(const path& src_rel_path, - const path& dest_rel_path, bool allow_copy, - bool should_succeed, - const wstring& additional_args) -{ - wstring command = allow_copy ? L"-deletemove" : L"-deleterename"; - run_ops(should_succeed, command, src_rel_path, additional_args, wstring(), - dest_rel_path); -} - -void usvfs_test_base::run_ops(bool should_succeed, const wstring& preargs, - const path& rel_path, const wstring& additional_args, - const wstring& postargs, const path& rel_path2) -{ - using namespace usvfs::shared; - using string = std::string; - using wstring = wstring; - - string commandlog = test::path(m_o.opsexe).filename().string(); - wstring commandline = m_o.opsexe; - if (commandline.find(' ') != wstring::npos && - commandline.find('"') == wstring::npos) { - commandline = L"\"" + commandline + L"\""; - commandlog = "\"" + commandlog + "\""; - } - - if (!m_o.mount.empty()) { - commandline += L" -basedir "; - commandline += m_o.mount; - commandlog += " -basedir "; - commandlog += m_o.mount.filename().string(); - } - - if (!m_o.ops_options.empty()) { - commandline += L" "; - commandline += m_o.ops_options; - commandlog += " "; - commandlog += string_cast<string>(m_o.ops_options, CodePage::UTF8); - } - - commandline += L" -cout+ "; - commandline += m_o.output; - commandlog += " -cout+ "; - commandlog += m_o.output.filename().string(); - - if (!additional_args.empty()) { - commandline += L" "; - commandline += additional_args; - commandlog += " "; - commandlog += string_cast<string>(additional_args, CodePage::UTF8); - } - - if (!preargs.empty()) { - commandline += L" "; - commandline += preargs; - commandlog += " "; - commandlog += string_cast<string>(preargs, CodePage::UTF8); - } - - if (!rel_path.empty()) { - commandline += L" "; - commandline += m_o.mount / rel_path; - commandlog += " "; - commandlog += MOUNT_LABEL + rel_path.string(); - } - - if (!rel_path2.empty()) { - commandline += L" "; - commandline += m_o.mount / rel_path2; - commandlog += " "; - commandlog += MOUNT_LABEL + rel_path2.string(); - } - - if (!postargs.empty()) { - commandline += L" "; - commandline += postargs; - commandlog += " "; - commandlog += string_cast<string>(postargs, CodePage::UTF8); - } - - fprintf(output(), "Spawning: %s\n", commandlog.c_str()); - auto res = usvfs_connector::spawn(&commandline[0]); - fprintf(output(), "\n"); - - bool success = res == 0; - if (success != should_succeed) - throw test::FuncFailed("run_ops", success ? "succeeded" : "failed", - commandlog.c_str(), res); -} - -std::string usvfs_test_base::mount_contents(const path& rel_path) -{ - verify_mount_existance(rel_path); - const auto& contents = test::read_small_file(m_o.mount / rel_path); - return std::string(contents.data(), contents.size()); -} - -std::string usvfs_test_base::source_contents(const path& rel_path) -{ - verify_source_existance(rel_path); - const auto& contents = test::read_small_file(m_o.source / rel_path); - return std::string(contents.data(), contents.size()); -} - -void usvfs_test_base::verify_mount_contents(const path& rel_path, const char* contents) -{ - verify_mount_existance(rel_path); - if (verify_contents(m_o.mount / rel_path, contents)) - throw test::FuncFailed("verify_mount_contents", - (MOUNT_LABEL + rel_path.string()).c_str(), contents); -} - -void usvfs_test_base::verify_source_contents(const path& rel_path, const char* contents) -{ - verify_source_existance(rel_path); - if (verify_contents(m_o.source / rel_path, contents)) - throw test::FuncFailed("verify_source_contents", - (SOURCE_LABEL + rel_path.string()).c_str(), contents); -} - -bool usvfs_test_base::verify_contents(const path& file, const char* contents) -{ - // we allow difference in trailing whitespace (i.e. extra new line): - - size_t sz = strlen(contents); - while (sz && isspace(contents[sz - 1])) - --sz; - - const auto& real_contents = test::read_small_file(file); - size_t real_sz = real_contents.size(); - while (real_sz && isspace(real_contents[real_sz - 1])) - --real_sz; - - return sz == real_sz && memcmp(contents, real_contents.data(), sz); -} - -void usvfs_test_base::verify_mount_existance(const path& rel_path, bool exists, - bool is_dir) -{ - bool real_is_dir = false; - bool real_exists = - winapi::ex::wide::fileExists((m_o.mount / rel_path).c_str(), &real_is_dir); - if (exists != real_exists) - throw test::FuncFailed("verify_mount_existance", - real_exists ? "path exists" : "path does not exist", - (MOUNT_LABEL + rel_path.string()).c_str()); - else if (real_exists && is_dir != real_is_dir) - throw test::FuncFailed("verify_mount_existance", - real_is_dir ? "path is a directory" : "path is a file", - (MOUNT_LABEL + rel_path.string()).c_str()); -} - -void usvfs_test_base::verify_source_existance(const path& rel_path, bool exists, - bool is_dir) -{ - bool real_is_dir = false; - bool real_exists = - winapi::ex::wide::fileExists((m_o.source / rel_path).c_str(), &real_is_dir); - if (exists != real_exists) - throw test::FuncFailed("verify_source_existance", - real_exists ? "path exists" : "path does not exist", - (SOURCE_LABEL + rel_path.string()).c_str()); - else if (real_exists && is_dir != real_is_dir) - throw test::FuncFailed("verify_source_existance", - real_is_dir ? "path is a directory" : "path is a file", - (SOURCE_LABEL + rel_path.string()).c_str()); -} diff --git a/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test_base.h b/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test_base.h deleted file mode 100644 index 4986e3b..0000000 --- a/libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test_base.h +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once - -#include <string> - -#include <test_helpers.h> - -class usvfs_test_options -{ -public: - static constexpr auto DEFAULT_MAPPING = L"vfs_mappings.txt"; - static constexpr auto MOUNT_DIR = L"mount"; - static constexpr auto SOURCE_DIR = L"source"; - - using path = test::path; - - // fills any values not set (or set to an empty value) to their default value - void fill_defaults(const path& test_name, const std::wstring& scenario, - const wchar_t* label); - - void set_ops32(); // sets opsexe iff opsexe is empty - void set_ops64(); // sets opsexe iff opsexe is empty - void add_ops_options(const std::wstring& options); - - path opsexe; - path fixture; - path mapping; - path temp; - path mount; - path source; - path output; - path usvfs_log; - std::wstring ops_options; - bool temp_cleanup = false; - bool force_temp_cleanup = false; -}; - -class usvfs_test_base -{ -public: - static constexpr auto MOUNT_DIR = usvfs_test_options::MOUNT_DIR; - static constexpr auto SOURCE_DIR = usvfs_test_options::SOURCE_DIR; - static constexpr auto MOUNT_LABEL = "mount:"; - static constexpr auto SOURCE_LABEL = "source:"; - static constexpr auto OUTPUT_CLEAN_SUFFIX = L"_clean"; - static constexpr auto POSTMORTEM_SUFFIX = L".postmortem"; - - using wstring = std::wstring; - using path = test::path; - - // options object should outlive this object. - usvfs_test_base(const usvfs_test_options& options) : m_o(options) {} - virtual ~usvfs_test_base() = default; - - int run(const std::wstring& exe_name); - - // function for override: - - virtual const char* scenario_name() = 0; - virtual bool scenario_run() = 0; - - // helpers for derived scenarios: - - virtual void ops_list(const path& rel_path, bool recursive, bool with_contents, - bool should_succeed = true, - const wstring& additional_args = wstring()); - virtual void ops_read(const path& rel_path, bool should_succeed = true, - const wstring& additional_args = wstring()); - virtual void ops_rewrite(const path& rel_path, const char* contents, - bool should_succeed = true, - const wstring& additional_args = wstring()); - virtual void ops_overwrite(const path& rel_path, const char* contents, bool recursive, - bool should_succeed = true, - const wstring& additional_args = wstring()); - virtual void ops_touch(const path& rel_path, bool full_write_access = false, - bool should_succeed = true, - const wstring& additional_args = wstring()); - virtual void ops_deleteoverwrite(const path& rel_path, const char* contents, - bool recursive, bool should_succeed = true, - const wstring& additional_args = wstring()); - virtual void ops_delete(const path& rel_path, bool should_succeed = true, - const wstring& additional_args = wstring()); - virtual void ops_copy(const path& src_rel_path, const path& dest_rel_path, - bool replace, bool should_succeed = true, - const wstring& additional_args = wstring()); - virtual void ops_rename(const path& src_rel_path, const path& dest_rel_path, - bool replace, bool allow_copy = false, - bool should_succeed = true, - const wstring& additional_args = wstring()); - virtual void ops_deleterename(const path& src_rel_path, const path& dest_rel_path, - bool allow_copy = false, bool should_succeed = true, - const wstring& additional_args = wstring()); - - virtual std::string mount_contents(const path& rel_path); - virtual void verify_mount_contents(const path& rel_path, const char* contents); - virtual void verify_mount_existance(const path& rel_path, bool exists = true, - bool is_dir = false); - virtual std::string source_contents(const path& rel_path); - virtual void verify_source_contents(const path& rel_path, const char* contents); - virtual void verify_source_existance(const path& rel_path, bool exists = true, - bool is_dir = false); - -private: - int run_impl(const std::wstring& exe_name); - void log_settings(const std::wstring& exe_name); - void cleanup_temp(); - void copy_fixture(); - bool postmortem_check(); - bool recursive_compare_dirs(path rel_path, path gold_base, path result_base, - FILE* log); - void clean_output(); - - test::ScopedFILE output(); - void run_ops(bool should_succeed, const wstring& preargs, const path& rel_path, - const wstring& additional_args, const wstring& postargs = wstring(), - const path& rel_path2 = path()); - bool verify_contents(const path& file, const char* contents); - - const usvfs_test_options& m_o; - bool m_clean_output = true; -}; |
