From 6c65b90a95bde4e5cee673f86efc135b92fce624 Mon Sep 17 00:00:00 2001
From: Andrei Karas <akaras@inbox.ru>
Date: Tue, 29 Aug 2017 17:25:20 +0300
Subject: Remove _unittest from unit tests file names.

---
 src/unittests/fs/virtfs/virtfs.cc           | 1054 +++++++++++++++++
 src/unittests/fs/virtfs/virtfs2.cc          | 1700 +++++++++++++++++++++++++++
 src/unittests/fs/virtfs/virtfs2_unittest.cc | 1700 ---------------------------
 src/unittests/fs/virtfs/virtfs_unittest.cc  | 1054 -----------------
 src/unittests/fs/virtfs/zip.cc              |  304 +++++
 src/unittests/fs/virtfs/zip_unittest.cc     |  304 -----
 6 files changed, 3058 insertions(+), 3058 deletions(-)
 create mode 100644 src/unittests/fs/virtfs/virtfs.cc
 create mode 100644 src/unittests/fs/virtfs/virtfs2.cc
 delete mode 100644 src/unittests/fs/virtfs/virtfs2_unittest.cc
 delete mode 100644 src/unittests/fs/virtfs/virtfs_unittest.cc
 create mode 100644 src/unittests/fs/virtfs/zip.cc
 delete mode 100644 src/unittests/fs/virtfs/zip_unittest.cc

(limited to 'src/unittests/fs/virtfs')

