aboutsummaryrefslogtreecommitdiff
path: root/libs/usvfs/test/usvfs_test_runner/usvfs_test
diff options
context:
space:
mode:
Diffstat (limited to 'libs/usvfs/test/usvfs_test_runner/usvfs_test')
-rw-r--r--libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_basic_test.cpp402
-rw-r--r--libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_basic_test.h14
-rw-r--r--libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test.cpp242
-rw-r--r--libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test_base.cpp1002
-rw-r--r--libs/usvfs/test/usvfs_test_runner/usvfs_test/usvfs_test_base.h120
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;
-};