diff --git a/src/unittests/fs/virtfs/virtfs.cc b/src/unittests/fs/virtfs/virtfs.cc
new file mode 100644
index 000000000..c31f0965e
--- /dev/null
+++ b/src/unittests/fs/virtfs/virtfs.cc
@@ -0,0 +1,1054 @@
+/*
+ *  The ManaPlus Client
+ *  Copyright (C) 2016-2017  The ManaPlus Developers
+ *
+ *  This file is part of The ManaPlus Client.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "unittests/unittests.h"
+
+#include "fs/files.h"
+#include "fs/paths.h"
+
+#include "fs/virtfs/fs.h"
+#include "fs/virtfs/list.h"
+
+#include "utils/checkutils.h"
+#include "utils/delete2.h"
+#include "utils/foreach.h"
+
+#ifndef UNITTESTS_CATCH
+#include <algorithm>
+#endif  // UNITTESTS_CATCH
+
+#include "debug.h"
+
+TEST_CASE("VirtFs dirSeparator", "")
+{
+    REQUIRE(dirSeparator != nullptr);
+    REQUIRE(VirtFs::getDirSeparator() == std::string(dirSeparator));
+    VirtFs::updateDirSeparator();
+    REQUIRE(dirSeparator != nullptr);
+    REQUIRE(VirtFs::getDirSeparator() == std::string(dirSeparator));
+}
+
+TEST_CASE("VirtFs getBaseDir", "")
+{
+    REQUIRE(VirtFs::getBaseDir() != nullptr);
+}
+
+TEST_CASE("VirtFs getUserDir", "")
+{
+    REQUIRE(VirtFs::getUserDir() != nullptr);
+}
+
+TEST_CASE("VirtFs exists1", "")
+{
+    logger = new Logger();
+    VirtFs::mountDirSilent("data", Append_false);
+    VirtFs::mountDirSilent("../data", Append_false);
+
+    REQUIRE(VirtFs::exists("test") == true);
+    REQUIRE(VirtFs::exists("test/dir1") == true);
+    REQUIRE(VirtFs::exists("test/dir") == false);
+    REQUIRE(VirtFs::exists("test/units.xml") == true);
+    REQUIRE(VirtFs::exists("test/units123.xml") == false);
+    REQUIRE(VirtFs::exists("tesQ/units.xml") == false);
+    REQUIRE(VirtFs::exists("units.xml") == false);
+
+    VirtFs::mountDirSilent("data/test", Append_false);
+    VirtFs::mountDirSilent("../data/test", Append_false);
+
+    REQUIRE(VirtFs::exists("test") == true);
+    REQUIRE(VirtFs::exists("test/dir1") == true);
+    REQUIRE(VirtFs::exists("test/dir") == false);
+    REQUIRE(VirtFs::exists("test/units.xml") == true);
+    REQUIRE(VirtFs::exists("test/units123.xml") == false);
+    REQUIRE(VirtFs::exists("tesQ/units.xml") == false);
+    REQUIRE(VirtFs::exists("units.xml") == true);
+
+    VirtFs::unmountDirSilent("data/test");
+    VirtFs::unmountDirSilent("../data/test");
+
+    REQUIRE(VirtFs::exists("test") == true);
+    REQUIRE(VirtFs::exists("test/dir1") == true);
+    REQUIRE(VirtFs::exists("test/dir") == false);
+    REQUIRE(VirtFs::exists("test/units.xml") == true);
+    REQUIRE(VirtFs::exists("test/units123.xml") == false);
+    REQUIRE(VirtFs::exists("tesQ/units.xml") == false);
+    REQUIRE(VirtFs::exists("units.xml") == false);
+
+    VirtFs::unmountDirSilent("data");
+    VirtFs::unmountDirSilent("../data");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs exists2", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
+
+    REQUIRE(VirtFs::exists("test") == false);
+    REQUIRE(VirtFs::exists("test/units.xml") == false);
+    REQUIRE(VirtFs::exists("test.txt") == true);
+    REQUIRE(VirtFs::exists("dir/hide.png") == true);
+    REQUIRE(VirtFs::exists("dir/gpl") == true);
+    REQUIRE(VirtFs::exists("dir/gpl/zzz") == false);
+    REQUIRE(VirtFs::exists("units.xml") == true);
+    REQUIRE(VirtFs::exists("units.xml.") == false);
+    REQUIRE(VirtFs::exists("units.xml2") == false);
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs exists3", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test.zip", Append_false);
+    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
+
+    REQUIRE(VirtFs::exists("test") == false);
+    REQUIRE(VirtFs::exists("test/units.xml") == false);
+    REQUIRE(VirtFs::exists("dir/brimmedhat.png"));
+    REQUIRE(VirtFs::exists("dir//brimmedhat.png"));
+    REQUIRE(VirtFs::exists("dir//hide.png"));
+    REQUIRE(VirtFs::exists("dir/1"));
+    REQUIRE(VirtFs::exists("dir/gpl"));
+    REQUIRE(VirtFs::exists("dir/dye.png"));
+    REQUIRE(VirtFs::exists("dir/2") == false);
+    REQUIRE(VirtFs::exists("dir2/2") == false);
+    REQUIRE(VirtFs::exists("dir2/paths.xml"));
+
+    VirtFs::unmountZip(prefix + "data/test/test.zip");
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs exists4", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test.zip", Append_false);
+    VirtFs::mountDirSilent(prefix + "data/test", Append_false);
+
+    REQUIRE(VirtFs::exists("test") == false);
+    REQUIRE(VirtFs::exists("test/units.xml") == false);
+    REQUIRE(VirtFs::exists("dir/brimmedhat.png"));
+    REQUIRE(VirtFs::exists("dir//brimmedhat.png"));
+    REQUIRE(VirtFs::exists("dir//hide.png"));
+    REQUIRE(VirtFs::exists("dir/1") == false);
+    REQUIRE(VirtFs::exists("dir/gpl") == false);
+    REQUIRE(VirtFs::exists("dir/dye.png") == false);
+    REQUIRE(VirtFs::exists("dir/2") == false);
+    REQUIRE(VirtFs::exists("dir2/2") == false);
+    REQUIRE(VirtFs::exists("dir2/paths.xml") == false);
+    REQUIRE(VirtFs::exists("units.xml"));
+    REQUIRE(VirtFs::exists("dir1/file1.txt"));
+    REQUIRE(VirtFs::exists("dir2/file2.txt"));
+    REQUIRE(VirtFs::exists("dir2/file3.txt") == false);
+
+    VirtFs::unmountZip(prefix + "data/test/test.zip");
+    VirtFs::unmountDirSilent(prefix + "data/test");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs exists5", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    const std::string realDir = getRealPath(prefix + "data");
+    logger->log("real dir: " + realDir);
+    REQUIRE_FALSE(VirtFs::exists(realDir));
+
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs exists6", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip2(prefix + "data/test/test2.zip",
+        "dir",
+        Append_false);
+
+    REQUIRE(VirtFs::exists("test") == false);
+    REQUIRE(VirtFs::exists("test/units.xml") == false);
+    REQUIRE(VirtFs::exists("test.txt") == false);
+    REQUIRE(VirtFs::exists("dir/hide.png") == false);
+    REQUIRE(VirtFs::exists("dir/gpl") == false);
+    REQUIRE(VirtFs::exists("dir/gpl/zzz") == false);
+    REQUIRE(VirtFs::exists("units.xml") == false);
+    REQUIRE(VirtFs::exists("units.xml.") == false);
+    REQUIRE(VirtFs::exists("units.xml2") == false);
+    REQUIRE(VirtFs::exists("hide.png"));
+    REQUIRE(VirtFs::exists("dye.png"));
+    REQUIRE(VirtFs::exists("gpl"));
+    REQUIRE(VirtFs::exists("gpl/zzz") == false);
+
+    VirtFs::unmountZip2(prefix + "data/test/test2.zip",
+        "dir");
+    delete2(logger);
+}
+
+static void removeTemp(StringVect &restrict list)
+{
+    int cnt = 0;
+    std::sort(list.begin(), list.end());
+
+    FOR_EACH (StringVectIter, it, list)
+    {
+        if (*it != "serverlistplus.xml.part")
+        {
+            logger->log("file: %d %s",
+                cnt,
+                (*it).c_str());
+            cnt ++;
+        }
+    }
+
+    FOR_EACH (StringVectIter, it, list)
+    {
+        if (*it == "serverlistplus.xml.part")
+        {
+            list.erase(it);
+            return;
+        }
+    }
+}
+
+static bool inList(const VirtFs::List *const list,
+                   const std::string &name)
+{
+    FOR_EACH (StringVectCIter, it, list->names)
+    {
+        if (*it == name)
+            return true;
+    }
+    return false;
+}
+
+TEST_CASE("VirtFs enumerateFiles1", "")
+{
+    logger = new Logger;
+
+    VirtFs::mountDirSilent("data", Append_false);
+    VirtFs::mountDirSilent("../data", Append_false);
+
+    VirtFs::List *list = nullptr;
+
+    const int cnt1 = VirtFs::exists("test/test2.txt") ? 28 : 27;
+    const int cnt2 = 28;
+
+    VirtFs::permitLinks(false);
+    list = VirtFs::enumerateFiles("test");
+    removeTemp(list->names);
+    const size_t sz = list->names.size();
+    REQUIRE(sz == cnt1);
+    VirtFs::freeList(list);
+
+    VirtFs::permitLinks(true);
+    list = VirtFs::enumerateFiles("test");
+    removeTemp(list->names);
+    REQUIRE(list->names.size() == cnt2);
+    VirtFs::freeList(list);
+
+    VirtFs::permitLinks(false);
+    list = VirtFs::enumerateFiles("test");
+    removeTemp(list->names);
+    REQUIRE(list->names.size() == cnt1);
+    VirtFs::freeList(list);
+
+    list = VirtFs::enumerateFiles("test/units.xml");
+    removeTemp(list->names);
+    REQUIRE(list->names.empty());
+    VirtFs::freeList(list);
+
+    VirtFs::unmountDirSilent("data");
+    VirtFs::unmountDirSilent("../data");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs enumerateFiles2", "")
+{
+    logger = new Logger;
+
+    VirtFs::mountDirSilent("data/test/dir1",
+        Append_false);
+    VirtFs::mountDirSilent("../data/test/dir1",
+        Append_false);
+
+    VirtFs::List *list = nullptr;
+
+    list = VirtFs::enumerateFiles("/");
+    REQUIRE(list->names.size() == 5);
+    VirtFs::freeList(list);
+
+    VirtFs::unmountDirSilent("data/test/dir1");
+    VirtFs::unmountDirSilent("../data/test/dir1");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs enumerateFiles3", "")
+{
+    logger = new Logger;
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test.zip",
+        Append_false);
+
+    VirtFs::List *list = nullptr;
+
+    list = VirtFs::enumerateFiles("/");
+    REQUIRE(list->names.size() == 1);
+    REQUIRE(inList(list, "dir"));
+    VirtFs::freeList(list);
+
+    VirtFs::unmountZip(prefix + "data/test/test.zip");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs enumerateFiles4", "")
+{
+    logger = new Logger;
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test2.zip",
+        Append_false);
+
+    VirtFs::List *list = nullptr;
+
+    list = VirtFs::enumerateFiles("/");
+    REQUIRE(list->names.size() == 4);
+    REQUIRE(inList(list, "dir"));
+    REQUIRE(inList(list, "dir2"));
+    REQUIRE(inList(list, "test.txt"));
+    REQUIRE(inList(list, "units.xml"));
+    VirtFs::freeList(list);
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs enumerateFiles5", "")
+{
+    logger = new Logger;
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test2.zip",
+        Append_false);
+    VirtFs::mountDirSilent(prefix + "data/test", Append_false);
+
+    VirtFs::List *list = nullptr;
+
+    list = VirtFs::enumerateFiles("dir2");
+    REQUIRE(inList(list, "file1.txt"));
+    REQUIRE(inList(list, "file2.txt"));
+    REQUIRE(inList(list, "hide.png"));
+    REQUIRE(inList(list, "paths.xml"));
+    REQUIRE(inList(list, "test.txt"));
+    REQUIRE(inList(list, "units.xml"));
+    VirtFs::freeList(list);
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    VirtFs::unmountDirSilent(prefix + "data/test");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs isDirectory1", "")
+{
+    logger = new Logger();
+    VirtFs::mountDirSilent("data", Append_false);
+    VirtFs::mountDirSilent("../data", Append_false);
+
+    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test/units.xml/") == false);
+    REQUIRE(VirtFs::isDirectory("test//units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test/units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test//units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ//units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test") == true);
+    REQUIRE(VirtFs::isDirectory("test/") == true);
+    REQUIRE(VirtFs::isDirectory("test//") == true);
+    REQUIRE(VirtFs::isDirectory("test/dir1") == true);
+    REQUIRE(VirtFs::isDirectory("test//dir1") == true);
+    REQUIRE(VirtFs::isDirectory("test//dir1/") == true);
+    REQUIRE(VirtFs::isDirectory("test//dir1//") == true);
+    REQUIRE(VirtFs::isDirectory("test/dir1/") == true);
+    REQUIRE(VirtFs::isDirectory("test/dir1//") == true);
+    REQUIRE(VirtFs::isDirectory("testQ") == false);
+    REQUIRE(VirtFs::isDirectory("testQ/") == false);
+    REQUIRE(VirtFs::isDirectory("testQ//") == false);
+
+    VirtFs::mountDirSilent("data/test", Append_false);
+    VirtFs::mountDirSilent("../data/test", Append_false);
+
+    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test/units.xml/") == false);
+    REQUIRE(VirtFs::isDirectory("test//units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test/units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test") == true);
+    REQUIRE(VirtFs::isDirectory("testQ") == false);
+    REQUIRE(VirtFs::isDirectory("test/dir1") == true);
+
+    VirtFs::unmountDirSilent("data/test");
+    VirtFs::unmountDirSilent("../data/test");
+
+    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test/units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("units.xml/") == false);
+    REQUIRE(VirtFs::isDirectory("test") == true);
+    REQUIRE(VirtFs::isDirectory("test/") == true);
+    REQUIRE(VirtFs::isDirectory("testQ") == false);
+    REQUIRE(VirtFs::isDirectory("test/dir1") == true);
+
+    VirtFs::unmountDirSilent("data");
+    VirtFs::unmountDirSilent("../data");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs isDirectory2", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
+
+    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir") == true);
+    REQUIRE(VirtFs::isDirectory("dir/") == true);
+    REQUIRE(VirtFs::isDirectory("dir//") == true);
+    REQUIRE(VirtFs::isDirectory("dir2") == true);
+    REQUIRE(VirtFs::isDirectory("dir3") == false);
+    REQUIRE(VirtFs::isDirectory("test.txt") == false);
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs isDirectory3", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountDir(prefix + "data", Append_false);
+    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
+
+    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test"));
+    REQUIRE(VirtFs::isDirectory("test//dye.png") == false);
+    REQUIRE(VirtFs::isDirectory("dir"));
+    REQUIRE(VirtFs::isDirectory("dir/"));
+    REQUIRE(VirtFs::isDirectory("dir//"));
+    REQUIRE(VirtFs::isDirectory("dir2"));
+    REQUIRE(VirtFs::isDirectory("dir3") == false);
+    REQUIRE(VirtFs::isDirectory("test.txt") == false);
+    REQUIRE(VirtFs::isDirectory("dir/hide.png") == false);
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    VirtFs::unmountDir(prefix + "data");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs openRead1", "")
+{
+    logger = new Logger();
+    VirtFs::mountDirSilent("data", Append_false);
+    VirtFs::mountDirSilent("../data", Append_false);
+
+    VirtFs::File *file = nullptr;
+
+    file = VirtFs::openRead("test/units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("test/units123.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("units.xml");
+    REQUIRE(file == nullptr);
+//    file = VirtFs::openRead("test");
+//    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+
+    VirtFs::mountDirSilent("data/test", Append_false);
+    VirtFs::mountDirSilent("../data/test", Append_false);
+
+    file = VirtFs::openRead("test/units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("test/units123.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+//    file = VirtFs::openRead("test");
+//    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+
+    VirtFs::unmountDirSilent("data/test");
+    VirtFs::unmountDirSilent("../data/test");
+
+    file = VirtFs::openRead("test/units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("test/units123.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("units.xml");
+    REQUIRE(file == nullptr);
+//    file = VirtFs::openRead("test");
+//    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+
+    VirtFs::unmountDirSilent("data");
+    VirtFs::unmountDirSilent("../data");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs openRead2", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
+
+    VirtFs::File *file = nullptr;
+
+    file = VirtFs::openRead("test/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir/hide.png");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir//hide.png");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs openRead3", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
+    VirtFs::mountDir(prefix + "data/test", Append_false);
+
+    VirtFs::File *file = nullptr;
+
+    file = VirtFs::openRead("test/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir/hide.png");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir//hide.png");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir/dye.png");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir/dye.pn_");
+    REQUIRE(file == nullptr);
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    VirtFs::unmountDir(prefix + "data/test");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs getRealDir1", "")
+{
+    logger = new Logger();
+    const std::string sep = dirSeparator;
+    REQUIRE(VirtFs::getRealDir(".").empty());
+    REQUIRE(VirtFs::getRealDir("..").empty());
+    const bool dir1 = VirtFs::mountDirSilent("data", Append_false);
+    REQUIRE((dir1 || VirtFs::mountDirSilent("../data", Append_false))
+        == true);
+    if (dir1 == true)
+    {
+        REQUIRE(VirtFs::getRealDir("test") == "data");
+        REQUIRE(VirtFs::getRealDir("test/test.txt") ==
+            "data");
+    }
+    else
+    {
+        REQUIRE(VirtFs::getRealDir("test") == "../data");
+        REQUIRE(VirtFs::getRealDir("test/test.txt") ==
+            "../data");
+    }
+    REQUIRE(VirtFs::getRealDir("zzz").empty());
+
+    VirtFs::mountDirSilent("data/test", Append_false);
+    VirtFs::mountDirSilent("../data/test", Append_false);
+    if (dir1 == true)
+    {
+        REQUIRE(VirtFs::getRealDir("test") == "data");
+        REQUIRE(VirtFs::getRealDir("test/test.txt") ==
+            "data");
+        REQUIRE(VirtFs::getRealDir("test.txt") ==
+            "data" + sep + "test");
+    }
+    else
+    {
+        REQUIRE(VirtFs::getRealDir("test") == ".." + sep + "data");
+        REQUIRE(VirtFs::getRealDir("test/test.txt") ==
+            ".." + sep + "data");
+        REQUIRE(VirtFs::getRealDir("test.txt") ==
+            ".." + sep + "data" + sep + "test");
+    }
+    REQUIRE(VirtFs::getRealDir("zzz").empty());
+
+    if (dir1 == true)
+    {
+        VirtFs::mountZip("data/test/test.zip", Append_false);
+        REQUIRE(VirtFs::getRealDir("dir/brimmedhat.png") ==
+            "data" + sep + "test" + sep + "test.zip");
+        REQUIRE(VirtFs::getRealDir("hide.png") ==
+            "data" + sep + "test");
+    }
+    else
+    {
+        VirtFs::mountZip("../data/test/test.zip", Append_false);
+        REQUIRE(VirtFs::getRealDir("dir/brimmedhat.png") ==
+            ".." + sep + "data" + sep + "test" + sep + "test.zip");
+        REQUIRE(VirtFs::getRealDir("hide.png") ==
+            ".." + sep + "data" + sep + "test");
+    }
+
+    VirtFs::unmountDirSilent("data/test");
+    VirtFs::unmountDirSilent("../data/test");
+
+    if (dir1 == true)
+    {
+        REQUIRE(VirtFs::getRealDir("test") == "data");
+        REQUIRE(VirtFs::getRealDir("test/test.txt") ==
+            "data");
+        REQUIRE(VirtFs::getRealDir("dir/hide.png") ==
+            "data" + sep + "test" + sep + "test.zip");
+    }
+    else
+    {
+        REQUIRE(VirtFs::getRealDir("test") == ".." + sep + "data");
+        REQUIRE(VirtFs::getRealDir("test/test.txt") ==
+            ".." + sep + "data");
+        REQUIRE(VirtFs::getRealDir("dir/hide.png") ==
+            ".." + sep + "data" + sep + "test" + sep + "test.zip");
+    }
+    REQUIRE(VirtFs::exists("dir/hide.png"));
+    REQUIRE(VirtFs::getRealDir("zzz").empty());
+
+    VirtFs::unmountDirSilent("data");
+    VirtFs::unmountDirSilent("../data");
+    if (dir1 == true)
+        VirtFs::unmountZip("data/test/test.zip");
+    else
+        VirtFs::unmountZip("../data/test/test.zip");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs getrealDir2", "")
+{
+    logger = new Logger();
+    const std::string sep = dirSeparator;
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
+    VirtFs::mountDir(prefix + "data/test", Append_false);
+    VirtFs::mountDir(prefix + "data", Append_false);
+
+    REQUIRE(VirtFs::getRealDir("zzz").empty());
+
+    REQUIRE(VirtFs::getRealDir("dir1/file1.txt") ==
+        prefix + "data" + sep + "test");
+    REQUIRE(VirtFs::getRealDir("hide.png") ==
+        prefix + "data" + sep + "test");
+    REQUIRE(VirtFs::getRealDir("dir//hide.png") ==
+        prefix + "data" + sep + "test" + sep + "test2.zip");
+    REQUIRE(VirtFs::getRealDir("dir/1//test.txt") ==
+        prefix + "data" + sep + "test" + sep + "test2.zip");
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    VirtFs::unmountDir(prefix + "data/test");
+    VirtFs::unmountDir(prefix + "data");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs getrealDir3", "")
+{
+    logger = new Logger();
+    const std::string sep = dirSeparator;
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip2(prefix + "data/test/test2.zip",
+        "dir",
+        Append_false);
+    VirtFs::mountDir(prefix + "data/test", Append_false);
+
+    REQUIRE(VirtFs::getRealDir("zzz").empty());
+
+    REQUIRE(VirtFs::getRealDir("dir1/file1.txt") ==
+        prefix + "data" + sep + "test");
+    REQUIRE(VirtFs::getRealDir("hide.png") ==
+        prefix + "data" + sep + "test");
+    REQUIRE(VirtFs::getRealDir("hide.png") ==
+        prefix + "data" + sep + "test");
+    REQUIRE(VirtFs::getRealDir("1//test.txt") ==
+        prefix + "data" + sep + "test" + sep + "test2.zip");
+
+    VirtFs::unmountZip2(prefix + "data/test/test2.zip",
+        "dir");
+    VirtFs::unmountDir(prefix + "data/test");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs permitLinks1", "")
+{
+    logger = new Logger();
+    VirtFs::mountDirSilent("data", Append_false);
+    VirtFs::mountDirSilent("../data", Append_false);
+
+    const int cnt1 = VirtFs::exists("test/test2.txt") ? 26 : 25;
+    const int cnt2 = 26;
+
+    StringVect list;
+    VirtFs::permitLinks(false);
+    VirtFs::getFiles("test", list);
+    removeTemp(list);
+    const size_t sz = list.size();
+    REQUIRE(sz == cnt1);
+
+    list.clear();
+    VirtFs::permitLinks(true);
+    VirtFs::getFiles("test", list);
+    removeTemp(list);
+    REQUIRE(list.size() == cnt2);
+
+    list.clear();
+    VirtFs::permitLinks(false);
+    VirtFs::getFiles("test", list);
+    removeTemp(list);
+    REQUIRE(list.size() == cnt1);
+
+    VirtFs::unmountDirSilent("data");
+    VirtFs::unmountDirSilent("../data");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs permitLinks2", "")
+{
+    logger = new Logger();
+    VirtFs::mountDirSilent2("data",
+        "test",
+        Append_false);
+    VirtFs::mountDirSilent2("../data",
+        "test",
+        Append_false);
+
+    const int cnt1 = VirtFs::exists("test2.txt") ? 26 : 25;
+    const int cnt2 = 26;
+
+    StringVect list;
+    VirtFs::permitLinks(false);
+    VirtFs::getFiles(dirSeparator, list);
+    removeTemp(list);
+    const size_t sz = list.size();
+    REQUIRE(sz == cnt1);
+
+    list.clear();
+    VirtFs::permitLinks(true);
+    VirtFs::getFiles(dirSeparator, list);
+    removeTemp(list);
+    REQUIRE(list.size() == cnt2);
+
+    list.clear();
+    VirtFs::permitLinks(false);
+    VirtFs::getFiles(dirSeparator, list);
+    removeTemp(list);
+    REQUIRE(list.size() == cnt1);
+
+    VirtFs::unmountDirSilent2("data",
+        "test");
+    VirtFs::unmountDirSilent2("../data",
+        "test");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs read1", "")
+{
+    logger = new Logger();
+    VirtFs::mountDirSilent("data", Append_false);
+    VirtFs::mountDirSilent("../data", Append_false);
+
+    VirtFs::File *file = VirtFs::openRead("test/test.txt");
+    REQUIRE(file != nullptr);
+    REQUIRE(VirtFs::fileLength(file) == 23);
+    const int fileSize = VirtFs::fileLength(file);
+
+    void *restrict buffer = calloc(fileSize + 1, 1);
+    REQUIRE(VirtFs::read(file, buffer, 1, fileSize) == fileSize);
+    REQUIRE(strcmp(static_cast<char*>(buffer),
+        "test line 1\ntest line 2") == 0);
+    REQUIRE(VirtFs::tell(file) == fileSize);
+    REQUIRE(VirtFs::eof(file) == true);
+
+    free(buffer);
+    buffer = calloc(fileSize + 1, 1);
+    REQUIRE(VirtFs::seek(file, 12) != 0);
+    REQUIRE(VirtFs::eof(file) == false);
+    REQUIRE(VirtFs::tell(file) == 12);
+    REQUIRE(VirtFs::read(file, buffer, 1, 11) == 11);
+    REQUIRE(strcmp(static_cast<char*>(buffer),
+        "test line 2") == 0);
+    REQUIRE(VirtFs::eof(file) == true);
+
+    VirtFs::close(file);
+    free(buffer);
+
+    VirtFs::unmountDirSilent("data");
+    VirtFs::unmountDirSilent("../data");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs read2", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
+
+    VirtFs::File *file = VirtFs::openRead("dir2/test.txt");
+    REQUIRE(file != nullptr);
+    REQUIRE(VirtFs::fileLength(file) == 23);
+    const int fileSize = VirtFs::fileLength(file);
+
+    void *restrict buffer = calloc(fileSize + 1, 1);
+    REQUIRE(VirtFs::read(file, buffer, 1, fileSize) == fileSize);
+    REQUIRE(strcmp(static_cast<char*>(buffer),
+        "test line 1\ntest line 2") == 0);
+    REQUIRE(VirtFs::tell(file) == fileSize);
+    REQUIRE(VirtFs::eof(file) == true);
+
+    free(buffer);
+    buffer = calloc(fileSize + 1, 1);
+    REQUIRE(VirtFs::seek(file, 12) != 0);
+    REQUIRE(VirtFs::eof(file) == false);
+    REQUIRE(VirtFs::tell(file) == 12);
+    REQUIRE(VirtFs::read(file, buffer, 1, 11) == 11);
+    REQUIRE(strcmp(static_cast<char*>(buffer),
+        "test line 2") == 0);
+    REQUIRE(VirtFs::eof(file) == true);
+
+    VirtFs::close(file);
+    free(buffer);
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs read3", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
+    VirtFs::mountDir(prefix + "data", Append_false);
+
+    VirtFs::File *file = VirtFs::openRead("dir2/test.txt");
+    REQUIRE(file != nullptr);
+    REQUIRE(VirtFs::fileLength(file) == 23);
+    const int fileSize = VirtFs::fileLength(file);
+
+    void *restrict buffer = calloc(fileSize + 1, 1);
+    REQUIRE(VirtFs::read(file, buffer, 1, fileSize) == fileSize);
+    REQUIRE(strcmp(static_cast<char*>(buffer),
+        "test line 1\ntest line 2") == 0);
+    REQUIRE(VirtFs::tell(file) == fileSize);
+    REQUIRE(VirtFs::eof(file) == true);
+
+    free(buffer);
+    buffer = calloc(fileSize + 1, 1);
+    REQUIRE(VirtFs::seek(file, 12) != 0);
+    REQUIRE(VirtFs::eof(file) == false);
+    REQUIRE(VirtFs::tell(file) == 12);
+    REQUIRE(VirtFs::read(file, buffer, 1, 11) == 11);
+    REQUIRE(strcmp(static_cast<char*>(buffer),
+        "test line 2") == 0);
+    REQUIRE(VirtFs::eof(file) == true);
+
+    VirtFs::close(file);
+    free(buffer);
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    VirtFs::unmountDir(prefix + "data");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs read4", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountDir(prefix + "data/test", Append_true);
+    VirtFs::mountZip(prefix + "data/test/test5.zip", Append_true);
+
+    VirtFs::File *file = VirtFs::openRead("dir1/file1.txt");
+    REQUIRE(file != nullptr);
+    REQUIRE(VirtFs::fileLength(file) == 23);
+    const int fileSize = VirtFs::fileLength(file);
+
+    void *restrict buffer = calloc(fileSize + 1, 1);
+    REQUIRE(VirtFs::read(file, buffer, 1, fileSize) == fileSize);
+    REQUIRE(strcmp(static_cast<char*>(buffer),
+        "test line 1\ntest line 2") == 0);
+    REQUIRE(VirtFs::tell(file) == fileSize);
+    REQUIRE(VirtFs::eof(file) == true);
+
+    free(buffer);
+    buffer = calloc(fileSize + 1, 1);
+    REQUIRE(VirtFs::seek(file, 12) != 0);
+    REQUIRE(VirtFs::eof(file) == false);
+    REQUIRE(VirtFs::tell(file) == 12);
+    REQUIRE(VirtFs::read(file, buffer, 1, 11) == 11);
+    REQUIRE(strcmp(static_cast<char*>(buffer),
+        "test line 2") == 0);
+    REQUIRE(VirtFs::eof(file) == true);
+
+    VirtFs::close(file);
+    free(buffer);
+
+    VirtFs::unmountZip(prefix + "data/test/test5.zip");
+    VirtFs::unmountDir(prefix + "data/test");
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs read5", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test5.zip", Append_true);
+    VirtFs::mountDir(prefix + "data/test", Append_true);
+
+    VirtFs::File *file = VirtFs::openRead("dir1/file1.txt");
+    REQUIRE(file != nullptr);
+    REQUIRE(VirtFs::fileLength(file) == 23);
+    const int fileSize = VirtFs::fileLength(file);
+
+    void *restrict buffer = calloc(fileSize + 1, 1);
+    REQUIRE(VirtFs::read(file, buffer, 1, fileSize) == fileSize);
+    REQUIRE(strcmp(static_cast<char*>(buffer),
+        "test line 3\ntest line 4") == 0);
+    REQUIRE(VirtFs::tell(file) == fileSize);
+    REQUIRE(VirtFs::eof(file) == true);
+
+    free(buffer);
+    buffer = calloc(fileSize + 1, 1);
+    REQUIRE(VirtFs::seek(file, 12) != 0);
+    REQUIRE(VirtFs::eof(file) == false);
+    REQUIRE(VirtFs::tell(file) == 12);
+    REQUIRE(VirtFs::read(file, buffer, 1, 11) == 11);
+    REQUIRE(strcmp(static_cast<char*>(buffer),
+        "test line 4") == 0);
+    REQUIRE(VirtFs::eof(file) == true);
+
+    VirtFs::close(file);
+    free(buffer);
+
+    VirtFs::unmountZip(prefix + "data/test/test5.zip");
+    VirtFs::unmountDir(prefix + "data/test");
+    delete2(logger);
+}
diff --git a/src/unittests/fs/virtfs/virtfs2.cc b/src/unittests/fs/virtfs/virtfs2.cc
new file mode 100644
index 000000000..8e578cc71
--- /dev/null
+++ b/src/unittests/fs/virtfs/virtfs2.cc
@@ -0,0 +1,1700 @@
+/*
+ *  The ManaPlus Client
+ *  Copyright (C) 2016-2017  The ManaPlus Developers
+ *
+ *  This file is part of The ManaPlus Client.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "unittests/unittests.h"
+
+#include "fs/files.h"
+
+#include "fs/virtfs/fs.h"
+#include "fs/virtfs/rwops.h"
+
+#include "utils/checkutils.h"
+#include "utils/delete2.h"
+#include "utils/foreach.h"
+#include "utils/stringutils.h"
+
+PRAGMA48(GCC diagnostic push)
+PRAGMA48(GCC diagnostic ignored "-Wshadow")
+#include <SDL_rwops.h>
+PRAGMA48(GCC diagnostic pop)
+
+#ifndef UNITTESTS_CATCH
+#include <algorithm>
+#endif  // UNITTESTS_CATCH
+
+#include "debug.h"
+
+static bool inList(StringVect list,
+                   const std::string &name)
+{
+    FOR_EACH (StringVectCIter, it, list)
+    {
+        if (*it == name)
+            return true;
+    }
+    return false;
+}
+
+static bool inList(StringVect list,
+                   const std::string &dir,
+                   const std::string &name)
+{
+    const std::string path = pathJoin(dir, name);
+    FOR_EACH (StringVectCIter, it, list)
+    {
+        if (*it == path)
+            return true;
+    }
+    return false;
+}
+
+static void removeTemp(StringVect &restrict list)
+{
+    int cnt = 0;
+    std::sort(list.begin(), list.end());
+
+    FOR_EACH (StringVectIter, it, list)
+    {
+        if (*it != "serverlistplus.xml.part")
+        {
+            logger->log("file: %d %s",
+                cnt,
+                (*it).c_str());
+            cnt ++;
+        }
+    }
+
+    FOR_EACH (StringVectIter, it, list)
+    {
+        if (*it == "serverlistplus.xml.part")
+        {
+            list.erase(it);
+            return;
+        }
+    }
+}
+
+TEST_CASE("VirtFs2 isDirectory1", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountDir(prefix + "data",
+        Append_false);
+
+    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test/units.xml/") == false);
+    REQUIRE(VirtFs::isDirectory("test//units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test/units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test//units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ//units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test") == true);
+    REQUIRE(VirtFs::isDirectory("test/") == true);
+    REQUIRE(VirtFs::isDirectory("test//") == true);
+    REQUIRE(VirtFs::isDirectory("test/dir1") == true);
+    REQUIRE(VirtFs::isDirectory("test//dir1") == true);
+    REQUIRE(VirtFs::isDirectory("test//dir1/") == true);
+    REQUIRE(VirtFs::isDirectory("test//dir1//") == true);
+    REQUIRE(VirtFs::isDirectory("test\\dir1/") == true);
+    REQUIRE(VirtFs::isDirectory("test/dir1//") == true);
+    REQUIRE(VirtFs::isDirectory("testQ") == false);
+    REQUIRE(VirtFs::isDirectory("testQ/") == false);
+    REQUIRE(VirtFs::isDirectory("testQ//") == false);
+
+    VirtFs::mountDir(prefix + "data/test",
+        Append_false);
+
+    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test/units.xml/") == false);
+    REQUIRE(VirtFs::isDirectory("test//units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test/units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test") == true);
+    REQUIRE(VirtFs::isDirectory("testQ") == false);
+    REQUIRE(VirtFs::isDirectory("test/dir1") == true);
+    REQUIRE(VirtFs::isDirectory("test\\dir1") == true);
+
+    VirtFs::unmountDir(prefix + "data/test");
+
+    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test/units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("units.xml/") == false);
+    REQUIRE(VirtFs::isDirectory("test") == true);
+    REQUIRE(VirtFs::isDirectory("test/") == true);
+    REQUIRE(VirtFs::isDirectory("testQ") == false);
+    REQUIRE(VirtFs::isDirectory("test/dir1") == true);
+
+    VirtFs::unmountDirSilent(prefix + "data");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 isDirectory2", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test2.zip",
+        Append_false);
+
+    REQUIRE(VirtFs::isDirectory("dir2/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir2/units.xml/") == false);
+    REQUIRE(VirtFs::isDirectory("dir2//units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir2/units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir2//units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ//units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir") == true);
+    REQUIRE(VirtFs::isDirectory("dir2/") == true);
+    REQUIRE(VirtFs::isDirectory("dir2//") == true);
+    REQUIRE(VirtFs::isDirectory("dir/1") == true);
+    REQUIRE(VirtFs::isDirectory("dir//1") == true);
+    REQUIRE(VirtFs::isDirectory("dir\\1/") == true);
+    REQUIRE(VirtFs::isDirectory("dir/1") == true);
+    REQUIRE(VirtFs::isDirectory("dir/1/zzz") == false);
+    REQUIRE(VirtFs::isDirectory("test/dir1\\") == false);
+    REQUIRE(VirtFs::isDirectory("testQ") == false);
+    REQUIRE(VirtFs::isDirectory("testQ/") == false);
+    REQUIRE(VirtFs::isDirectory("testQ//") == false);
+
+    VirtFs::mountZip(prefix + "data/test/test.zip",
+        Append_false);
+
+    REQUIRE(VirtFs::isDirectory("dir2/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir2/units.xml/") == false);
+    REQUIRE(VirtFs::isDirectory("dir2\\units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir2/units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir2//units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ//units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir") == true);
+    REQUIRE(VirtFs::isDirectory("dir2/") == true);
+    REQUIRE(VirtFs::isDirectory("dir2\\") == true);
+    REQUIRE(VirtFs::isDirectory("dir/1") == true);
+    REQUIRE(VirtFs::isDirectory("dir//1") == true);
+    REQUIRE(VirtFs::isDirectory("dir//1/") == true);
+    REQUIRE(VirtFs::isDirectory("dir/1") == true);
+    REQUIRE(VirtFs::isDirectory("dir/1/zzz") == false);
+    REQUIRE(VirtFs::isDirectory("test/dir1//") == false);
+    REQUIRE(VirtFs::isDirectory("testQ") == false);
+    REQUIRE(VirtFs::isDirectory("testQ/") == false);
+    REQUIRE(VirtFs::isDirectory("testQ//") == false);
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+
+    REQUIRE(VirtFs::isDirectory("dir2/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir2/units.xml/") == false);
+    REQUIRE(VirtFs::isDirectory("dir2//units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir2/units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir2//units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ//units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir") == true);
+    REQUIRE(VirtFs::isDirectory("dir2/") == false);
+    REQUIRE(VirtFs::isDirectory("dir2//") == false);
+    REQUIRE(VirtFs::isDirectory("dir/1") == false);
+    REQUIRE(VirtFs::isDirectory("dir\\1") == false);
+    REQUIRE(VirtFs::isDirectory("dir//1/") == false);
+    REQUIRE(VirtFs::isDirectory("dir/1") == false);
+    REQUIRE(VirtFs::isDirectory("dir/1/zzz") == false);
+    REQUIRE(VirtFs::isDirectory("test/dir1//") == false);
+    REQUIRE(VirtFs::isDirectory("testQ") == false);
+    REQUIRE(VirtFs::isDirectory("testQ/") == false);
+    REQUIRE(VirtFs::isDirectory("testQ//") == false);
+
+    VirtFs::unmountZip(prefix + "data/test/test.zip");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 isDirectory3", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountDir2(prefix + "data",
+        "test",
+        Append_false);
+
+    REQUIRE(VirtFs::isDirectory("units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("units.xml/") == false);
+    REQUIRE(VirtFs::isDirectory("units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ//units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("test") == false);
+    REQUIRE(VirtFs::isDirectory("dir1") == true);
+    REQUIRE(VirtFs::isDirectory("dir2//") == true);
+    REQUIRE(VirtFs::isDirectory("test/dir1") == false);
+    REQUIRE(VirtFs::isDirectory("testQ") == false);
+    REQUIRE(VirtFs::isDirectory("testQ/") == false);
+    REQUIRE(VirtFs::isDirectory("testQ//") == false);
+
+    VirtFs::unmountDirSilent2(prefix + "data",
+        "test");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 isDirectory4", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip2(prefix + "data/test/test2.zip",
+        "dir",
+        Append_false);
+
+    REQUIRE(VirtFs::isDirectory("dir2/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir2/units.xml/") == false);
+    REQUIRE(VirtFs::isDirectory("dir2//units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir2/units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("dir2//units123.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("tesQ//units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("units.xml") == false);
+    REQUIRE(VirtFs::isDirectory("1") == true);
+    REQUIRE(VirtFs::isDirectory("gpl") == true);
+    REQUIRE(VirtFs::isDirectory("dir2/") == false);
+    REQUIRE(VirtFs::isDirectory("dir/1") == false);
+    REQUIRE(VirtFs::isDirectory("dir/1/zzz") == false);
+    REQUIRE(VirtFs::isDirectory("test/dir1\\") == false);
+    REQUIRE(VirtFs::isDirectory("testQ") == false);
+    REQUIRE(VirtFs::isDirectory("testQ/") == false);
+    REQUIRE(VirtFs::isDirectory("testQ//") == false);
+
+    VirtFs::unmountZip2(prefix + "data/test/test2.zip",
+        "dir");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 openRead1", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountDir(prefix + "data",
+        Append_false);
+
+    VirtFs::File *file = nullptr;
+
+    file = VirtFs::openRead("test/units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("test\\units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("test/units123.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+
+    VirtFs::mountDir(prefix + "data/test",
+        Append_false);
+
+    file = VirtFs::openRead("test/units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("test/units123.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+
+    VirtFs::unmountDir(prefix + "data/test");
+
+    file = VirtFs::openRead("test/units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("test/units123.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+
+    VirtFs::unmountDir(prefix + "data");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 openRead2", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix("data/test/");
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "test2.zip",
+        Append_false);
+
+    VirtFs::File *file = nullptr;
+
+    file = VirtFs::openRead("dir2/units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir2\\units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir2/units123.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("units.xml1");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("dir/brimmedhat.png");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("dir//brimmedhat.png");
+    REQUIRE(file == nullptr);
+
+    VirtFs::mountZip(prefix + "test.zip",
+        Append_false);
+
+    file = VirtFs::openRead("dir2/units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir2//units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir2/units123.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("units.xml1");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("dir/brimmedhat.png");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+
+    VirtFs::unmountZip(prefix + "test.zip");
+
+    file = VirtFs::openRead("dir2/units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir2\\/\\units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir2/units123.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("units.xml1");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("dir/brimmedhat.png");
+    REQUIRE(file == nullptr);
+
+    VirtFs::unmountZip(prefix + "test2.zip");
+
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 openRead3", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountDir2(prefix + "data",
+        "test",
+        Append_false);
+
+    VirtFs::File *file = nullptr;
+
+    file = VirtFs::openRead("units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("test/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("units123.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("file1.txt");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("file2.txt");
+    REQUIRE(file == nullptr);
+
+    VirtFs::mountDir2(prefix + "data/test",
+        "dir2",
+        Append_false);
+
+    file = VirtFs::openRead("units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("test/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("units123.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("file1.txt");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("file2.txt");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+
+    VirtFs::unmountDir2(prefix + "data/test",
+        "dir2");
+
+    file = VirtFs::openRead("units.xml");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("test/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("units123.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("file1.txt");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("file2.txt");
+    REQUIRE(file == nullptr);
+
+    VirtFs::unmountDir2(prefix + "data",
+        "test");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 openRead4", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix("data/test/");
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip2(prefix + "test2.zip",
+        "dir",
+        Append_false);
+
+    VirtFs::File *file = nullptr;
+
+    file = VirtFs::openRead("dye.png");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("1\\test.txt");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir/dye.png");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("dye.png1");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("brimmedhat.png");
+    REQUIRE(file == nullptr);
+
+    VirtFs::mountZip2(prefix + "test.zip",
+        "dir",
+        Append_false);
+
+    file = VirtFs::openRead("dye.png");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("1\\test.txt");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir/dye.png");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("dye.png1");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("brimmedhat.png");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+
+    VirtFs::unmountZip2(prefix + "test.zip",
+        "dir");
+
+    file = VirtFs::openRead("dye.png");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("1\\test.txt");
+    REQUIRE(file != nullptr);
+    VirtFs::close(file);
+    file = VirtFs::openRead("dir/dye.png");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("tesQ/units.xml");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("dye.png1");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("testQ");
+    REQUIRE(file == nullptr);
+    file = VirtFs::openRead("brimmedhat.png");
+    REQUIRE(file == nullptr);
+
+    VirtFs::unmountZip2(prefix + "test2.zip",
+        "dir");
+
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 permitLinks", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountDir(prefix + "data",
+        Append_false);
+
+    const int cnt1 = VirtFs::exists("test/test2.txt") ? 26 : 25;
+    const int cnt2 = 26;
+
+    StringVect list;
+    VirtFs::permitLinks(false);
+    VirtFs::getFiles("test", list);
+    removeTemp(list);
+    const size_t sz = list.size();
+    REQUIRE(sz == cnt1);
+
+    list.clear();
+    VirtFs::permitLinks(true);
+    VirtFs::getFiles("test", list);
+    removeTemp(list);
+    REQUIRE(list.size() == cnt2);
+
+    list.clear();
+    VirtFs::permitLinks(false);
+    VirtFs::getFiles("test", list);
+    removeTemp(list);
+    REQUIRE(list.size() == cnt1);
+
+    VirtFs::unmountDirSilent(prefix + "data");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 read1", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountDir(prefix + "data",
+        Append_false);
+
+    VirtFs::File *file = VirtFs::openRead("test/test.txt");
+    REQUIRE(file != nullptr);
+    REQUIRE(VirtFs::fileLength(file) == 23);
+    const int fileSize = VirtFs::fileLength(file);
+
+    void *restrict buffer = calloc(fileSize + 1, 1);
+    REQUIRE(VirtFs::read(file, buffer, 1, fileSize) == fileSize);
+    REQUIRE(strcmp(static_cast<char*>(buffer),
+        "test line 1\ntest line 2") == 0);
+    REQUIRE(VirtFs::tell(file) == fileSize);
+    REQUIRE(VirtFs::eof(file) != 0);
+
+    free(buffer);
+    buffer = calloc(fileSize + 1, 1);
+    REQUIRE(VirtFs::seek(file, 12) != 0);
+    REQUIRE(VirtFs::eof(file) == 0);
+    REQUIRE(VirtFs::tell(file) == 12);
+    REQUIRE(VirtFs::read(file, buffer, 1, 11) == 11);
+    REQUIRE(strcmp(static_cast<char*>(buffer),
+        "test line 2") == 0);
+    REQUIRE(VirtFs::eof(file) != 0);
+
+    VirtFs::close(file);
+    free(buffer);
+
+    VirtFs::unmountDir(prefix + "data");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 read2", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix("data/test/");
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "test2.zip",
+        Append_false);
+    VirtFs::File *file = nullptr;
+    void *restrict buffer = nullptr;
+
+    SECTION("test 1")
+    {
+        file = VirtFs::openRead("dir2//test.txt");
+        REQUIRE(file != nullptr);
+        REQUIRE(VirtFs::fileLength(file) == 23);
+        const int fileSize = VirtFs::fileLength(file);
+
+        buffer = calloc(fileSize + 1, 1);
+        REQUIRE(VirtFs::read(file, buffer, 1, fileSize) == fileSize);
+        REQUIRE(strcmp(static_cast<char*>(buffer),
+            "test line 1\ntest line 2") == 0);
+        REQUIRE(VirtFs::tell(file) == fileSize);
+        REQUIRE(VirtFs::eof(file) != 0);
+    }
+
+    SECTION("test 2")
+    {
+        file = VirtFs::openRead("dir2\\/test.txt");
+        REQUIRE(file != nullptr);
+        REQUIRE(VirtFs::fileLength(file) == 23);
+        const int fileSize = VirtFs::fileLength(file);
+
+        buffer = calloc(fileSize + 1, 1);
+        REQUIRE(VirtFs::seek(file, 12) != 0);
+        REQUIRE(VirtFs::eof(file) == 0);
+        REQUIRE(VirtFs::tell(file) == 12);
+        REQUIRE(VirtFs::read(file, buffer, 1, 11) == 11);
+        REQUIRE(strcmp(static_cast<char*>(buffer),
+            "test line 2") == 0);
+        REQUIRE(VirtFs::eof(file) != 0);
+    }
+
+    SECTION("test 3")
+    {
+        file = VirtFs::openRead("dir2//test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = VirtFs::fileLength(file);
+
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize; f ++)
+        {
+            REQUIRE(VirtFs::seek(file, f) != 0);
+            REQUIRE(VirtFs::eof(file) == 0);
+            REQUIRE(VirtFs::tell(file) == f);
+        }
+    }
+
+    SECTION("test 4")
+    {
+        file = VirtFs::openRead("dir2/test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = VirtFs::fileLength(file);
+        const char *restrict const str = "test line 1\ntest line 2";
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize - 1; f ++)
+        {
+            REQUIRE(VirtFs::read(file, buffer, 1, 1) == 1);
+            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
+            REQUIRE(VirtFs::eof(file) == 0);
+            REQUIRE(VirtFs::tell(file) == f + 1);
+        }
+        REQUIRE(VirtFs::read(file, buffer, 1, 1) == 1);
+        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
+        REQUIRE(VirtFs::eof(file) != 0);
+        REQUIRE(VirtFs::tell(file) == fileSize);
+    }
+
+    SECTION("test 5")
+    {
+        file = VirtFs::openRead("dir2\\\\test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = VirtFs::fileLength(file);
+        const char *restrict const str = "test line 1\ntest line 2";
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize - 1; f += 2)
+        {
+            REQUIRE(VirtFs::read(file, buffer, 2, 1) == 1);
+            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
+            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
+            REQUIRE(VirtFs::eof(file) == 0);
+            REQUIRE(VirtFs::tell(file) == f + 2);
+        }
+        REQUIRE(VirtFs::eof(file) == 0);
+        REQUIRE(VirtFs::tell(file) == 22);
+        REQUIRE(VirtFs::read(file, buffer, 2, 1) == 0);
+        REQUIRE(VirtFs::eof(file) == 0);
+    }
+
+    SECTION("test 6")
+    {
+        file = VirtFs::openRead("dir2//test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = VirtFs::fileLength(file);
+        const char *restrict const str = "test line 1\ntest line 2";
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize - 1; f += 2)
+        {
+            REQUIRE(VirtFs::read(file, buffer, 1, 2) == 2);
+            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
+            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
+            REQUIRE(VirtFs::eof(file) == 0);
+            REQUIRE(VirtFs::tell(file) == f + 2);
+        }
+        REQUIRE(VirtFs::eof(file) == 0);
+        REQUIRE(VirtFs::tell(file) == 22);
+        REQUIRE(VirtFs::read(file, buffer, 1, 2) == 1);
+        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
+        REQUIRE(VirtFs::eof(file) != 0);
+    }
+
+    VirtFs::close(file);
+    free(buffer);
+    VirtFs::unmountZip(prefix + "test2.zip");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 loadFile1", "")
+{
+    VirtFs::init(".");
+    int fileSize = 0;
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountDir(prefix + "data",
+        Append_false);
+
+    const char *const buffer = VirtFs::loadFile("test/test.txt", fileSize);
+    REQUIRE(static_cast<const void*>(buffer) != nullptr);
+    REQUIRE(fileSize == 23);
+    REQUIRE(strncmp(buffer, "test line 1\ntest line 2", 23) == 0);
+    delete [] buffer;
+
+    VirtFs::unmountDir(prefix + "data");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 loadFile2", "")
+{
+    VirtFs::init(".");
+    int fileSize = 0;
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test2.zip",
+        Append_false);
+
+    SECTION("test 1")
+    {
+        const char *restrict buffer = VirtFs::loadFile("dir2//test.txt",
+            fileSize);
+        REQUIRE(static_cast<const void*>(buffer) != nullptr);
+        REQUIRE(fileSize == 23);
+        REQUIRE(strncmp(buffer, "test line 1\ntest line 2", 23) == 0);
+        delete [] buffer;
+    }
+
+    SECTION("test 2")
+    {
+        const char *restrict buffer = VirtFs::loadFile("dir2\\/test.txt",
+            fileSize);
+        REQUIRE(static_cast<const void*>(buffer) != nullptr);
+        REQUIRE(fileSize == 23);
+        REQUIRE(strncmp(buffer, "test line 1\ntest line 2", 23) == 0);
+        delete [] buffer;
+    }
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 loadFile3", "")
+{
+    VirtFs::init(".");
+    int fileSize = 0;
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountDir2(prefix + "data",
+        "test",
+        Append_false);
+
+    const char *const buffer = VirtFs::loadFile("test.txt", fileSize);
+    REQUIRE(static_cast<const void*>(buffer) != nullptr);
+    REQUIRE(fileSize == 23);
+    REQUIRE(strncmp(buffer, "test line 1\ntest line 2", 23) == 0);
+    delete [] buffer;
+
+    VirtFs::unmountDir2(prefix + "data",
+        "test");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 loadFile4", "")
+{
+    VirtFs::init(".");
+    int fileSize = 0;
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip2(prefix + "data/test/test2.zip",
+        "dir2",
+        Append_false);
+
+    SECTION("test 1")
+    {
+        const char *restrict buffer = VirtFs::loadFile("test.txt",
+            fileSize);
+        REQUIRE(static_cast<const void*>(buffer) != nullptr);
+        REQUIRE(fileSize == 23);
+        REQUIRE(strncmp(buffer, "test line 1\ntest line 2", 23) == 0);
+        delete [] buffer;
+    }
+
+    SECTION("test 2")
+    {
+        const char *restrict buffer = VirtFs::loadFile("test.txt",
+            fileSize);
+        REQUIRE(static_cast<const void*>(buffer) != nullptr);
+        REQUIRE(fileSize == 23);
+        REQUIRE(strncmp(buffer, "test line 1\ntest line 2", 23) == 0);
+        delete [] buffer;
+    }
+
+    VirtFs::unmountZip2(prefix + "data/test/test2.zip",
+        "dir2");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 rwops_read1", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountDir(prefix + "data",
+        Append_false);
+
+    SDL_RWops *file = VirtFs::rwopsOpenRead("test/test.txt");
+    REQUIRE(file != nullptr);
+#ifdef USE_SDL2
+    REQUIRE(file->size(file) == 23);
+#endif  // USE_SDL2
+
+    const int fileSize = 23;
+
+    void *restrict buffer = calloc(fileSize + 1, 1);
+    REQUIRE(file->read(file, buffer, 1, fileSize) == fileSize);
+    REQUIRE(strcmp(static_cast<char*>(buffer),
+        "test line 1\ntest line 2") == 0);
+    REQUIRE(file->seek(file, 0, SEEK_CUR) == fileSize);
+
+    free(buffer);
+    buffer = calloc(fileSize + 1, 1);
+    REQUIRE(file->seek(file, 12, SEEK_SET) != 0);
+    REQUIRE(file->seek(file, 0, SEEK_CUR) == 12);
+    REQUIRE(file->read(file, buffer, 1, 11) == 11);
+    REQUIRE(strcmp(static_cast<char*>(buffer),
+        "test line 2") == 0);
+
+    file->close(file);
+    free(buffer);
+
+    VirtFs::unmountDir(prefix + "data");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 rwops_read2", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix("data/test/");
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "test2.zip",
+        Append_false);
+    SDL_RWops *file = nullptr;
+    void *restrict buffer = nullptr;
+
+    SECTION("test 1")
+    {
+        file = VirtFs::rwopsOpenRead("dir2//test.txt");
+        REQUIRE(file != nullptr);
+#ifdef USE_SDL2
+        REQUIRE(file->size(file) == 23);
+#endif  // USE_SDL2
+        const int fileSize = 23;
+
+        buffer = calloc(fileSize + 1, 1);
+        REQUIRE(file->read(file, buffer, 1, fileSize) == fileSize);
+        REQUIRE(strcmp(static_cast<char*>(buffer),
+            "test line 1\ntest line 2") == 0);
+        REQUIRE(file->seek(file, 0, SEEK_CUR) == fileSize);
+    }
+
+    SECTION("test 2")
+    {
+        file = VirtFs::rwopsOpenRead("dir2\\/test.txt");
+        REQUIRE(file != nullptr);
+#ifdef USE_SDL2
+        REQUIRE(file->size(file) == 23);
+#endif  // USE_SDL2
+        const int fileSize = 23;
+
+        buffer = calloc(fileSize + 1, 1);
+        REQUIRE(file->seek(file, 12, SEEK_SET) != 0);
+        REQUIRE(file->seek(file, 0, SEEK_CUR) == 12);
+        REQUIRE(file->read(file, buffer, 1, 11) == 11);
+        REQUIRE(strcmp(static_cast<char*>(buffer),
+            "test line 2") == 0);
+    }
+
+    SECTION("test 3")
+    {
+        file = VirtFs::rwopsOpenRead("dir2//test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = 23;
+
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize; f ++)
+        {
+            REQUIRE(file->seek(file, f, SEEK_SET) == f);
+            REQUIRE(file->seek(file, 0, SEEK_CUR) == f);
+        }
+    }
+
+    SECTION("test 4")
+    {
+        file = VirtFs::rwopsOpenRead("dir2/test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = 23;
+        const char *restrict const str = "test line 1\ntest line 2";
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize - 1; f ++)
+        {
+            REQUIRE(file->read(file, buffer, 1, 1) == 1);
+            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
+            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 1);
+        }
+        REQUIRE(file->read(file, buffer, 1, 1) == 1);
+        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
+        REQUIRE(file->seek(file, 0, SEEK_CUR) == fileSize);
+    }
+
+    SECTION("test 5")
+    {
+        file = VirtFs::rwopsOpenRead("dir2\\\\test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = 23;
+        const char *restrict const str = "test line 1\ntest line 2";
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize - 1; f += 2)
+        {
+            REQUIRE(file->read(file, buffer, 2, 1) == 1);
+            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
+            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
+            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 2);
+        }
+        REQUIRE(file->seek(file, 0, SEEK_CUR) == 22);
+        REQUIRE(file->read(file, buffer, 2, 1) == 0);
+    }
+
+    SECTION("test 6")
+    {
+        file = VirtFs::rwopsOpenRead("dir2//test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = 23;
+        const char *restrict const str = "test line 1\ntest line 2";
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize - 1; f += 2)
+        {
+            REQUIRE(file->read(file, buffer, 1, 2) == 2);
+            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
+            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
+            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 2);
+        }
+        REQUIRE(file->seek(file, 0, SEEK_CUR) == 22);
+        REQUIRE(file->read(file, buffer, 1, 2) == 1);
+        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
+    }
+
+    SECTION("test 7")
+    {
+        file = VirtFs::rwopsOpenRead("dir2//test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = 23;
+        const char *restrict const str = "test line 1\ntest line 2";
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize - 1; f += 2)
+        {
+            REQUIRE(file->read(file, buffer, 1, 2) == 2);
+            REQUIRE(file->seek(file, -2, SEEK_CUR) == f);
+            REQUIRE(file->seek(file, 0, SEEK_CUR) == f);
+            REQUIRE(file->seek(file, 2, SEEK_CUR) == f + 2);
+            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
+            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
+            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 2);
+        }
+        REQUIRE(file->seek(file, 0, SEEK_CUR) == 22);
+        REQUIRE(file->read(file, buffer, 1, 2) == 1);
+        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
+    }
+
+    SECTION("test 8")
+    {
+        file = VirtFs::rwopsOpenRead("dir2//test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = 23;
+        const char *restrict const str = "test line 1\ntest line 2";
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize - 1; f += 2)
+        {
+            REQUIRE(file->seek(file, -f - 2, SEEK_END) == 23 - f - 2);
+            REQUIRE(file->read(file, buffer, 1, 2) == 2);
+            REQUIRE(static_cast<char*>(buffer)[0] == str[23 - f - 2]);
+            REQUIRE(static_cast<char*>(buffer)[1] == str[23 - f - 2 + 1]);
+            REQUIRE(file->seek(file, 0, SEEK_CUR) == 23 - f);
+        }
+        // 3
+        REQUIRE(file->seek(file, 1, SEEK_CUR) == 4);
+        // 4
+        REQUIRE(file->read(file, buffer, 1, 2) == 2);
+        // 6
+        REQUIRE(static_cast<char*>(buffer)[0] == str[4]);
+        REQUIRE(static_cast<char*>(buffer)[1] == str[5]);
+        REQUIRE(file->seek(file, -7, SEEK_CUR) == -1);
+        REQUIRE(file->seek(file, 6, SEEK_SET) == 6);
+        REQUIRE(file->seek(file, -6, SEEK_CUR) == 0);
+    }
+
+    if (file != nullptr)
+        file->close(file);
+    free(buffer);
+    VirtFs::unmountZip(prefix + "test2.zip");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 rwops_read3", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountDir(prefix + "data",
+        Append_false);
+    SDL_RWops *file = nullptr;
+    void *restrict buffer = nullptr;
+
+    SECTION("test 1")
+    {
+        file = VirtFs::rwopsOpenRead("test/test.txt");
+        REQUIRE(file != nullptr);
+#ifdef USE_SDL2
+        REQUIRE(file->size(file) == 23);
+#endif  // USE_SDL2
+        const int fileSize = 23;
+
+        buffer = calloc(fileSize + 1, 1);
+        REQUIRE(file->read(file, buffer, 1, fileSize) == fileSize);
+        REQUIRE(strcmp(static_cast<char*>(buffer),
+            "test line 1\ntest line 2") == 0);
+        REQUIRE(file->seek(file, 0, SEEK_CUR) == fileSize);
+    }
+
+    SECTION("test 2")
+    {
+        file = VirtFs::rwopsOpenRead("test\\test.txt");
+        REQUIRE(file != nullptr);
+#ifdef USE_SDL2
+        REQUIRE(file->size(file) == 23);
+#endif  // USE_SDL2
+        const int fileSize = 23;
+
+        buffer = calloc(fileSize + 1, 1);
+        REQUIRE(file->seek(file, 12, SEEK_SET) != 0);
+        REQUIRE(file->seek(file, 0, SEEK_CUR) == 12);
+        REQUIRE(file->read(file, buffer, 1, 11) == 11);
+        REQUIRE(strcmp(static_cast<char*>(buffer),
+            "test line 2") == 0);
+    }
+
+    SECTION("test 3")
+    {
+        file = VirtFs::rwopsOpenRead("test\\/test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = 23;
+
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize; f ++)
+        {
+            REQUIRE(file->seek(file, f, SEEK_SET) == f);
+            REQUIRE(file->seek(file, 0, SEEK_CUR) == f);
+        }
+    }
+
+    SECTION("test 4")
+    {
+        file = VirtFs::rwopsOpenRead("test/test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = 23;
+        const char *restrict const str = "test line 1\ntest line 2";
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize - 1; f ++)
+        {
+            REQUIRE(file->read(file, buffer, 1, 1) == 1);
+            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
+            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 1);
+        }
+        REQUIRE(file->read(file, buffer, 1, 1) == 1);
+        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
+        REQUIRE(file->seek(file, 0, SEEK_CUR) == fileSize);
+    }
+
+    SECTION("test 5")
+    {
+        file = VirtFs::rwopsOpenRead("test///test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = 23;
+        const char *restrict const str = "test line 1\ntest line 2";
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize - 1; f += 2)
+        {
+            REQUIRE(file->read(file, buffer, 2, 1) == 1);
+            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
+            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
+            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 2);
+        }
+        REQUIRE(file->seek(file, 0, SEEK_CUR) == 22);
+        REQUIRE(file->read(file, buffer, 2, 1) == 0);
+    }
+
+    SECTION("test 6")
+    {
+        file = VirtFs::rwopsOpenRead("test\\\\test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = 23;
+        const char *restrict const str = "test line 1\ntest line 2";
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize - 1; f += 2)
+        {
+            REQUIRE(file->read(file, buffer, 1, 2) == 2);
+            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
+            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
+            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 2);
+        }
+        REQUIRE(file->seek(file, 0, SEEK_CUR) == 22);
+        REQUIRE(file->read(file, buffer, 1, 2) == 1);
+        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
+    }
+
+    SECTION("test 7")
+    {
+        file = VirtFs::rwopsOpenRead("test//test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = 23;
+        const char *restrict const str = "test line 1\ntest line 2";
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize - 1; f += 2)
+        {
+            REQUIRE(file->read(file, buffer, 1, 2) == 2);
+            REQUIRE(file->seek(file, -2, SEEK_CUR) == f);
+            REQUIRE(file->seek(file, 0, SEEK_CUR) == f);
+            REQUIRE(file->seek(file, 2, SEEK_CUR) == f + 2);
+            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
+            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
+            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 2);
+        }
+        REQUIRE(file->seek(file, 0, SEEK_CUR) == 22);
+        REQUIRE(file->read(file, buffer, 1, 2) == 1);
+        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
+    }
+
+    SECTION("test 8")
+    {
+        file = VirtFs::rwopsOpenRead("test/test.txt");
+        REQUIRE(file != nullptr);
+        const int fileSize = 23;
+        const char *restrict const str = "test line 1\ntest line 2";
+        buffer = calloc(fileSize + 1, 1);
+        for (int f = 0; f < fileSize - 1; f += 2)
+        {
+            REQUIRE(file->seek(file, -f - 2, SEEK_END) == 23 - f - 2);
+            REQUIRE(file->read(file, buffer, 1, 2) == 2);
+            REQUIRE(static_cast<char*>(buffer)[0] == str[23 - f - 2]);
+            REQUIRE(static_cast<char*>(buffer)[1] == str[23 - f - 2 + 1]);
+            REQUIRE(file->seek(file, 0, SEEK_CUR) == 23 - f);
+        }
+        // 3
+        REQUIRE(file->seek(file, 1, SEEK_CUR) == 4);
+        // 4
+        REQUIRE(file->read(file, buffer, 1, 2) == 2);
+        // 6
+        REQUIRE(static_cast<char*>(buffer)[0] == str[4]);
+        REQUIRE(static_cast<char*>(buffer)[1] == str[5]);
+        REQUIRE(file->seek(file, -7, SEEK_CUR) == -1);
+        REQUIRE(file->seek(file, 6, SEEK_SET) == 6);
+        REQUIRE(file->seek(file, -6, SEEK_CUR) == 0);
+    }
+
+    if (file != nullptr)
+        file->close(file);
+    free(buffer);
+    VirtFs::unmountDir(prefix + "data");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 getFiles zip1", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test2.zip",
+        Append_false);
+
+    StringVect list;
+    VirtFs::getFiles("dir", list);
+    REQUIRE(list.size() == 2);
+    REQUIRE(inList(list, "dye.png"));
+    REQUIRE(inList(list, "hide.png"));
+
+    list.clear();
+    VirtFs::getFiles("dir2", list);
+    REQUIRE(list.size() == 4);
+    REQUIRE(inList(list, "hide.png"));
+    REQUIRE(inList(list, "paths.xml"));
+    REQUIRE(inList(list, "test.txt"));
+    REQUIRE(inList(list, "units.xml"));
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 getFiles zip2", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip2(prefix + "data/test/test2.zip",
+        "dir",
+        Append_false);
+
+    StringVect list;
+    VirtFs::getFiles(dirSeparator, list);
+    REQUIRE(list.size() == 2);
+    REQUIRE(inList(list, "dye.png"));
+    REQUIRE(inList(list, "hide.png"));
+
+    list.clear();
+    VirtFs::getFiles("1", list);
+    REQUIRE(list.size() == 2);
+    REQUIRE(inList(list, "file1.txt"));
+    REQUIRE(inList(list, "test.txt"));
+
+    VirtFs::unmountZip2(prefix + "data/test/test2.zip",
+        "dir");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 getDirs1", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test2.zip",
+        Append_false);
+
+    StringVect list;
+    VirtFs::getDirs("dir", list);
+    REQUIRE(list.size() == 2);
+    REQUIRE(inList(list, "1"));
+    REQUIRE(inList(list, "gpl"));
+    list.clear();
+
+    VirtFs::getDirs("dir2", list);
+    REQUIRE(list.empty());
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 getDirs2", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+    StringVect list;
+
+    SECTION("dir1")
+    {
+        VirtFs::mountDir(prefix + "data/test",
+            Append_false);
+
+        VirtFs::getDirs("/", list);
+//        REQUIRE(list.size() == 2);
+        REQUIRE(inList(list, "dir1"));
+        REQUIRE(inList(list, "dir2"));
+        list.clear();
+
+        VirtFs::getDirs("dir1", list);
+        REQUIRE(list.empty());
+
+        VirtFs::unmountDir(prefix + "data/test");
+    }
+
+    SECTION("dir2")
+    {
+        VirtFs::mountDir(prefix + "data",
+            Append_false);
+
+        VirtFs::getDirs("sfx", list);
+        REQUIRE(inList(list, "system"));
+        list.clear();
+
+        VirtFs::getDirs("evol", list);
+        REQUIRE(list.size() == 2);
+        REQUIRE(inList(list, "icons"));
+        REQUIRE(inList(list, "images"));
+
+        VirtFs::unmountDir(prefix + "data");
+    }
+
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 getDirs3", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip2(prefix + "data/test/test2.zip",
+        "dir",
+        Append_false);
+
+    StringVect list;
+    VirtFs::getDirs(dirSeparator, list);
+    REQUIRE(list.size() == 2);
+    REQUIRE(inList(list, "1"));
+    REQUIRE(inList(list, "gpl"));
+    list.clear();
+
+    VirtFs::getDirs("1", list);
+    REQUIRE(list.empty());
+
+    VirtFs::unmountZip2(prefix + "data/test/test2.zip",
+        "dir");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 getDirs4", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+    StringVect list;
+
+    SECTION("dir1")
+    {
+        VirtFs::mountDir2(prefix + "data",
+            "test",
+            Append_false);
+
+        VirtFs::getDirs("/", list);
+        REQUIRE(inList(list, "dir1"));
+        REQUIRE(inList(list, "dir2"));
+        list.clear();
+
+        VirtFs::getDirs("dir1", list);
+        REQUIRE(list.empty());
+
+        VirtFs::unmountDir2(prefix + "data",
+            "test");
+    }
+
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 getFilesWithDir1", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip(prefix + "data/test/test2.zip",
+        Append_false);
+
+    StringVect list;
+    VirtFs::getFilesWithDir("dir", list);
+    REQUIRE(list.size() == 2);
+    REQUIRE(inList(list, "dir", "dye.png"));
+    REQUIRE(inList(list, "dir", "hide.png"));
+    list.clear();
+
+    VirtFs::getFilesWithDir("dir2", list);
+    REQUIRE(list.size() == 4);
+    REQUIRE(inList(list, "dir2", "hide.png"));
+    REQUIRE(inList(list, "dir2", "paths.xml"));
+    REQUIRE(inList(list, "dir2", "test.txt"));
+    REQUIRE(inList(list, "dir2", "units.xml"));
+    list.clear();
+
+    VirtFs::getFilesWithDir(dirSeparator, list);
+    REQUIRE(list.size() > 2);
+    REQUIRE(inList(list, dirSeparator, "test.txt"));
+    REQUIRE(inList(list, dirSeparator, "units.xml"));
+    list.clear();
+
+    VirtFs::unmountZip(prefix + "data/test/test2.zip");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 getFilesWithDir2", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+    StringVect list;
+
+    SECTION("dir1")
+    {
+        VirtFs::mountDir(prefix + "data/graphics",
+            Append_false);
+
+        VirtFs::getFilesWithDir("/", list);
+        REQUIRE(list.size() <= 5);
+        VirtFs::unmountDir(prefix + "data/graphics");
+    }
+
+    SECTION("dir2")
+    {
+        VirtFs::mountDir(prefix + "data",
+            Append_false);
+
+        VirtFs::getFilesWithDir("music", list);
+        REQUIRE(list.size() <= 5);
+        REQUIRE(!list.empty());
+        REQUIRE(inList(list, "music", "keprohm.ogg"));
+        list.clear();
+
+        VirtFs::getFilesWithDir(pathJoin("evol", "icons"), list);
+#ifdef WIN32
+        REQUIRE(list.size() == 1);
+        REQUIRE(inList(list, pathJoin("evol", "icons"), "evol-client.ico"));
+#else  // WIN32
+
+        REQUIRE(list.size() == 3);
+        REQUIRE(inList(list, pathJoin("evol", "icons"), "evol-client.ico"));
+        REQUIRE(inList(list, pathJoin("evol", "icons"), "evol-client.png"));
+        REQUIRE(inList(list, pathJoin("evol", "icons"), "evol-client.xpm"));
+#endif  // WIN32
+
+        VirtFs::unmountDir(prefix + "data");
+    }
+
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 getFilesWithDir3", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+
+    VirtFs::mountZip2(prefix + "data/test/test2.zip",
+        "dir",
+        Append_false);
+
+    StringVect list;
+    VirtFs::getFilesWithDir("1", list);
+    REQUIRE(list.size() == 2);
+    REQUIRE(inList(list, "1", "file1.txt"));
+    REQUIRE(inList(list, "1", "test.txt"));
+    list.clear();
+
+    VirtFs::getFilesWithDir(dirSeparator, list);
+    REQUIRE(list.size() == 2);
+    REQUIRE(inList(list, dirSeparator, "dye.png"));
+    REQUIRE(inList(list, dirSeparator, "hide.png"));
+    list.clear();
+
+    VirtFs::unmountZip2(prefix + "data/test/test2.zip",
+        "dir");
+    VirtFs::deinit();
+    delete2(logger);
+}
+
+TEST_CASE("VirtFs2 getFilesWithDir4", "")
+{
+    VirtFs::init(".");
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../" + prefix;
+    StringVect list;
+
+    SECTION("dir1")
+    {
+        VirtFs::mountDir2(prefix + "data/graphics",
+            "sprites",
+            Append_false);
+
+        VirtFs::getFilesWithDir("/", list);
+        REQUIRE(list.size() <= 16);
+        VirtFs::unmountDir2(prefix + "data/graphics",
+            "sprites");
+    }
+
+    SECTION("dir2")
+    {
+        VirtFs::mountDir2(prefix + "data",
+            "test",
+            Append_false);
+
+        VirtFs::getFilesWithDir("dir1", list);
+        REQUIRE(list.size() <= 6);
+        REQUIRE(!list.empty());
+        REQUIRE(inList(list, "dir1", "file1.txt"));
+        list.clear();
+
+        VirtFs::unmountDir2(prefix + "data",
+            "test");
+    }
+
+    VirtFs::deinit();
+    delete2(logger);
+}
diff --git a/src/unittests/fs/virtfs/virtfs2_unittest.cc b/src/unittests/fs/virtfs/virtfs2_unittest.cc
deleted file mode 100644
index 8e578cc71..000000000
--- a/src/unittests/fs/virtfs/virtfs2_unittest.cc
+++ /dev/null
@@ -1,1700 +0,0 @@
-/*
- *  The ManaPlus Client
- *  Copyright (C) 2016-2017  The ManaPlus Developers
- *
- *  This file is part of The ManaPlus Client.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "unittests/unittests.h"
-
-#include "fs/files.h"
-
-#include "fs/virtfs/fs.h"
-#include "fs/virtfs/rwops.h"
-
-#include "utils/checkutils.h"
-#include "utils/delete2.h"
-#include "utils/foreach.h"
-#include "utils/stringutils.h"
-
-PRAGMA48(GCC diagnostic push)
-PRAGMA48(GCC diagnostic ignored "-Wshadow")
-#include <SDL_rwops.h>
-PRAGMA48(GCC diagnostic pop)
-
-#ifndef UNITTESTS_CATCH
-#include <algorithm>
-#endif  // UNITTESTS_CATCH
-
-#include "debug.h"
-
-static bool inList(StringVect list,
-                   const std::string &name)
-{
-    FOR_EACH (StringVectCIter, it, list)
-    {
-        if (*it == name)
-            return true;
-    }
-    return false;
-}
-
-static bool inList(StringVect list,
-                   const std::string &dir,
-                   const std::string &name)
-{
-    const std::string path = pathJoin(dir, name);
-    FOR_EACH (StringVectCIter, it, list)
-    {
-        if (*it == path)
-            return true;
-    }
-    return false;
-}
-
-static void removeTemp(StringVect &restrict list)
-{
-    int cnt = 0;
-    std::sort(list.begin(), list.end());
-
-    FOR_EACH (StringVectIter, it, list)
-    {
-        if (*it != "serverlistplus.xml.part")
-        {
-            logger->log("file: %d %s",
-                cnt,
-                (*it).c_str());
-            cnt ++;
-        }
-    }
-
-    FOR_EACH (StringVectIter, it, list)
-    {
-        if (*it == "serverlistplus.xml.part")
-        {
-            list.erase(it);
-            return;
-        }
-    }
-}
-
-TEST_CASE("VirtFs2 isDirectory1", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountDir(prefix + "data",
-        Append_false);
-
-    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test/units.xml/") == false);
-    REQUIRE(VirtFs::isDirectory("test//units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test/units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test//units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ//units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test") == true);
-    REQUIRE(VirtFs::isDirectory("test/") == true);
-    REQUIRE(VirtFs::isDirectory("test//") == true);
-    REQUIRE(VirtFs::isDirectory("test/dir1") == true);
-    REQUIRE(VirtFs::isDirectory("test//dir1") == true);
-    REQUIRE(VirtFs::isDirectory("test//dir1/") == true);
-    REQUIRE(VirtFs::isDirectory("test//dir1//") == true);
-    REQUIRE(VirtFs::isDirectory("test\\dir1/") == true);
-    REQUIRE(VirtFs::isDirectory("test/dir1//") == true);
-    REQUIRE(VirtFs::isDirectory("testQ") == false);
-    REQUIRE(VirtFs::isDirectory("testQ/") == false);
-    REQUIRE(VirtFs::isDirectory("testQ//") == false);
-
-    VirtFs::mountDir(prefix + "data/test",
-        Append_false);
-
-    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test/units.xml/") == false);
-    REQUIRE(VirtFs::isDirectory("test//units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test/units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test") == true);
-    REQUIRE(VirtFs::isDirectory("testQ") == false);
-    REQUIRE(VirtFs::isDirectory("test/dir1") == true);
-    REQUIRE(VirtFs::isDirectory("test\\dir1") == true);
-
-    VirtFs::unmountDir(prefix + "data/test");
-
-    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test/units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("units.xml/") == false);
-    REQUIRE(VirtFs::isDirectory("test") == true);
-    REQUIRE(VirtFs::isDirectory("test/") == true);
-    REQUIRE(VirtFs::isDirectory("testQ") == false);
-    REQUIRE(VirtFs::isDirectory("test/dir1") == true);
-
-    VirtFs::unmountDirSilent(prefix + "data");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 isDirectory2", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test2.zip",
-        Append_false);
-
-    REQUIRE(VirtFs::isDirectory("dir2/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir2/units.xml/") == false);
-    REQUIRE(VirtFs::isDirectory("dir2//units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir2/units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir2//units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ//units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir") == true);
-    REQUIRE(VirtFs::isDirectory("dir2/") == true);
-    REQUIRE(VirtFs::isDirectory("dir2//") == true);
-    REQUIRE(VirtFs::isDirectory("dir/1") == true);
-    REQUIRE(VirtFs::isDirectory("dir//1") == true);
-    REQUIRE(VirtFs::isDirectory("dir\\1/") == true);
-    REQUIRE(VirtFs::isDirectory("dir/1") == true);
-    REQUIRE(VirtFs::isDirectory("dir/1/zzz") == false);
-    REQUIRE(VirtFs::isDirectory("test/dir1\\") == false);
-    REQUIRE(VirtFs::isDirectory("testQ") == false);
-    REQUIRE(VirtFs::isDirectory("testQ/") == false);
-    REQUIRE(VirtFs::isDirectory("testQ//") == false);
-
-    VirtFs::mountZip(prefix + "data/test/test.zip",
-        Append_false);
-
-    REQUIRE(VirtFs::isDirectory("dir2/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir2/units.xml/") == false);
-    REQUIRE(VirtFs::isDirectory("dir2\\units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir2/units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir2//units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ//units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir") == true);
-    REQUIRE(VirtFs::isDirectory("dir2/") == true);
-    REQUIRE(VirtFs::isDirectory("dir2\\") == true);
-    REQUIRE(VirtFs::isDirectory("dir/1") == true);
-    REQUIRE(VirtFs::isDirectory("dir//1") == true);
-    REQUIRE(VirtFs::isDirectory("dir//1/") == true);
-    REQUIRE(VirtFs::isDirectory("dir/1") == true);
-    REQUIRE(VirtFs::isDirectory("dir/1/zzz") == false);
-    REQUIRE(VirtFs::isDirectory("test/dir1//") == false);
-    REQUIRE(VirtFs::isDirectory("testQ") == false);
-    REQUIRE(VirtFs::isDirectory("testQ/") == false);
-    REQUIRE(VirtFs::isDirectory("testQ//") == false);
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-
-    REQUIRE(VirtFs::isDirectory("dir2/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir2/units.xml/") == false);
-    REQUIRE(VirtFs::isDirectory("dir2//units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir2/units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir2//units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ//units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir") == true);
-    REQUIRE(VirtFs::isDirectory("dir2/") == false);
-    REQUIRE(VirtFs::isDirectory("dir2//") == false);
-    REQUIRE(VirtFs::isDirectory("dir/1") == false);
-    REQUIRE(VirtFs::isDirectory("dir\\1") == false);
-    REQUIRE(VirtFs::isDirectory("dir//1/") == false);
-    REQUIRE(VirtFs::isDirectory("dir/1") == false);
-    REQUIRE(VirtFs::isDirectory("dir/1/zzz") == false);
-    REQUIRE(VirtFs::isDirectory("test/dir1//") == false);
-    REQUIRE(VirtFs::isDirectory("testQ") == false);
-    REQUIRE(VirtFs::isDirectory("testQ/") == false);
-    REQUIRE(VirtFs::isDirectory("testQ//") == false);
-
-    VirtFs::unmountZip(prefix + "data/test/test.zip");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 isDirectory3", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountDir2(prefix + "data",
-        "test",
-        Append_false);
-
-    REQUIRE(VirtFs::isDirectory("units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("units.xml/") == false);
-    REQUIRE(VirtFs::isDirectory("units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ//units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test") == false);
-    REQUIRE(VirtFs::isDirectory("dir1") == true);
-    REQUIRE(VirtFs::isDirectory("dir2//") == true);
-    REQUIRE(VirtFs::isDirectory("test/dir1") == false);
-    REQUIRE(VirtFs::isDirectory("testQ") == false);
-    REQUIRE(VirtFs::isDirectory("testQ/") == false);
-    REQUIRE(VirtFs::isDirectory("testQ//") == false);
-
-    VirtFs::unmountDirSilent2(prefix + "data",
-        "test");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 isDirectory4", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip2(prefix + "data/test/test2.zip",
-        "dir",
-        Append_false);
-
-    REQUIRE(VirtFs::isDirectory("dir2/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir2/units.xml/") == false);
-    REQUIRE(VirtFs::isDirectory("dir2//units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir2/units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir2//units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ//units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("1") == true);
-    REQUIRE(VirtFs::isDirectory("gpl") == true);
-    REQUIRE(VirtFs::isDirectory("dir2/") == false);
-    REQUIRE(VirtFs::isDirectory("dir/1") == false);
-    REQUIRE(VirtFs::isDirectory("dir/1/zzz") == false);
-    REQUIRE(VirtFs::isDirectory("test/dir1\\") == false);
-    REQUIRE(VirtFs::isDirectory("testQ") == false);
-    REQUIRE(VirtFs::isDirectory("testQ/") == false);
-    REQUIRE(VirtFs::isDirectory("testQ//") == false);
-
-    VirtFs::unmountZip2(prefix + "data/test/test2.zip",
-        "dir");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 openRead1", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountDir(prefix + "data",
-        Append_false);
-
-    VirtFs::File *file = nullptr;
-
-    file = VirtFs::openRead("test/units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("test\\units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("test/units123.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-
-    VirtFs::mountDir(prefix + "data/test",
-        Append_false);
-
-    file = VirtFs::openRead("test/units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("test/units123.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-
-    VirtFs::unmountDir(prefix + "data/test");
-
-    file = VirtFs::openRead("test/units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("test/units123.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-
-    VirtFs::unmountDir(prefix + "data");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 openRead2", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix("data/test/");
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "test2.zip",
-        Append_false);
-
-    VirtFs::File *file = nullptr;
-
-    file = VirtFs::openRead("dir2/units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir2\\units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir2/units123.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("units.xml1");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("dir/brimmedhat.png");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("dir//brimmedhat.png");
-    REQUIRE(file == nullptr);
-
-    VirtFs::mountZip(prefix + "test.zip",
-        Append_false);
-
-    file = VirtFs::openRead("dir2/units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir2//units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir2/units123.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("units.xml1");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("dir/brimmedhat.png");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-
-    VirtFs::unmountZip(prefix + "test.zip");
-
-    file = VirtFs::openRead("dir2/units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir2\\/\\units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir2/units123.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("units.xml1");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("dir/brimmedhat.png");
-    REQUIRE(file == nullptr);
-
-    VirtFs::unmountZip(prefix + "test2.zip");
-
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 openRead3", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountDir2(prefix + "data",
-        "test",
-        Append_false);
-
-    VirtFs::File *file = nullptr;
-
-    file = VirtFs::openRead("units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("test/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("units123.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("file1.txt");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("file2.txt");
-    REQUIRE(file == nullptr);
-
-    VirtFs::mountDir2(prefix + "data/test",
-        "dir2",
-        Append_false);
-
-    file = VirtFs::openRead("units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("test/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("units123.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("file1.txt");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("file2.txt");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-
-    VirtFs::unmountDir2(prefix + "data/test",
-        "dir2");
-
-    file = VirtFs::openRead("units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("test/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("units123.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("file1.txt");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("file2.txt");
-    REQUIRE(file == nullptr);
-
-    VirtFs::unmountDir2(prefix + "data",
-        "test");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 openRead4", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix("data/test/");
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip2(prefix + "test2.zip",
-        "dir",
-        Append_false);
-
-    VirtFs::File *file = nullptr;
-
-    file = VirtFs::openRead("dye.png");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("1\\test.txt");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir/dye.png");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("dye.png1");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("brimmedhat.png");
-    REQUIRE(file == nullptr);
-
-    VirtFs::mountZip2(prefix + "test.zip",
-        "dir",
-        Append_false);
-
-    file = VirtFs::openRead("dye.png");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("1\\test.txt");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir/dye.png");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("dye.png1");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("brimmedhat.png");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-
-    VirtFs::unmountZip2(prefix + "test.zip",
-        "dir");
-
-    file = VirtFs::openRead("dye.png");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("1\\test.txt");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir/dye.png");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("dye.png1");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("brimmedhat.png");
-    REQUIRE(file == nullptr);
-
-    VirtFs::unmountZip2(prefix + "test2.zip",
-        "dir");
-
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 permitLinks", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountDir(prefix + "data",
-        Append_false);
-
-    const int cnt1 = VirtFs::exists("test/test2.txt") ? 26 : 25;
-    const int cnt2 = 26;
-
-    StringVect list;
-    VirtFs::permitLinks(false);
-    VirtFs::getFiles("test", list);
-    removeTemp(list);
-    const size_t sz = list.size();
-    REQUIRE(sz == cnt1);
-
-    list.clear();
-    VirtFs::permitLinks(true);
-    VirtFs::getFiles("test", list);
-    removeTemp(list);
-    REQUIRE(list.size() == cnt2);
-
-    list.clear();
-    VirtFs::permitLinks(false);
-    VirtFs::getFiles("test", list);
-    removeTemp(list);
-    REQUIRE(list.size() == cnt1);
-
-    VirtFs::unmountDirSilent(prefix + "data");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 read1", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountDir(prefix + "data",
-        Append_false);
-
-    VirtFs::File *file = VirtFs::openRead("test/test.txt");
-    REQUIRE(file != nullptr);
-    REQUIRE(VirtFs::fileLength(file) == 23);
-    const int fileSize = VirtFs::fileLength(file);
-
-    void *restrict buffer = calloc(fileSize + 1, 1);
-    REQUIRE(VirtFs::read(file, buffer, 1, fileSize) == fileSize);
-    REQUIRE(strcmp(static_cast<char*>(buffer),
-        "test line 1\ntest line 2") == 0);
-    REQUIRE(VirtFs::tell(file) == fileSize);
-    REQUIRE(VirtFs::eof(file) != 0);
-
-    free(buffer);
-    buffer = calloc(fileSize + 1, 1);
-    REQUIRE(VirtFs::seek(file, 12) != 0);
-    REQUIRE(VirtFs::eof(file) == 0);
-    REQUIRE(VirtFs::tell(file) == 12);
-    REQUIRE(VirtFs::read(file, buffer, 1, 11) == 11);
-    REQUIRE(strcmp(static_cast<char*>(buffer),
-        "test line 2") == 0);
-    REQUIRE(VirtFs::eof(file) != 0);
-
-    VirtFs::close(file);
-    free(buffer);
-
-    VirtFs::unmountDir(prefix + "data");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 read2", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix("data/test/");
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "test2.zip",
-        Append_false);
-    VirtFs::File *file = nullptr;
-    void *restrict buffer = nullptr;
-
-    SECTION("test 1")
-    {
-        file = VirtFs::openRead("dir2//test.txt");
-        REQUIRE(file != nullptr);
-        REQUIRE(VirtFs::fileLength(file) == 23);
-        const int fileSize = VirtFs::fileLength(file);
-
-        buffer = calloc(fileSize + 1, 1);
-        REQUIRE(VirtFs::read(file, buffer, 1, fileSize) == fileSize);
-        REQUIRE(strcmp(static_cast<char*>(buffer),
-            "test line 1\ntest line 2") == 0);
-        REQUIRE(VirtFs::tell(file) == fileSize);
-        REQUIRE(VirtFs::eof(file) != 0);
-    }
-
-    SECTION("test 2")
-    {
-        file = VirtFs::openRead("dir2\\/test.txt");
-        REQUIRE(file != nullptr);
-        REQUIRE(VirtFs::fileLength(file) == 23);
-        const int fileSize = VirtFs::fileLength(file);
-
-        buffer = calloc(fileSize + 1, 1);
-        REQUIRE(VirtFs::seek(file, 12) != 0);
-        REQUIRE(VirtFs::eof(file) == 0);
-        REQUIRE(VirtFs::tell(file) == 12);
-        REQUIRE(VirtFs::read(file, buffer, 1, 11) == 11);
-        REQUIRE(strcmp(static_cast<char*>(buffer),
-            "test line 2") == 0);
-        REQUIRE(VirtFs::eof(file) != 0);
-    }
-
-    SECTION("test 3")
-    {
-        file = VirtFs::openRead("dir2//test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = VirtFs::fileLength(file);
-
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize; f ++)
-        {
-            REQUIRE(VirtFs::seek(file, f) != 0);
-            REQUIRE(VirtFs::eof(file) == 0);
-            REQUIRE(VirtFs::tell(file) == f);
-        }
-    }
-
-    SECTION("test 4")
-    {
-        file = VirtFs::openRead("dir2/test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = VirtFs::fileLength(file);
-        const char *restrict const str = "test line 1\ntest line 2";
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize - 1; f ++)
-        {
-            REQUIRE(VirtFs::read(file, buffer, 1, 1) == 1);
-            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
-            REQUIRE(VirtFs::eof(file) == 0);
-            REQUIRE(VirtFs::tell(file) == f + 1);
-        }
-        REQUIRE(VirtFs::read(file, buffer, 1, 1) == 1);
-        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
-        REQUIRE(VirtFs::eof(file) != 0);
-        REQUIRE(VirtFs::tell(file) == fileSize);
-    }
-
-    SECTION("test 5")
-    {
-        file = VirtFs::openRead("dir2\\\\test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = VirtFs::fileLength(file);
-        const char *restrict const str = "test line 1\ntest line 2";
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize - 1; f += 2)
-        {
-            REQUIRE(VirtFs::read(file, buffer, 2, 1) == 1);
-            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
-            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
-            REQUIRE(VirtFs::eof(file) == 0);
-            REQUIRE(VirtFs::tell(file) == f + 2);
-        }
-        REQUIRE(VirtFs::eof(file) == 0);
-        REQUIRE(VirtFs::tell(file) == 22);
-        REQUIRE(VirtFs::read(file, buffer, 2, 1) == 0);
-        REQUIRE(VirtFs::eof(file) == 0);
-    }
-
-    SECTION("test 6")
-    {
-        file = VirtFs::openRead("dir2//test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = VirtFs::fileLength(file);
-        const char *restrict const str = "test line 1\ntest line 2";
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize - 1; f += 2)
-        {
-            REQUIRE(VirtFs::read(file, buffer, 1, 2) == 2);
-            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
-            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
-            REQUIRE(VirtFs::eof(file) == 0);
-            REQUIRE(VirtFs::tell(file) == f + 2);
-        }
-        REQUIRE(VirtFs::eof(file) == 0);
-        REQUIRE(VirtFs::tell(file) == 22);
-        REQUIRE(VirtFs::read(file, buffer, 1, 2) == 1);
-        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
-        REQUIRE(VirtFs::eof(file) != 0);
-    }
-
-    VirtFs::close(file);
-    free(buffer);
-    VirtFs::unmountZip(prefix + "test2.zip");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 loadFile1", "")
-{
-    VirtFs::init(".");
-    int fileSize = 0;
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountDir(prefix + "data",
-        Append_false);
-
-    const char *const buffer = VirtFs::loadFile("test/test.txt", fileSize);
-    REQUIRE(static_cast<const void*>(buffer) != nullptr);
-    REQUIRE(fileSize == 23);
-    REQUIRE(strncmp(buffer, "test line 1\ntest line 2", 23) == 0);
-    delete [] buffer;
-
-    VirtFs::unmountDir(prefix + "data");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 loadFile2", "")
-{
-    VirtFs::init(".");
-    int fileSize = 0;
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test2.zip",
-        Append_false);
-
-    SECTION("test 1")
-    {
-        const char *restrict buffer = VirtFs::loadFile("dir2//test.txt",
-            fileSize);
-        REQUIRE(static_cast<const void*>(buffer) != nullptr);
-        REQUIRE(fileSize == 23);
-        REQUIRE(strncmp(buffer, "test line 1\ntest line 2", 23) == 0);
-        delete [] buffer;
-    }
-
-    SECTION("test 2")
-    {
-        const char *restrict buffer = VirtFs::loadFile("dir2\\/test.txt",
-            fileSize);
-        REQUIRE(static_cast<const void*>(buffer) != nullptr);
-        REQUIRE(fileSize == 23);
-        REQUIRE(strncmp(buffer, "test line 1\ntest line 2", 23) == 0);
-        delete [] buffer;
-    }
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 loadFile3", "")
-{
-    VirtFs::init(".");
-    int fileSize = 0;
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountDir2(prefix + "data",
-        "test",
-        Append_false);
-
-    const char *const buffer = VirtFs::loadFile("test.txt", fileSize);
-    REQUIRE(static_cast<const void*>(buffer) != nullptr);
-    REQUIRE(fileSize == 23);
-    REQUIRE(strncmp(buffer, "test line 1\ntest line 2", 23) == 0);
-    delete [] buffer;
-
-    VirtFs::unmountDir2(prefix + "data",
-        "test");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 loadFile4", "")
-{
-    VirtFs::init(".");
-    int fileSize = 0;
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip2(prefix + "data/test/test2.zip",
-        "dir2",
-        Append_false);
-
-    SECTION("test 1")
-    {
-        const char *restrict buffer = VirtFs::loadFile("test.txt",
-            fileSize);
-        REQUIRE(static_cast<const void*>(buffer) != nullptr);
-        REQUIRE(fileSize == 23);
-        REQUIRE(strncmp(buffer, "test line 1\ntest line 2", 23) == 0);
-        delete [] buffer;
-    }
-
-    SECTION("test 2")
-    {
-        const char *restrict buffer = VirtFs::loadFile("test.txt",
-            fileSize);
-        REQUIRE(static_cast<const void*>(buffer) != nullptr);
-        REQUIRE(fileSize == 23);
-        REQUIRE(strncmp(buffer, "test line 1\ntest line 2", 23) == 0);
-        delete [] buffer;
-    }
-
-    VirtFs::unmountZip2(prefix + "data/test/test2.zip",
-        "dir2");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 rwops_read1", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountDir(prefix + "data",
-        Append_false);
-
-    SDL_RWops *file = VirtFs::rwopsOpenRead("test/test.txt");
-    REQUIRE(file != nullptr);
-#ifdef USE_SDL2
-    REQUIRE(file->size(file) == 23);
-#endif  // USE_SDL2
-
-    const int fileSize = 23;
-
-    void *restrict buffer = calloc(fileSize + 1, 1);
-    REQUIRE(file->read(file, buffer, 1, fileSize) == fileSize);
-    REQUIRE(strcmp(static_cast<char*>(buffer),
-        "test line 1\ntest line 2") == 0);
-    REQUIRE(file->seek(file, 0, SEEK_CUR) == fileSize);
-
-    free(buffer);
-    buffer = calloc(fileSize + 1, 1);
-    REQUIRE(file->seek(file, 12, SEEK_SET) != 0);
-    REQUIRE(file->seek(file, 0, SEEK_CUR) == 12);
-    REQUIRE(file->read(file, buffer, 1, 11) == 11);
-    REQUIRE(strcmp(static_cast<char*>(buffer),
-        "test line 2") == 0);
-
-    file->close(file);
-    free(buffer);
-
-    VirtFs::unmountDir(prefix + "data");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 rwops_read2", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix("data/test/");
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "test2.zip",
-        Append_false);
-    SDL_RWops *file = nullptr;
-    void *restrict buffer = nullptr;
-
-    SECTION("test 1")
-    {
-        file = VirtFs::rwopsOpenRead("dir2//test.txt");
-        REQUIRE(file != nullptr);
-#ifdef USE_SDL2
-        REQUIRE(file->size(file) == 23);
-#endif  // USE_SDL2
-        const int fileSize = 23;
-
-        buffer = calloc(fileSize + 1, 1);
-        REQUIRE(file->read(file, buffer, 1, fileSize) == fileSize);
-        REQUIRE(strcmp(static_cast<char*>(buffer),
-            "test line 1\ntest line 2") == 0);
-        REQUIRE(file->seek(file, 0, SEEK_CUR) == fileSize);
-    }
-
-    SECTION("test 2")
-    {
-        file = VirtFs::rwopsOpenRead("dir2\\/test.txt");
-        REQUIRE(file != nullptr);
-#ifdef USE_SDL2
-        REQUIRE(file->size(file) == 23);
-#endif  // USE_SDL2
-        const int fileSize = 23;
-
-        buffer = calloc(fileSize + 1, 1);
-        REQUIRE(file->seek(file, 12, SEEK_SET) != 0);
-        REQUIRE(file->seek(file, 0, SEEK_CUR) == 12);
-        REQUIRE(file->read(file, buffer, 1, 11) == 11);
-        REQUIRE(strcmp(static_cast<char*>(buffer),
-            "test line 2") == 0);
-    }
-
-    SECTION("test 3")
-    {
-        file = VirtFs::rwopsOpenRead("dir2//test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = 23;
-
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize; f ++)
-        {
-            REQUIRE(file->seek(file, f, SEEK_SET) == f);
-            REQUIRE(file->seek(file, 0, SEEK_CUR) == f);
-        }
-    }
-
-    SECTION("test 4")
-    {
-        file = VirtFs::rwopsOpenRead("dir2/test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = 23;
-        const char *restrict const str = "test line 1\ntest line 2";
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize - 1; f ++)
-        {
-            REQUIRE(file->read(file, buffer, 1, 1) == 1);
-            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
-            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 1);
-        }
-        REQUIRE(file->read(file, buffer, 1, 1) == 1);
-        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
-        REQUIRE(file->seek(file, 0, SEEK_CUR) == fileSize);
-    }
-
-    SECTION("test 5")
-    {
-        file = VirtFs::rwopsOpenRead("dir2\\\\test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = 23;
-        const char *restrict const str = "test line 1\ntest line 2";
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize - 1; f += 2)
-        {
-            REQUIRE(file->read(file, buffer, 2, 1) == 1);
-            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
-            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
-            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 2);
-        }
-        REQUIRE(file->seek(file, 0, SEEK_CUR) == 22);
-        REQUIRE(file->read(file, buffer, 2, 1) == 0);
-    }
-
-    SECTION("test 6")
-    {
-        file = VirtFs::rwopsOpenRead("dir2//test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = 23;
-        const char *restrict const str = "test line 1\ntest line 2";
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize - 1; f += 2)
-        {
-            REQUIRE(file->read(file, buffer, 1, 2) == 2);
-            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
-            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
-            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 2);
-        }
-        REQUIRE(file->seek(file, 0, SEEK_CUR) == 22);
-        REQUIRE(file->read(file, buffer, 1, 2) == 1);
-        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
-    }
-
-    SECTION("test 7")
-    {
-        file = VirtFs::rwopsOpenRead("dir2//test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = 23;
-        const char *restrict const str = "test line 1\ntest line 2";
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize - 1; f += 2)
-        {
-            REQUIRE(file->read(file, buffer, 1, 2) == 2);
-            REQUIRE(file->seek(file, -2, SEEK_CUR) == f);
-            REQUIRE(file->seek(file, 0, SEEK_CUR) == f);
-            REQUIRE(file->seek(file, 2, SEEK_CUR) == f + 2);
-            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
-            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
-            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 2);
-        }
-        REQUIRE(file->seek(file, 0, SEEK_CUR) == 22);
-        REQUIRE(file->read(file, buffer, 1, 2) == 1);
-        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
-    }
-
-    SECTION("test 8")
-    {
-        file = VirtFs::rwopsOpenRead("dir2//test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = 23;
-        const char *restrict const str = "test line 1\ntest line 2";
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize - 1; f += 2)
-        {
-            REQUIRE(file->seek(file, -f - 2, SEEK_END) == 23 - f - 2);
-            REQUIRE(file->read(file, buffer, 1, 2) == 2);
-            REQUIRE(static_cast<char*>(buffer)[0] == str[23 - f - 2]);
-            REQUIRE(static_cast<char*>(buffer)[1] == str[23 - f - 2 + 1]);
-            REQUIRE(file->seek(file, 0, SEEK_CUR) == 23 - f);
-        }
-        // 3
-        REQUIRE(file->seek(file, 1, SEEK_CUR) == 4);
-        // 4
-        REQUIRE(file->read(file, buffer, 1, 2) == 2);
-        // 6
-        REQUIRE(static_cast<char*>(buffer)[0] == str[4]);
-        REQUIRE(static_cast<char*>(buffer)[1] == str[5]);
-        REQUIRE(file->seek(file, -7, SEEK_CUR) == -1);
-        REQUIRE(file->seek(file, 6, SEEK_SET) == 6);
-        REQUIRE(file->seek(file, -6, SEEK_CUR) == 0);
-    }
-
-    if (file != nullptr)
-        file->close(file);
-    free(buffer);
-    VirtFs::unmountZip(prefix + "test2.zip");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 rwops_read3", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountDir(prefix + "data",
-        Append_false);
-    SDL_RWops *file = nullptr;
-    void *restrict buffer = nullptr;
-
-    SECTION("test 1")
-    {
-        file = VirtFs::rwopsOpenRead("test/test.txt");
-        REQUIRE(file != nullptr);
-#ifdef USE_SDL2
-        REQUIRE(file->size(file) == 23);
-#endif  // USE_SDL2
-        const int fileSize = 23;
-
-        buffer = calloc(fileSize + 1, 1);
-        REQUIRE(file->read(file, buffer, 1, fileSize) == fileSize);
-        REQUIRE(strcmp(static_cast<char*>(buffer),
-            "test line 1\ntest line 2") == 0);
-        REQUIRE(file->seek(file, 0, SEEK_CUR) == fileSize);
-    }
-
-    SECTION("test 2")
-    {
-        file = VirtFs::rwopsOpenRead("test\\test.txt");
-        REQUIRE(file != nullptr);
-#ifdef USE_SDL2
-        REQUIRE(file->size(file) == 23);
-#endif  // USE_SDL2
-        const int fileSize = 23;
-
-        buffer = calloc(fileSize + 1, 1);
-        REQUIRE(file->seek(file, 12, SEEK_SET) != 0);
-        REQUIRE(file->seek(file, 0, SEEK_CUR) == 12);
-        REQUIRE(file->read(file, buffer, 1, 11) == 11);
-        REQUIRE(strcmp(static_cast<char*>(buffer),
-            "test line 2") == 0);
-    }
-
-    SECTION("test 3")
-    {
-        file = VirtFs::rwopsOpenRead("test\\/test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = 23;
-
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize; f ++)
-        {
-            REQUIRE(file->seek(file, f, SEEK_SET) == f);
-            REQUIRE(file->seek(file, 0, SEEK_CUR) == f);
-        }
-    }
-
-    SECTION("test 4")
-    {
-        file = VirtFs::rwopsOpenRead("test/test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = 23;
-        const char *restrict const str = "test line 1\ntest line 2";
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize - 1; f ++)
-        {
-            REQUIRE(file->read(file, buffer, 1, 1) == 1);
-            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
-            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 1);
-        }
-        REQUIRE(file->read(file, buffer, 1, 1) == 1);
-        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
-        REQUIRE(file->seek(file, 0, SEEK_CUR) == fileSize);
-    }
-
-    SECTION("test 5")
-    {
-        file = VirtFs::rwopsOpenRead("test///test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = 23;
-        const char *restrict const str = "test line 1\ntest line 2";
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize - 1; f += 2)
-        {
-            REQUIRE(file->read(file, buffer, 2, 1) == 1);
-            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
-            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
-            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 2);
-        }
-        REQUIRE(file->seek(file, 0, SEEK_CUR) == 22);
-        REQUIRE(file->read(file, buffer, 2, 1) == 0);
-    }
-
-    SECTION("test 6")
-    {
-        file = VirtFs::rwopsOpenRead("test\\\\test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = 23;
-        const char *restrict const str = "test line 1\ntest line 2";
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize - 1; f += 2)
-        {
-            REQUIRE(file->read(file, buffer, 1, 2) == 2);
-            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
-            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
-            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 2);
-        }
-        REQUIRE(file->seek(file, 0, SEEK_CUR) == 22);
-        REQUIRE(file->read(file, buffer, 1, 2) == 1);
-        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
-    }
-
-    SECTION("test 7")
-    {
-        file = VirtFs::rwopsOpenRead("test//test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = 23;
-        const char *restrict const str = "test line 1\ntest line 2";
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize - 1; f += 2)
-        {
-            REQUIRE(file->read(file, buffer, 1, 2) == 2);
-            REQUIRE(file->seek(file, -2, SEEK_CUR) == f);
-            REQUIRE(file->seek(file, 0, SEEK_CUR) == f);
-            REQUIRE(file->seek(file, 2, SEEK_CUR) == f + 2);
-            REQUIRE(static_cast<char*>(buffer)[0] == str[f]);
-            REQUIRE(static_cast<char*>(buffer)[1] == str[f + 1]);
-            REQUIRE(file->seek(file, 0, SEEK_CUR) == f + 2);
-        }
-        REQUIRE(file->seek(file, 0, SEEK_CUR) == 22);
-        REQUIRE(file->read(file, buffer, 1, 2) == 1);
-        REQUIRE(static_cast<char*>(buffer)[0] == str[22]);
-    }
-
-    SECTION("test 8")
-    {
-        file = VirtFs::rwopsOpenRead("test/test.txt");
-        REQUIRE(file != nullptr);
-        const int fileSize = 23;
-        const char *restrict const str = "test line 1\ntest line 2";
-        buffer = calloc(fileSize + 1, 1);
-        for (int f = 0; f < fileSize - 1; f += 2)
-        {
-            REQUIRE(file->seek(file, -f - 2, SEEK_END) == 23 - f - 2);
-            REQUIRE(file->read(file, buffer, 1, 2) == 2);
-            REQUIRE(static_cast<char*>(buffer)[0] == str[23 - f - 2]);
-            REQUIRE(static_cast<char*>(buffer)[1] == str[23 - f - 2 + 1]);
-            REQUIRE(file->seek(file, 0, SEEK_CUR) == 23 - f);
-        }
-        // 3
-        REQUIRE(file->seek(file, 1, SEEK_CUR) == 4);
-        // 4
-        REQUIRE(file->read(file, buffer, 1, 2) == 2);
-        // 6
-        REQUIRE(static_cast<char*>(buffer)[0] == str[4]);
-        REQUIRE(static_cast<char*>(buffer)[1] == str[5]);
-        REQUIRE(file->seek(file, -7, SEEK_CUR) == -1);
-        REQUIRE(file->seek(file, 6, SEEK_SET) == 6);
-        REQUIRE(file->seek(file, -6, SEEK_CUR) == 0);
-    }
-
-    if (file != nullptr)
-        file->close(file);
-    free(buffer);
-    VirtFs::unmountDir(prefix + "data");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 getFiles zip1", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test2.zip",
-        Append_false);
-
-    StringVect list;
-    VirtFs::getFiles("dir", list);
-    REQUIRE(list.size() == 2);
-    REQUIRE(inList(list, "dye.png"));
-    REQUIRE(inList(list, "hide.png"));
-
-    list.clear();
-    VirtFs::getFiles("dir2", list);
-    REQUIRE(list.size() == 4);
-    REQUIRE(inList(list, "hide.png"));
-    REQUIRE(inList(list, "paths.xml"));
-    REQUIRE(inList(list, "test.txt"));
-    REQUIRE(inList(list, "units.xml"));
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 getFiles zip2", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip2(prefix + "data/test/test2.zip",
-        "dir",
-        Append_false);
-
-    StringVect list;
-    VirtFs::getFiles(dirSeparator, list);
-    REQUIRE(list.size() == 2);
-    REQUIRE(inList(list, "dye.png"));
-    REQUIRE(inList(list, "hide.png"));
-
-    list.clear();
-    VirtFs::getFiles("1", list);
-    REQUIRE(list.size() == 2);
-    REQUIRE(inList(list, "file1.txt"));
-    REQUIRE(inList(list, "test.txt"));
-
-    VirtFs::unmountZip2(prefix + "data/test/test2.zip",
-        "dir");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 getDirs1", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test2.zip",
-        Append_false);
-
-    StringVect list;
-    VirtFs::getDirs("dir", list);
-    REQUIRE(list.size() == 2);
-    REQUIRE(inList(list, "1"));
-    REQUIRE(inList(list, "gpl"));
-    list.clear();
-
-    VirtFs::getDirs("dir2", list);
-    REQUIRE(list.empty());
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 getDirs2", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-    StringVect list;
-
-    SECTION("dir1")
-    {
-        VirtFs::mountDir(prefix + "data/test",
-            Append_false);
-
-        VirtFs::getDirs("/", list);
-//        REQUIRE(list.size() == 2);
-        REQUIRE(inList(list, "dir1"));
-        REQUIRE(inList(list, "dir2"));
-        list.clear();
-
-        VirtFs::getDirs("dir1", list);
-        REQUIRE(list.empty());
-
-        VirtFs::unmountDir(prefix + "data/test");
-    }
-
-    SECTION("dir2")
-    {
-        VirtFs::mountDir(prefix + "data",
-            Append_false);
-
-        VirtFs::getDirs("sfx", list);
-        REQUIRE(inList(list, "system"));
-        list.clear();
-
-        VirtFs::getDirs("evol", list);
-        REQUIRE(list.size() == 2);
-        REQUIRE(inList(list, "icons"));
-        REQUIRE(inList(list, "images"));
-
-        VirtFs::unmountDir(prefix + "data");
-    }
-
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 getDirs3", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip2(prefix + "data/test/test2.zip",
-        "dir",
-        Append_false);
-
-    StringVect list;
-    VirtFs::getDirs(dirSeparator, list);
-    REQUIRE(list.size() == 2);
-    REQUIRE(inList(list, "1"));
-    REQUIRE(inList(list, "gpl"));
-    list.clear();
-
-    VirtFs::getDirs("1", list);
-    REQUIRE(list.empty());
-
-    VirtFs::unmountZip2(prefix + "data/test/test2.zip",
-        "dir");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 getDirs4", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-    StringVect list;
-
-    SECTION("dir1")
-    {
-        VirtFs::mountDir2(prefix + "data",
-            "test",
-            Append_false);
-
-        VirtFs::getDirs("/", list);
-        REQUIRE(inList(list, "dir1"));
-        REQUIRE(inList(list, "dir2"));
-        list.clear();
-
-        VirtFs::getDirs("dir1", list);
-        REQUIRE(list.empty());
-
-        VirtFs::unmountDir2(prefix + "data",
-            "test");
-    }
-
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 getFilesWithDir1", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test2.zip",
-        Append_false);
-
-    StringVect list;
-    VirtFs::getFilesWithDir("dir", list);
-    REQUIRE(list.size() == 2);
-    REQUIRE(inList(list, "dir", "dye.png"));
-    REQUIRE(inList(list, "dir", "hide.png"));
-    list.clear();
-
-    VirtFs::getFilesWithDir("dir2", list);
-    REQUIRE(list.size() == 4);
-    REQUIRE(inList(list, "dir2", "hide.png"));
-    REQUIRE(inList(list, "dir2", "paths.xml"));
-    REQUIRE(inList(list, "dir2", "test.txt"));
-    REQUIRE(inList(list, "dir2", "units.xml"));
-    list.clear();
-
-    VirtFs::getFilesWithDir(dirSeparator, list);
-    REQUIRE(list.size() > 2);
-    REQUIRE(inList(list, dirSeparator, "test.txt"));
-    REQUIRE(inList(list, dirSeparator, "units.xml"));
-    list.clear();
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 getFilesWithDir2", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-    StringVect list;
-
-    SECTION("dir1")
-    {
-        VirtFs::mountDir(prefix + "data/graphics",
-            Append_false);
-
-        VirtFs::getFilesWithDir("/", list);
-        REQUIRE(list.size() <= 5);
-        VirtFs::unmountDir(prefix + "data/graphics");
-    }
-
-    SECTION("dir2")
-    {
-        VirtFs::mountDir(prefix + "data",
-            Append_false);
-
-        VirtFs::getFilesWithDir("music", list);
-        REQUIRE(list.size() <= 5);
-        REQUIRE(!list.empty());
-        REQUIRE(inList(list, "music", "keprohm.ogg"));
-        list.clear();
-
-        VirtFs::getFilesWithDir(pathJoin("evol", "icons"), list);
-#ifdef WIN32
-        REQUIRE(list.size() == 1);
-        REQUIRE(inList(list, pathJoin("evol", "icons"), "evol-client.ico"));
-#else  // WIN32
-
-        REQUIRE(list.size() == 3);
-        REQUIRE(inList(list, pathJoin("evol", "icons"), "evol-client.ico"));
-        REQUIRE(inList(list, pathJoin("evol", "icons"), "evol-client.png"));
-        REQUIRE(inList(list, pathJoin("evol", "icons"), "evol-client.xpm"));
-#endif  // WIN32
-
-        VirtFs::unmountDir(prefix + "data");
-    }
-
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 getFilesWithDir3", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip2(prefix + "data/test/test2.zip",
-        "dir",
-        Append_false);
-
-    StringVect list;
-    VirtFs::getFilesWithDir("1", list);
-    REQUIRE(list.size() == 2);
-    REQUIRE(inList(list, "1", "file1.txt"));
-    REQUIRE(inList(list, "1", "test.txt"));
-    list.clear();
-
-    VirtFs::getFilesWithDir(dirSeparator, list);
-    REQUIRE(list.size() == 2);
-    REQUIRE(inList(list, dirSeparator, "dye.png"));
-    REQUIRE(inList(list, dirSeparator, "hide.png"));
-    list.clear();
-
-    VirtFs::unmountZip2(prefix + "data/test/test2.zip",
-        "dir");
-    VirtFs::deinit();
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs2 getFilesWithDir4", "")
-{
-    VirtFs::init(".");
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-    StringVect list;
-
-    SECTION("dir1")
-    {
-        VirtFs::mountDir2(prefix + "data/graphics",
-            "sprites",
-            Append_false);
-
-        VirtFs::getFilesWithDir("/", list);
-        REQUIRE(list.size() <= 16);
-        VirtFs::unmountDir2(prefix + "data/graphics",
-            "sprites");
-    }
-
-    SECTION("dir2")
-    {
-        VirtFs::mountDir2(prefix + "data",
-            "test",
-            Append_false);
-
-        VirtFs::getFilesWithDir("dir1", list);
-        REQUIRE(list.size() <= 6);
-        REQUIRE(!list.empty());
-        REQUIRE(inList(list, "dir1", "file1.txt"));
-        list.clear();
-
-        VirtFs::unmountDir2(prefix + "data",
-            "test");
-    }
-
-    VirtFs::deinit();
-    delete2(logger);
-}
diff --git a/src/unittests/fs/virtfs/virtfs_unittest.cc b/src/unittests/fs/virtfs/virtfs_unittest.cc
deleted file mode 100644
index c31f0965e..000000000
--- a/src/unittests/fs/virtfs/virtfs_unittest.cc
+++ /dev/null
@@ -1,1054 +0,0 @@
-/*
- *  The ManaPlus Client
- *  Copyright (C) 2016-2017  The ManaPlus Developers
- *
- *  This file is part of The ManaPlus Client.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "unittests/unittests.h"
-
-#include "fs/files.h"
-#include "fs/paths.h"
-
-#include "fs/virtfs/fs.h"
-#include "fs/virtfs/list.h"
-
-#include "utils/checkutils.h"
-#include "utils/delete2.h"
-#include "utils/foreach.h"
-
-#ifndef UNITTESTS_CATCH
-#include <algorithm>
-#endif  // UNITTESTS_CATCH
-
-#include "debug.h"
-
-TEST_CASE("VirtFs dirSeparator", "")
-{
-    REQUIRE(dirSeparator != nullptr);
-    REQUIRE(VirtFs::getDirSeparator() == std::string(dirSeparator));
-    VirtFs::updateDirSeparator();
-    REQUIRE(dirSeparator != nullptr);
-    REQUIRE(VirtFs::getDirSeparator() == std::string(dirSeparator));
-}
-
-TEST_CASE("VirtFs getBaseDir", "")
-{
-    REQUIRE(VirtFs::getBaseDir() != nullptr);
-}
-
-TEST_CASE("VirtFs getUserDir", "")
-{
-    REQUIRE(VirtFs::getUserDir() != nullptr);
-}
-
-TEST_CASE("VirtFs exists1", "")
-{
-    logger = new Logger();
-    VirtFs::mountDirSilent("data", Append_false);
-    VirtFs::mountDirSilent("../data", Append_false);
-
-    REQUIRE(VirtFs::exists("test") == true);
-    REQUIRE(VirtFs::exists("test/dir1") == true);
-    REQUIRE(VirtFs::exists("test/dir") == false);
-    REQUIRE(VirtFs::exists("test/units.xml") == true);
-    REQUIRE(VirtFs::exists("test/units123.xml") == false);
-    REQUIRE(VirtFs::exists("tesQ/units.xml") == false);
-    REQUIRE(VirtFs::exists("units.xml") == false);
-
-    VirtFs::mountDirSilent("data/test", Append_false);
-    VirtFs::mountDirSilent("../data/test", Append_false);
-
-    REQUIRE(VirtFs::exists("test") == true);
-    REQUIRE(VirtFs::exists("test/dir1") == true);
-    REQUIRE(VirtFs::exists("test/dir") == false);
-    REQUIRE(VirtFs::exists("test/units.xml") == true);
-    REQUIRE(VirtFs::exists("test/units123.xml") == false);
-    REQUIRE(VirtFs::exists("tesQ/units.xml") == false);
-    REQUIRE(VirtFs::exists("units.xml") == true);
-
-    VirtFs::unmountDirSilent("data/test");
-    VirtFs::unmountDirSilent("../data/test");
-
-    REQUIRE(VirtFs::exists("test") == true);
-    REQUIRE(VirtFs::exists("test/dir1") == true);
-    REQUIRE(VirtFs::exists("test/dir") == false);
-    REQUIRE(VirtFs::exists("test/units.xml") == true);
-    REQUIRE(VirtFs::exists("test/units123.xml") == false);
-    REQUIRE(VirtFs::exists("tesQ/units.xml") == false);
-    REQUIRE(VirtFs::exists("units.xml") == false);
-
-    VirtFs::unmountDirSilent("data");
-    VirtFs::unmountDirSilent("../data");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs exists2", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
-
-    REQUIRE(VirtFs::exists("test") == false);
-    REQUIRE(VirtFs::exists("test/units.xml") == false);
-    REQUIRE(VirtFs::exists("test.txt") == true);
-    REQUIRE(VirtFs::exists("dir/hide.png") == true);
-    REQUIRE(VirtFs::exists("dir/gpl") == true);
-    REQUIRE(VirtFs::exists("dir/gpl/zzz") == false);
-    REQUIRE(VirtFs::exists("units.xml") == true);
-    REQUIRE(VirtFs::exists("units.xml.") == false);
-    REQUIRE(VirtFs::exists("units.xml2") == false);
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs exists3", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test.zip", Append_false);
-    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
-
-    REQUIRE(VirtFs::exists("test") == false);
-    REQUIRE(VirtFs::exists("test/units.xml") == false);
-    REQUIRE(VirtFs::exists("dir/brimmedhat.png"));
-    REQUIRE(VirtFs::exists("dir//brimmedhat.png"));
-    REQUIRE(VirtFs::exists("dir//hide.png"));
-    REQUIRE(VirtFs::exists("dir/1"));
-    REQUIRE(VirtFs::exists("dir/gpl"));
-    REQUIRE(VirtFs::exists("dir/dye.png"));
-    REQUIRE(VirtFs::exists("dir/2") == false);
-    REQUIRE(VirtFs::exists("dir2/2") == false);
-    REQUIRE(VirtFs::exists("dir2/paths.xml"));
-
-    VirtFs::unmountZip(prefix + "data/test/test.zip");
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs exists4", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test.zip", Append_false);
-    VirtFs::mountDirSilent(prefix + "data/test", Append_false);
-
-    REQUIRE(VirtFs::exists("test") == false);
-    REQUIRE(VirtFs::exists("test/units.xml") == false);
-    REQUIRE(VirtFs::exists("dir/brimmedhat.png"));
-    REQUIRE(VirtFs::exists("dir//brimmedhat.png"));
-    REQUIRE(VirtFs::exists("dir//hide.png"));
-    REQUIRE(VirtFs::exists("dir/1") == false);
-    REQUIRE(VirtFs::exists("dir/gpl") == false);
-    REQUIRE(VirtFs::exists("dir/dye.png") == false);
-    REQUIRE(VirtFs::exists("dir/2") == false);
-    REQUIRE(VirtFs::exists("dir2/2") == false);
-    REQUIRE(VirtFs::exists("dir2/paths.xml") == false);
-    REQUIRE(VirtFs::exists("units.xml"));
-    REQUIRE(VirtFs::exists("dir1/file1.txt"));
-    REQUIRE(VirtFs::exists("dir2/file2.txt"));
-    REQUIRE(VirtFs::exists("dir2/file3.txt") == false);
-
-    VirtFs::unmountZip(prefix + "data/test/test.zip");
-    VirtFs::unmountDirSilent(prefix + "data/test");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs exists5", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    const std::string realDir = getRealPath(prefix + "data");
-    logger->log("real dir: " + realDir);
-    REQUIRE_FALSE(VirtFs::exists(realDir));
-
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs exists6", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip2(prefix + "data/test/test2.zip",
-        "dir",
-        Append_false);
-
-    REQUIRE(VirtFs::exists("test") == false);
-    REQUIRE(VirtFs::exists("test/units.xml") == false);
-    REQUIRE(VirtFs::exists("test.txt") == false);
-    REQUIRE(VirtFs::exists("dir/hide.png") == false);
-    REQUIRE(VirtFs::exists("dir/gpl") == false);
-    REQUIRE(VirtFs::exists("dir/gpl/zzz") == false);
-    REQUIRE(VirtFs::exists("units.xml") == false);
-    REQUIRE(VirtFs::exists("units.xml.") == false);
-    REQUIRE(VirtFs::exists("units.xml2") == false);
-    REQUIRE(VirtFs::exists("hide.png"));
-    REQUIRE(VirtFs::exists("dye.png"));
-    REQUIRE(VirtFs::exists("gpl"));
-    REQUIRE(VirtFs::exists("gpl/zzz") == false);
-
-    VirtFs::unmountZip2(prefix + "data/test/test2.zip",
-        "dir");
-    delete2(logger);
-}
-
-static void removeTemp(StringVect &restrict list)
-{
-    int cnt = 0;
-    std::sort(list.begin(), list.end());
-
-    FOR_EACH (StringVectIter, it, list)
-    {
-        if (*it != "serverlistplus.xml.part")
-        {
-            logger->log("file: %d %s",
-                cnt,
-                (*it).c_str());
-            cnt ++;
-        }
-    }
-
-    FOR_EACH (StringVectIter, it, list)
-    {
-        if (*it == "serverlistplus.xml.part")
-        {
-            list.erase(it);
-            return;
-        }
-    }
-}
-
-static bool inList(const VirtFs::List *const list,
-                   const std::string &name)
-{
-    FOR_EACH (StringVectCIter, it, list->names)
-    {
-        if (*it == name)
-            return true;
-    }
-    return false;
-}
-
-TEST_CASE("VirtFs enumerateFiles1", "")
-{
-    logger = new Logger;
-
-    VirtFs::mountDirSilent("data", Append_false);
-    VirtFs::mountDirSilent("../data", Append_false);
-
-    VirtFs::List *list = nullptr;
-
-    const int cnt1 = VirtFs::exists("test/test2.txt") ? 28 : 27;
-    const int cnt2 = 28;
-
-    VirtFs::permitLinks(false);
-    list = VirtFs::enumerateFiles("test");
-    removeTemp(list->names);
-    const size_t sz = list->names.size();
-    REQUIRE(sz == cnt1);
-    VirtFs::freeList(list);
-
-    VirtFs::permitLinks(true);
-    list = VirtFs::enumerateFiles("test");
-    removeTemp(list->names);
-    REQUIRE(list->names.size() == cnt2);
-    VirtFs::freeList(list);
-
-    VirtFs::permitLinks(false);
-    list = VirtFs::enumerateFiles("test");
-    removeTemp(list->names);
-    REQUIRE(list->names.size() == cnt1);
-    VirtFs::freeList(list);
-
-    list = VirtFs::enumerateFiles("test/units.xml");
-    removeTemp(list->names);
-    REQUIRE(list->names.empty());
-    VirtFs::freeList(list);
-
-    VirtFs::unmountDirSilent("data");
-    VirtFs::unmountDirSilent("../data");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs enumerateFiles2", "")
-{
-    logger = new Logger;
-
-    VirtFs::mountDirSilent("data/test/dir1",
-        Append_false);
-    VirtFs::mountDirSilent("../data/test/dir1",
-        Append_false);
-
-    VirtFs::List *list = nullptr;
-
-    list = VirtFs::enumerateFiles("/");
-    REQUIRE(list->names.size() == 5);
-    VirtFs::freeList(list);
-
-    VirtFs::unmountDirSilent("data/test/dir1");
-    VirtFs::unmountDirSilent("../data/test/dir1");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs enumerateFiles3", "")
-{
-    logger = new Logger;
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test.zip",
-        Append_false);
-
-    VirtFs::List *list = nullptr;
-
-    list = VirtFs::enumerateFiles("/");
-    REQUIRE(list->names.size() == 1);
-    REQUIRE(inList(list, "dir"));
-    VirtFs::freeList(list);
-
-    VirtFs::unmountZip(prefix + "data/test/test.zip");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs enumerateFiles4", "")
-{
-    logger = new Logger;
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test2.zip",
-        Append_false);
-
-    VirtFs::List *list = nullptr;
-
-    list = VirtFs::enumerateFiles("/");
-    REQUIRE(list->names.size() == 4);
-    REQUIRE(inList(list, "dir"));
-    REQUIRE(inList(list, "dir2"));
-    REQUIRE(inList(list, "test.txt"));
-    REQUIRE(inList(list, "units.xml"));
-    VirtFs::freeList(list);
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs enumerateFiles5", "")
-{
-    logger = new Logger;
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test2.zip",
-        Append_false);
-    VirtFs::mountDirSilent(prefix + "data/test", Append_false);
-
-    VirtFs::List *list = nullptr;
-
-    list = VirtFs::enumerateFiles("dir2");
-    REQUIRE(inList(list, "file1.txt"));
-    REQUIRE(inList(list, "file2.txt"));
-    REQUIRE(inList(list, "hide.png"));
-    REQUIRE(inList(list, "paths.xml"));
-    REQUIRE(inList(list, "test.txt"));
-    REQUIRE(inList(list, "units.xml"));
-    VirtFs::freeList(list);
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    VirtFs::unmountDirSilent(prefix + "data/test");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs isDirectory1", "")
-{
-    logger = new Logger();
-    VirtFs::mountDirSilent("data", Append_false);
-    VirtFs::mountDirSilent("../data", Append_false);
-
-    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test/units.xml/") == false);
-    REQUIRE(VirtFs::isDirectory("test//units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test/units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test//units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ//units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test") == true);
-    REQUIRE(VirtFs::isDirectory("test/") == true);
-    REQUIRE(VirtFs::isDirectory("test//") == true);
-    REQUIRE(VirtFs::isDirectory("test/dir1") == true);
-    REQUIRE(VirtFs::isDirectory("test//dir1") == true);
-    REQUIRE(VirtFs::isDirectory("test//dir1/") == true);
-    REQUIRE(VirtFs::isDirectory("test//dir1//") == true);
-    REQUIRE(VirtFs::isDirectory("test/dir1/") == true);
-    REQUIRE(VirtFs::isDirectory("test/dir1//") == true);
-    REQUIRE(VirtFs::isDirectory("testQ") == false);
-    REQUIRE(VirtFs::isDirectory("testQ/") == false);
-    REQUIRE(VirtFs::isDirectory("testQ//") == false);
-
-    VirtFs::mountDirSilent("data/test", Append_false);
-    VirtFs::mountDirSilent("../data/test", Append_false);
-
-    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test/units.xml/") == false);
-    REQUIRE(VirtFs::isDirectory("test//units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test/units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test") == true);
-    REQUIRE(VirtFs::isDirectory("testQ") == false);
-    REQUIRE(VirtFs::isDirectory("test/dir1") == true);
-
-    VirtFs::unmountDirSilent("data/test");
-    VirtFs::unmountDirSilent("../data/test");
-
-    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test/units123.xml") == false);
-    REQUIRE(VirtFs::isDirectory("tesQ/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("units.xml/") == false);
-    REQUIRE(VirtFs::isDirectory("test") == true);
-    REQUIRE(VirtFs::isDirectory("test/") == true);
-    REQUIRE(VirtFs::isDirectory("testQ") == false);
-    REQUIRE(VirtFs::isDirectory("test/dir1") == true);
-
-    VirtFs::unmountDirSilent("data");
-    VirtFs::unmountDirSilent("../data");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs isDirectory2", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
-
-    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("dir") == true);
-    REQUIRE(VirtFs::isDirectory("dir/") == true);
-    REQUIRE(VirtFs::isDirectory("dir//") == true);
-    REQUIRE(VirtFs::isDirectory("dir2") == true);
-    REQUIRE(VirtFs::isDirectory("dir3") == false);
-    REQUIRE(VirtFs::isDirectory("test.txt") == false);
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs isDirectory3", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountDir(prefix + "data", Append_false);
-    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
-
-    REQUIRE(VirtFs::isDirectory("test/units.xml") == false);
-    REQUIRE(VirtFs::isDirectory("test"));
-    REQUIRE(VirtFs::isDirectory("test//dye.png") == false);
-    REQUIRE(VirtFs::isDirectory("dir"));
-    REQUIRE(VirtFs::isDirectory("dir/"));
-    REQUIRE(VirtFs::isDirectory("dir//"));
-    REQUIRE(VirtFs::isDirectory("dir2"));
-    REQUIRE(VirtFs::isDirectory("dir3") == false);
-    REQUIRE(VirtFs::isDirectory("test.txt") == false);
-    REQUIRE(VirtFs::isDirectory("dir/hide.png") == false);
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    VirtFs::unmountDir(prefix + "data");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs openRead1", "")
-{
-    logger = new Logger();
-    VirtFs::mountDirSilent("data", Append_false);
-    VirtFs::mountDirSilent("../data", Append_false);
-
-    VirtFs::File *file = nullptr;
-
-    file = VirtFs::openRead("test/units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("test/units123.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("units.xml");
-    REQUIRE(file == nullptr);
-//    file = VirtFs::openRead("test");
-//    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-
-    VirtFs::mountDirSilent("data/test", Append_false);
-    VirtFs::mountDirSilent("../data/test", Append_false);
-
-    file = VirtFs::openRead("test/units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("test/units123.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-//    file = VirtFs::openRead("test");
-//    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-
-    VirtFs::unmountDirSilent("data/test");
-    VirtFs::unmountDirSilent("../data/test");
-
-    file = VirtFs::openRead("test/units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("test/units123.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("tesQ/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("units.xml");
-    REQUIRE(file == nullptr);
-//    file = VirtFs::openRead("test");
-//    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("testQ");
-    REQUIRE(file == nullptr);
-
-    VirtFs::unmountDirSilent("data");
-    VirtFs::unmountDirSilent("../data");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs openRead2", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
-
-    VirtFs::File *file = nullptr;
-
-    file = VirtFs::openRead("test/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir/hide.png");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir//hide.png");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs openRead3", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
-    VirtFs::mountDir(prefix + "data/test", Append_false);
-
-    VirtFs::File *file = nullptr;
-
-    file = VirtFs::openRead("test/units.xml");
-    REQUIRE(file == nullptr);
-    file = VirtFs::openRead("units.xml");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir/hide.png");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir//hide.png");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir/dye.png");
-    REQUIRE(file != nullptr);
-    VirtFs::close(file);
-    file = VirtFs::openRead("dir/dye.pn_");
-    REQUIRE(file == nullptr);
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    VirtFs::unmountDir(prefix + "data/test");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs getRealDir1", "")
-{
-    logger = new Logger();
-    const std::string sep = dirSeparator;
-    REQUIRE(VirtFs::getRealDir(".").empty());
-    REQUIRE(VirtFs::getRealDir("..").empty());
-    const bool dir1 = VirtFs::mountDirSilent("data", Append_false);
-    REQUIRE((dir1 || VirtFs::mountDirSilent("../data", Append_false))
-        == true);
-    if (dir1 == true)
-    {
-        REQUIRE(VirtFs::getRealDir("test") == "data");
-        REQUIRE(VirtFs::getRealDir("test/test.txt") ==
-            "data");
-    }
-    else
-    {
-        REQUIRE(VirtFs::getRealDir("test") == "../data");
-        REQUIRE(VirtFs::getRealDir("test/test.txt") ==
-            "../data");
-    }
-    REQUIRE(VirtFs::getRealDir("zzz").empty());
-
-    VirtFs::mountDirSilent("data/test", Append_false);
-    VirtFs::mountDirSilent("../data/test", Append_false);
-    if (dir1 == true)
-    {
-        REQUIRE(VirtFs::getRealDir("test") == "data");
-        REQUIRE(VirtFs::getRealDir("test/test.txt") ==
-            "data");
-        REQUIRE(VirtFs::getRealDir("test.txt") ==
-            "data" + sep + "test");
-    }
-    else
-    {
-        REQUIRE(VirtFs::getRealDir("test") == ".." + sep + "data");
-        REQUIRE(VirtFs::getRealDir("test/test.txt") ==
-            ".." + sep + "data");
-        REQUIRE(VirtFs::getRealDir("test.txt") ==
-            ".." + sep + "data" + sep + "test");
-    }
-    REQUIRE(VirtFs::getRealDir("zzz").empty());
-
-    if (dir1 == true)
-    {
-        VirtFs::mountZip("data/test/test.zip", Append_false);
-        REQUIRE(VirtFs::getRealDir("dir/brimmedhat.png") ==
-            "data" + sep + "test" + sep + "test.zip");
-        REQUIRE(VirtFs::getRealDir("hide.png") ==
-            "data" + sep + "test");
-    }
-    else
-    {
-        VirtFs::mountZip("../data/test/test.zip", Append_false);
-        REQUIRE(VirtFs::getRealDir("dir/brimmedhat.png") ==
-            ".." + sep + "data" + sep + "test" + sep + "test.zip");
-        REQUIRE(VirtFs::getRealDir("hide.png") ==
-            ".." + sep + "data" + sep + "test");
-    }
-
-    VirtFs::unmountDirSilent("data/test");
-    VirtFs::unmountDirSilent("../data/test");
-
-    if (dir1 == true)
-    {
-        REQUIRE(VirtFs::getRealDir("test") == "data");
-        REQUIRE(VirtFs::getRealDir("test/test.txt") ==
-            "data");
-        REQUIRE(VirtFs::getRealDir("dir/hide.png") ==
-            "data" + sep + "test" + sep + "test.zip");
-    }
-    else
-    {
-        REQUIRE(VirtFs::getRealDir("test") == ".." + sep + "data");
-        REQUIRE(VirtFs::getRealDir("test/test.txt") ==
-            ".." + sep + "data");
-        REQUIRE(VirtFs::getRealDir("dir/hide.png") ==
-            ".." + sep + "data" + sep + "test" + sep + "test.zip");
-    }
-    REQUIRE(VirtFs::exists("dir/hide.png"));
-    REQUIRE(VirtFs::getRealDir("zzz").empty());
-
-    VirtFs::unmountDirSilent("data");
-    VirtFs::unmountDirSilent("../data");
-    if (dir1 == true)
-        VirtFs::unmountZip("data/test/test.zip");
-    else
-        VirtFs::unmountZip("../data/test/test.zip");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs getrealDir2", "")
-{
-    logger = new Logger();
-    const std::string sep = dirSeparator;
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
-    VirtFs::mountDir(prefix + "data/test", Append_false);
-    VirtFs::mountDir(prefix + "data", Append_false);
-
-    REQUIRE(VirtFs::getRealDir("zzz").empty());
-
-    REQUIRE(VirtFs::getRealDir("dir1/file1.txt") ==
-        prefix + "data" + sep + "test");
-    REQUIRE(VirtFs::getRealDir("hide.png") ==
-        prefix + "data" + sep + "test");
-    REQUIRE(VirtFs::getRealDir("dir//hide.png") ==
-        prefix + "data" + sep + "test" + sep + "test2.zip");
-    REQUIRE(VirtFs::getRealDir("dir/1//test.txt") ==
-        prefix + "data" + sep + "test" + sep + "test2.zip");
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    VirtFs::unmountDir(prefix + "data/test");
-    VirtFs::unmountDir(prefix + "data");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs getrealDir3", "")
-{
-    logger = new Logger();
-    const std::string sep = dirSeparator;
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip2(prefix + "data/test/test2.zip",
-        "dir",
-        Append_false);
-    VirtFs::mountDir(prefix + "data/test", Append_false);
-
-    REQUIRE(VirtFs::getRealDir("zzz").empty());
-
-    REQUIRE(VirtFs::getRealDir("dir1/file1.txt") ==
-        prefix + "data" + sep + "test");
-    REQUIRE(VirtFs::getRealDir("hide.png") ==
-        prefix + "data" + sep + "test");
-    REQUIRE(VirtFs::getRealDir("hide.png") ==
-        prefix + "data" + sep + "test");
-    REQUIRE(VirtFs::getRealDir("1//test.txt") ==
-        prefix + "data" + sep + "test" + sep + "test2.zip");
-
-    VirtFs::unmountZip2(prefix + "data/test/test2.zip",
-        "dir");
-    VirtFs::unmountDir(prefix + "data/test");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs permitLinks1", "")
-{
-    logger = new Logger();
-    VirtFs::mountDirSilent("data", Append_false);
-    VirtFs::mountDirSilent("../data", Append_false);
-
-    const int cnt1 = VirtFs::exists("test/test2.txt") ? 26 : 25;
-    const int cnt2 = 26;
-
-    StringVect list;
-    VirtFs::permitLinks(false);
-    VirtFs::getFiles("test", list);
-    removeTemp(list);
-    const size_t sz = list.size();
-    REQUIRE(sz == cnt1);
-
-    list.clear();
-    VirtFs::permitLinks(true);
-    VirtFs::getFiles("test", list);
-    removeTemp(list);
-    REQUIRE(list.size() == cnt2);
-
-    list.clear();
-    VirtFs::permitLinks(false);
-    VirtFs::getFiles("test", list);
-    removeTemp(list);
-    REQUIRE(list.size() == cnt1);
-
-    VirtFs::unmountDirSilent("data");
-    VirtFs::unmountDirSilent("../data");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs permitLinks2", "")
-{
-    logger = new Logger();
-    VirtFs::mountDirSilent2("data",
-        "test",
-        Append_false);
-    VirtFs::mountDirSilent2("../data",
-        "test",
-        Append_false);
-
-    const int cnt1 = VirtFs::exists("test2.txt") ? 26 : 25;
-    const int cnt2 = 26;
-
-    StringVect list;
-    VirtFs::permitLinks(false);
-    VirtFs::getFiles(dirSeparator, list);
-    removeTemp(list);
-    const size_t sz = list.size();
-    REQUIRE(sz == cnt1);
-
-    list.clear();
-    VirtFs::permitLinks(true);
-    VirtFs::getFiles(dirSeparator, list);
-    removeTemp(list);
-    REQUIRE(list.size() == cnt2);
-
-    list.clear();
-    VirtFs::permitLinks(false);
-    VirtFs::getFiles(dirSeparator, list);
-    removeTemp(list);
-    REQUIRE(list.size() == cnt1);
-
-    VirtFs::unmountDirSilent2("data",
-        "test");
-    VirtFs::unmountDirSilent2("../data",
-        "test");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs read1", "")
-{
-    logger = new Logger();
-    VirtFs::mountDirSilent("data", Append_false);
-    VirtFs::mountDirSilent("../data", Append_false);
-
-    VirtFs::File *file = VirtFs::openRead("test/test.txt");
-    REQUIRE(file != nullptr);
-    REQUIRE(VirtFs::fileLength(file) == 23);
-    const int fileSize = VirtFs::fileLength(file);
-
-    void *restrict buffer = calloc(fileSize + 1, 1);
-    REQUIRE(VirtFs::read(file, buffer, 1, fileSize) == fileSize);
-    REQUIRE(strcmp(static_cast<char*>(buffer),
-        "test line 1\ntest line 2") == 0);
-    REQUIRE(VirtFs::tell(file) == fileSize);
-    REQUIRE(VirtFs::eof(file) == true);
-
-    free(buffer);
-    buffer = calloc(fileSize + 1, 1);
-    REQUIRE(VirtFs::seek(file, 12) != 0);
-    REQUIRE(VirtFs::eof(file) == false);
-    REQUIRE(VirtFs::tell(file) == 12);
-    REQUIRE(VirtFs::read(file, buffer, 1, 11) == 11);
-    REQUIRE(strcmp(static_cast<char*>(buffer),
-        "test line 2") == 0);
-    REQUIRE(VirtFs::eof(file) == true);
-
-    VirtFs::close(file);
-    free(buffer);
-
-    VirtFs::unmountDirSilent("data");
-    VirtFs::unmountDirSilent("../data");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs read2", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
-
-    VirtFs::File *file = VirtFs::openRead("dir2/test.txt");
-    REQUIRE(file != nullptr);
-    REQUIRE(VirtFs::fileLength(file) == 23);
-    const int fileSize = VirtFs::fileLength(file);
-
-    void *restrict buffer = calloc(fileSize + 1, 1);
-    REQUIRE(VirtFs::read(file, buffer, 1, fileSize) == fileSize);
-    REQUIRE(strcmp(static_cast<char*>(buffer),
-        "test line 1\ntest line 2") == 0);
-    REQUIRE(VirtFs::tell(file) == fileSize);
-    REQUIRE(VirtFs::eof(file) == true);
-
-    free(buffer);
-    buffer = calloc(fileSize + 1, 1);
-    REQUIRE(VirtFs::seek(file, 12) != 0);
-    REQUIRE(VirtFs::eof(file) == false);
-    REQUIRE(VirtFs::tell(file) == 12);
-    REQUIRE(VirtFs::read(file, buffer, 1, 11) == 11);
-    REQUIRE(strcmp(static_cast<char*>(buffer),
-        "test line 2") == 0);
-    REQUIRE(VirtFs::eof(file) == true);
-
-    VirtFs::close(file);
-    free(buffer);
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs read3", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test2.zip", Append_false);
-    VirtFs::mountDir(prefix + "data", Append_false);
-
-    VirtFs::File *file = VirtFs::openRead("dir2/test.txt");
-    REQUIRE(file != nullptr);
-    REQUIRE(VirtFs::fileLength(file) == 23);
-    const int fileSize = VirtFs::fileLength(file);
-
-    void *restrict buffer = calloc(fileSize + 1, 1);
-    REQUIRE(VirtFs::read(file, buffer, 1, fileSize) == fileSize);
-    REQUIRE(strcmp(static_cast<char*>(buffer),
-        "test line 1\ntest line 2") == 0);
-    REQUIRE(VirtFs::tell(file) == fileSize);
-    REQUIRE(VirtFs::eof(file) == true);
-
-    free(buffer);
-    buffer = calloc(fileSize + 1, 1);
-    REQUIRE(VirtFs::seek(file, 12) != 0);
-    REQUIRE(VirtFs::eof(file) == false);
-    REQUIRE(VirtFs::tell(file) == 12);
-    REQUIRE(VirtFs::read(file, buffer, 1, 11) == 11);
-    REQUIRE(strcmp(static_cast<char*>(buffer),
-        "test line 2") == 0);
-    REQUIRE(VirtFs::eof(file) == true);
-
-    VirtFs::close(file);
-    free(buffer);
-
-    VirtFs::unmountZip(prefix + "data/test/test2.zip");
-    VirtFs::unmountDir(prefix + "data");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs read4", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountDir(prefix + "data/test", Append_true);
-    VirtFs::mountZip(prefix + "data/test/test5.zip", Append_true);
-
-    VirtFs::File *file = VirtFs::openRead("dir1/file1.txt");
-    REQUIRE(file != nullptr);
-    REQUIRE(VirtFs::fileLength(file) == 23);
-    const int fileSize = VirtFs::fileLength(file);
-
-    void *restrict buffer = calloc(fileSize + 1, 1);
-    REQUIRE(VirtFs::read(file, buffer, 1, fileSize) == fileSize);
-    REQUIRE(strcmp(static_cast<char*>(buffer),
-        "test line 1\ntest line 2") == 0);
-    REQUIRE(VirtFs::tell(file) == fileSize);
-    REQUIRE(VirtFs::eof(file) == true);
-
-    free(buffer);
-    buffer = calloc(fileSize + 1, 1);
-    REQUIRE(VirtFs::seek(file, 12) != 0);
-    REQUIRE(VirtFs::eof(file) == false);
-    REQUIRE(VirtFs::tell(file) == 12);
-    REQUIRE(VirtFs::read(file, buffer, 1, 11) == 11);
-    REQUIRE(strcmp(static_cast<char*>(buffer),
-        "test line 2") == 0);
-    REQUIRE(VirtFs::eof(file) == true);
-
-    VirtFs::close(file);
-    free(buffer);
-
-    VirtFs::unmountZip(prefix + "data/test/test5.zip");
-    VirtFs::unmountDir(prefix + "data/test");
-    delete2(logger);
-}
-
-TEST_CASE("VirtFs read5", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../" + prefix;
-
-    VirtFs::mountZip(prefix + "data/test/test5.zip", Append_true);
-    VirtFs::mountDir(prefix + "data/test", Append_true);
-
-    VirtFs::File *file = VirtFs::openRead("dir1/file1.txt");
-    REQUIRE(file != nullptr);
-    REQUIRE(VirtFs::fileLength(file) == 23);
-    const int fileSize = VirtFs::fileLength(file);
-
-    void *restrict buffer = calloc(fileSize + 1, 1);
-    REQUIRE(VirtFs::read(file, buffer, 1, fileSize) == fileSize);
-    REQUIRE(strcmp(static_cast<char*>(buffer),
-        "test line 3\ntest line 4") == 0);
-    REQUIRE(VirtFs::tell(file) == fileSize);
-    REQUIRE(VirtFs::eof(file) == true);
-
-    free(buffer);
-    buffer = calloc(fileSize + 1, 1);
-    REQUIRE(VirtFs::seek(file, 12) != 0);
-    REQUIRE(VirtFs::eof(file) == false);
-    REQUIRE(VirtFs::tell(file) == 12);
-    REQUIRE(VirtFs::read(file, buffer, 1, 11) == 11);
-    REQUIRE(strcmp(static_cast<char*>(buffer),
-        "test line 4") == 0);
-    REQUIRE(VirtFs::eof(file) == true);
-
-    VirtFs::close(file);
-    free(buffer);
-
-    VirtFs::unmountZip(prefix + "data/test/test5.zip");
-    VirtFs::unmountDir(prefix + "data/test");
-    delete2(logger);
-}
diff --git a/src/unittests/fs/virtfs/zip.cc b/src/unittests/fs/virtfs/zip.cc
new file mode 100644
index 000000000..6ea9063fe
--- /dev/null
+++ b/src/unittests/fs/virtfs/zip.cc
@@ -0,0 +1,304 @@
+/*
+ *  The ManaPlus Client
+ *  Copyright (C) 2017  The ManaPlus Developers
+ *
+ *  This file is part of The ManaPlus Client.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "unittests/unittests.h"
+
+#include "logger.h"
+
+#include "fs/files.h"
+
+#include "fs/virtfs/fszip.h"
+#include "fs/virtfs/zipentry.h"
+#include "fs/virtfs/zipreader.h"
+#include "fs/virtfs/ziplocalheader.h"
+
+#include "utils/delete2.h"
+
+#include "debug.h"
+
+extern const char *dirSeparator;
+
+TEST_CASE("Zip readArchiveInfo", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    const std::string sep = dirSeparator;
+    if (Files::existsLocal(name) == false)
+        prefix = "../";
+
+    SECTION("test.zip")
+    {
+        name = prefix + "data/test/test.zip";
+
+        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
+            dirSeparator,
+            VirtFs::FsZip::getFuncs());
+        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
+
+        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
+        REQUIRE(headers.size() == 2);
+        REQUIRE(entry->root == name);
+        REQUIRE(headers[0]->fileName == "dir" + sep + "hide.png");
+        REQUIRE(headers[0]->compressSize == 365);
+        REQUIRE(headers[0]->uncompressSize == 368);
+        REQUIRE(headers[1]->fileName == "dir" + sep + "brimmedhat.png");
+        REQUIRE(headers[1]->compressSize == 1959);
+        REQUIRE(headers[1]->uncompressSize == 1959);
+
+        delete entry;
+    }
+
+    SECTION("test2.zip")
+    {
+        name = prefix + "data/test/test2.zip";
+
+        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
+            dirSeparator,
+            VirtFs::FsZip::getFuncs());
+        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
+
+        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
+        REQUIRE(headers.size() == 11);
+        REQUIRE(entry->root == name);
+        REQUIRE(headers[0]->fileName == "test.txt");
+        REQUIRE(headers[0]->compressSize == 17);
+        REQUIRE(headers[0]->uncompressSize == 23);
+
+        REQUIRE(headers[1]->fileName == "dir2" + sep + "hide.png");
+        REQUIRE(headers[1]->compressSize == 365);
+        REQUIRE(headers[1]->uncompressSize == 368);
+
+        REQUIRE(headers[2]->fileName == "dir2" + sep + "test.txt");
+        REQUIRE(headers[2]->compressSize == 17);
+        REQUIRE(headers[2]->uncompressSize == 23);
+
+        REQUIRE(headers[3]->fileName == "dir2" + sep + "paths.xml");
+        REQUIRE(headers[3]->compressSize == 154);
+        REQUIRE(headers[3]->uncompressSize == 185);
+
+        REQUIRE(headers[4]->fileName == "dir2" + sep + "units.xml");
+        REQUIRE(headers[4]->compressSize == 202);
+        REQUIRE(headers[4]->uncompressSize == 306);
+
+        REQUIRE(headers[5]->fileName == "dir" + sep + "hide.png");
+        REQUIRE(headers[5]->compressSize == 365);
+        REQUIRE(headers[5]->uncompressSize == 368);
+
+        REQUIRE(headers[6]->fileName ==
+            "dir" + sep + "1" + sep + "test.txt");
+        REQUIRE(headers[6]->compressSize == 17);
+        REQUIRE(headers[6]->uncompressSize == 23);
+
+        REQUIRE(headers[7]->fileName ==
+            "dir" + sep + "1" + sep + "file1.txt");
+        REQUIRE(headers[7]->compressSize == 17);
+        REQUIRE(headers[7]->uncompressSize == 23);
+
+        REQUIRE(headers[8]->fileName ==
+            "dir" + sep + "gpl" + sep + "palette.gpl");
+        REQUIRE(headers[8]->compressSize == 128);
+        REQUIRE(headers[8]->uncompressSize == 213);
+
+        REQUIRE(headers[9]->fileName ==
+            "dir" + sep + "dye.png");
+        REQUIRE(headers[9]->compressSize == 794);
+        REQUIRE(headers[9]->uncompressSize == 794);
+
+        REQUIRE(headers[10]->fileName == "units.xml");
+        REQUIRE(headers[10]->compressSize == 202);
+        REQUIRE(headers[10]->uncompressSize == 306);
+
+        delete entry;
+    }
+
+    SECTION("test3.zip")
+    {
+        name = prefix + "data/test/test3.zip";
+
+        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
+            dirSeparator,
+            VirtFs::FsZip::getFuncs());
+        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
+
+        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
+        REQUIRE(headers.size() == 2);
+        REQUIRE(entry->root == name);
+        REQUIRE(headers[0]->fileName == "test.txt");
+        REQUIRE(headers[0]->compressSize == 17);
+        REQUIRE(headers[0]->uncompressSize == 23);
+        REQUIRE(headers[1]->fileName == "units.xml");
+        REQUIRE(headers[1]->compressSize == 202);
+        REQUIRE(headers[1]->uncompressSize == 306);
+
+        delete entry;
+    }
+
+    SECTION("test4.zip")
+    {
+        name = prefix + "data/test/test4.zip";
+
+        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
+            dirSeparator,
+            VirtFs::FsZip::getFuncs());
+        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
+
+        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
+        REQUIRE(entry->root == name);
+        REQUIRE(headers.empty());
+
+        delete entry;
+    }
+
+    delete2(logger);
+}
+
+TEST_CASE("Zip readCompressedFile", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../";
+
+    SECTION("empty")
+    {
+        REQUIRE_THROWS(VirtFs::ZipReader::readCompressedFile(nullptr));
+    }
+
+    SECTION("test2.zip")
+    {
+        name = prefix + "data/test/test2.zip";
+
+        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
+            dirSeparator,
+            VirtFs::FsZip::getFuncs());
+        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
+
+        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
+        REQUIRE(headers.size() == 11);
+        REQUIRE(entry->root == name);
+        // test.txt
+        uint8_t *const buf = VirtFs::ZipReader::readCompressedFile(headers[0]);
+        REQUIRE(buf != nullptr);
+        delete [] buf;
+        delete entry;
+    }
+
+    delete2(logger);
+}
+
+TEST_CASE("Zip readFile", "")
+{
+    logger = new Logger();
+    std::string name("data/test/test.zip");
+    std::string prefix;
+    if (Files::existsLocal(name) == false)
+        prefix = "../";
+
+    SECTION("empty")
+    {
+        REQUIRE_THROWS(VirtFs::ZipReader::readFile(nullptr));
+    }
+
+    SECTION("test.zip")
+    {
+        name = prefix + "data/test/test.zip";
+
+        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
+            dirSeparator,
+            VirtFs::FsZip::getFuncs());
+        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
+
+        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
+        REQUIRE(headers.size() == 2);
+        REQUIRE(entry->root == name);
+        for (int f = 0; f < 2; f ++)
+        {
+            logger->log("test header: %s, %u, %u",
+                headers[f]->fileName.c_str(),
+                headers[f]->compressSize,
+                headers[f]->uncompressSize);
+            const uint8_t *const buf = VirtFs::ZipReader::readFile(headers[f]);
+            REQUIRE(buf != nullptr);
+            delete [] buf;
+        }
+        delete entry;
+    }
+
+    SECTION("test2.zip")
+    {
+        name = prefix + "data/test/test2.zip";
+
+        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
+            dirSeparator,
+            VirtFs::FsZip::getFuncs());
+        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
+
+        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
+        REQUIRE(headers.size() == 11);
+        REQUIRE(entry->root == name);
+        // test.txt
+        const uint8_t *buf = VirtFs::ZipReader::readFile(headers[0]);
+        REQUIRE(buf != nullptr);
+        const std::string str = std::string(reinterpret_cast<const char*>(buf),
+            headers[0]->uncompressSize);
+        REQUIRE(str == "test line 1\ntest line 2");
+        delete [] buf;
+        for (int f = 0; f < 11; f ++)
+        {
+            logger->log("test header: %s, %u, %u",
+                headers[f]->fileName.c_str(),
+                headers[f]->compressSize,
+                headers[f]->uncompressSize);
+            buf = VirtFs::ZipReader::readFile(headers[f]);
+            REQUIRE(buf != nullptr);
+            delete [] buf;
+        }
+        delete entry;
+    }
+
+    SECTION("test3.zip")
+    {
+        name = prefix + "data/test/test3.zip";
+
+        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
+            dirSeparator,
+            VirtFs::FsZip::getFuncs());
+        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
+
+        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
+        REQUIRE(headers.size() == 2);
+        REQUIRE(entry->root == name);
+        for (int f = 0; f < 2; f ++)
+        {
+            logger->log("test header: %s, %u, %u",
+                headers[f]->fileName.c_str(),
+                headers[f]->compressSize,
+                headers[f]->uncompressSize);
+            const uint8_t *const buf = VirtFs::ZipReader::readFile(headers[f]);
+            REQUIRE(buf != nullptr);
+            delete [] buf;
+        }
+        delete entry;
+    }
+
+    delete2(logger);
+}
diff --git a/src/unittests/fs/virtfs/zip_unittest.cc b/src/unittests/fs/virtfs/zip_unittest.cc
deleted file mode 100644
index 6ea9063fe..000000000
--- a/src/unittests/fs/virtfs/zip_unittest.cc
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- *  The ManaPlus Client
- *  Copyright (C) 2017  The ManaPlus Developers
- *
- *  This file is part of The ManaPlus Client.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "unittests/unittests.h"
-
-#include "logger.h"
-
-#include "fs/files.h"
-
-#include "fs/virtfs/fszip.h"
-#include "fs/virtfs/zipentry.h"
-#include "fs/virtfs/zipreader.h"
-#include "fs/virtfs/ziplocalheader.h"
-
-#include "utils/delete2.h"
-
-#include "debug.h"
-
-extern const char *dirSeparator;
-
-TEST_CASE("Zip readArchiveInfo", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    const std::string sep = dirSeparator;
-    if (Files::existsLocal(name) == false)
-        prefix = "../";
-
-    SECTION("test.zip")
-    {
-        name = prefix + "data/test/test.zip";
-
-        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
-            dirSeparator,
-            VirtFs::FsZip::getFuncs());
-        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
-
-        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
-        REQUIRE(headers.size() == 2);
-        REQUIRE(entry->root == name);
-        REQUIRE(headers[0]->fileName == "dir" + sep + "hide.png");
-        REQUIRE(headers[0]->compressSize == 365);
-        REQUIRE(headers[0]->uncompressSize == 368);
-        REQUIRE(headers[1]->fileName == "dir" + sep + "brimmedhat.png");
-        REQUIRE(headers[1]->compressSize == 1959);
-        REQUIRE(headers[1]->uncompressSize == 1959);
-
-        delete entry;
-    }
-
-    SECTION("test2.zip")
-    {
-        name = prefix + "data/test/test2.zip";
-
-        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
-            dirSeparator,
-            VirtFs::FsZip::getFuncs());
-        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
-
-        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
-        REQUIRE(headers.size() == 11);
-        REQUIRE(entry->root == name);
-        REQUIRE(headers[0]->fileName == "test.txt");
-        REQUIRE(headers[0]->compressSize == 17);
-        REQUIRE(headers[0]->uncompressSize == 23);
-
-        REQUIRE(headers[1]->fileName == "dir2" + sep + "hide.png");
-        REQUIRE(headers[1]->compressSize == 365);
-        REQUIRE(headers[1]->uncompressSize == 368);
-
-        REQUIRE(headers[2]->fileName == "dir2" + sep + "test.txt");
-        REQUIRE(headers[2]->compressSize == 17);
-        REQUIRE(headers[2]->uncompressSize == 23);
-
-        REQUIRE(headers[3]->fileName == "dir2" + sep + "paths.xml");
-        REQUIRE(headers[3]->compressSize == 154);
-        REQUIRE(headers[3]->uncompressSize == 185);
-
-        REQUIRE(headers[4]->fileName == "dir2" + sep + "units.xml");
-        REQUIRE(headers[4]->compressSize == 202);
-        REQUIRE(headers[4]->uncompressSize == 306);
-
-        REQUIRE(headers[5]->fileName == "dir" + sep + "hide.png");
-        REQUIRE(headers[5]->compressSize == 365);
-        REQUIRE(headers[5]->uncompressSize == 368);
-
-        REQUIRE(headers[6]->fileName ==
-            "dir" + sep + "1" + sep + "test.txt");
-        REQUIRE(headers[6]->compressSize == 17);
-        REQUIRE(headers[6]->uncompressSize == 23);
-
-        REQUIRE(headers[7]->fileName ==
-            "dir" + sep + "1" + sep + "file1.txt");
-        REQUIRE(headers[7]->compressSize == 17);
-        REQUIRE(headers[7]->uncompressSize == 23);
-
-        REQUIRE(headers[8]->fileName ==
-            "dir" + sep + "gpl" + sep + "palette.gpl");
-        REQUIRE(headers[8]->compressSize == 128);
-        REQUIRE(headers[8]->uncompressSize == 213);
-
-        REQUIRE(headers[9]->fileName ==
-            "dir" + sep + "dye.png");
-        REQUIRE(headers[9]->compressSize == 794);
-        REQUIRE(headers[9]->uncompressSize == 794);
-
-        REQUIRE(headers[10]->fileName == "units.xml");
-        REQUIRE(headers[10]->compressSize == 202);
-        REQUIRE(headers[10]->uncompressSize == 306);
-
-        delete entry;
-    }
-
-    SECTION("test3.zip")
-    {
-        name = prefix + "data/test/test3.zip";
-
-        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
-            dirSeparator,
-            VirtFs::FsZip::getFuncs());
-        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
-
-        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
-        REQUIRE(headers.size() == 2);
-        REQUIRE(entry->root == name);
-        REQUIRE(headers[0]->fileName == "test.txt");
-        REQUIRE(headers[0]->compressSize == 17);
-        REQUIRE(headers[0]->uncompressSize == 23);
-        REQUIRE(headers[1]->fileName == "units.xml");
-        REQUIRE(headers[1]->compressSize == 202);
-        REQUIRE(headers[1]->uncompressSize == 306);
-
-        delete entry;
-    }
-
-    SECTION("test4.zip")
-    {
-        name = prefix + "data/test/test4.zip";
-
-        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
-            dirSeparator,
-            VirtFs::FsZip::getFuncs());
-        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
-
-        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
-        REQUIRE(entry->root == name);
-        REQUIRE(headers.empty());
-
-        delete entry;
-    }
-
-    delete2(logger);
-}
-
-TEST_CASE("Zip readCompressedFile", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../";
-
-    SECTION("empty")
-    {
-        REQUIRE_THROWS(VirtFs::ZipReader::readCompressedFile(nullptr));
-    }
-
-    SECTION("test2.zip")
-    {
-        name = prefix + "data/test/test2.zip";
-
-        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
-            dirSeparator,
-            VirtFs::FsZip::getFuncs());
-        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
-
-        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
-        REQUIRE(headers.size() == 11);
-        REQUIRE(entry->root == name);
-        // test.txt
-        uint8_t *const buf = VirtFs::ZipReader::readCompressedFile(headers[0]);
-        REQUIRE(buf != nullptr);
-        delete [] buf;
-        delete entry;
-    }
-
-    delete2(logger);
-}
-
-TEST_CASE("Zip readFile", "")
-{
-    logger = new Logger();
-    std::string name("data/test/test.zip");
-    std::string prefix;
-    if (Files::existsLocal(name) == false)
-        prefix = "../";
-
-    SECTION("empty")
-    {
-        REQUIRE_THROWS(VirtFs::ZipReader::readFile(nullptr));
-    }
-
-    SECTION("test.zip")
-    {
-        name = prefix + "data/test/test.zip";
-
-        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
-            dirSeparator,
-            VirtFs::FsZip::getFuncs());
-        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
-
-        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
-        REQUIRE(headers.size() == 2);
-        REQUIRE(entry->root == name);
-        for (int f = 0; f < 2; f ++)
-        {
-            logger->log("test header: %s, %u, %u",
-                headers[f]->fileName.c_str(),
-                headers[f]->compressSize,
-                headers[f]->uncompressSize);
-            const uint8_t *const buf = VirtFs::ZipReader::readFile(headers[f]);
-            REQUIRE(buf != nullptr);
-            delete [] buf;
-        }
-        delete entry;
-    }
-
-    SECTION("test2.zip")
-    {
-        name = prefix + "data/test/test2.zip";
-
-        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
-            dirSeparator,
-            VirtFs::FsZip::getFuncs());
-        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
-
-        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
-        REQUIRE(headers.size() == 11);
-        REQUIRE(entry->root == name);
-        // test.txt
-        const uint8_t *buf = VirtFs::ZipReader::readFile(headers[0]);
-        REQUIRE(buf != nullptr);
-        const std::string str = std::string(reinterpret_cast<const char*>(buf),
-            headers[0]->uncompressSize);
-        REQUIRE(str == "test line 1\ntest line 2");
-        delete [] buf;
-        for (int f = 0; f < 11; f ++)
-        {
-            logger->log("test header: %s, %u, %u",
-                headers[f]->fileName.c_str(),
-                headers[f]->compressSize,
-                headers[f]->uncompressSize);
-            buf = VirtFs::ZipReader::readFile(headers[f]);
-            REQUIRE(buf != nullptr);
-            delete [] buf;
-        }
-        delete entry;
-    }
-
-    SECTION("test3.zip")
-    {
-        name = prefix + "data/test/test3.zip";
-
-        VirtFs::ZipEntry *const entry = new VirtFs::ZipEntry(name,
-            dirSeparator,
-            VirtFs::FsZip::getFuncs());
-        STD_VECTOR<VirtFs::ZipLocalHeader*> &headers = entry->mHeaders;
-
-        REQUIRE(VirtFs::ZipReader::readArchiveInfo(entry));
-        REQUIRE(headers.size() == 2);
-        REQUIRE(entry->root == name);
-        for (int f = 0; f < 2; f ++)
-        {
-            logger->log("test header: %s, %u, %u",
-                headers[f]->fileName.c_str(),
-                headers[f]->compressSize,
-                headers[f]->uncompressSize);
-            const uint8_t *const buf = VirtFs::ZipReader::readFile(headers[f]);
-            REQUIRE(buf != nullptr);
-            delete [] buf;
-        }
-        delete entry;
-    }
-
-    delete2(logger);
-}
-- 
cgit v1.2.3-70-g09d2