2023-02-10 06:07:07 +00:00
|
|
|
#include <QDir>
|
2016-04-14 00:23:54 +01:00
|
|
|
#include <QStandardPaths>
|
2023-08-14 17:16:53 +01:00
|
|
|
#include <QTemporaryDir>
|
|
|
|
#include <QTest>
|
2013-12-02 10:09:56 +00:00
|
|
|
|
2023-02-08 08:35:03 +00:00
|
|
|
#include <tasks/Task.h>
|
|
|
|
|
2022-09-11 21:25:18 +01:00
|
|
|
#include <FileSystem.h>
|
2023-02-07 10:27:49 +00:00
|
|
|
#include <StringUtils.h>
|
|
|
|
|
|
|
|
// Snippet from https://github.com/gulrak/filesystem#using-it-as-single-file-header
|
|
|
|
|
|
|
|
#ifdef __APPLE__
|
2023-08-14 17:16:53 +01:00
|
|
|
#include <Availability.h> // for deployment target to support pre-catalina targets without std::fs
|
|
|
|
#endif // __APPLE__
|
2023-02-07 10:27:49 +00:00
|
|
|
|
|
|
|
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
|
|
|
|
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
|
|
|
|
#define GHC_USE_STD_FS
|
|
|
|
#include <filesystem>
|
|
|
|
namespace fs = std::filesystem;
|
2023-08-14 17:16:53 +01:00
|
|
|
#endif // MacOS min version check
|
|
|
|
#endif // Other OSes version check
|
2023-02-07 10:27:49 +00:00
|
|
|
|
|
|
|
#ifndef GHC_USE_STD_FS
|
|
|
|
#include <ghc/filesystem.hpp>
|
|
|
|
namespace fs = ghc::filesystem;
|
|
|
|
#endif
|
2015-12-26 01:44:33 +00:00
|
|
|
|
2022-09-12 17:12:55 +01:00
|
|
|
#include <pathmatcher/RegexpMatcher.h>
|
|
|
|
|
2023-02-08 08:35:03 +00:00
|
|
|
class LinkTask : public Task {
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
friend class FileSystemTest;
|
|
|
|
|
|
|
|
LinkTask(QString src, QString dst)
|
|
|
|
{
|
|
|
|
m_lnk = new FS::create_link(src, dst, this);
|
|
|
|
m_lnk->debug(true);
|
|
|
|
}
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
~LinkTask() { delete m_lnk; }
|
2023-07-04 02:18:48 +01:00
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
void matcher(const IPathMatcher* filter) { m_lnk->matcher(filter); }
|
2023-02-08 08:35:03 +00:00
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
void linkRecursively(bool recursive)
|
2023-02-08 08:35:03 +00:00
|
|
|
{
|
|
|
|
m_lnk->linkRecursively(recursive);
|
|
|
|
m_linkRecursive = recursive;
|
|
|
|
}
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
void whitelist(bool b) { m_lnk->whitelist(b); }
|
2023-02-08 08:35:03 +00:00
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
void setMaxDepth(int depth) { m_lnk->setMaxDepth(depth); }
|
2023-02-10 02:48:40 +00:00
|
|
|
|
2023-02-08 08:35:03 +00:00
|
|
|
private:
|
|
|
|
void executeTask() override
|
|
|
|
{
|
2023-08-14 17:16:53 +01:00
|
|
|
if (!(*m_lnk)()) {
|
2023-02-08 08:35:03 +00:00
|
|
|
#if defined Q_OS_WIN32
|
|
|
|
if (!m_useHard) {
|
|
|
|
qDebug() << "EXPECTED: Link failure, Windows requires permissions for symlinks";
|
|
|
|
|
|
|
|
qDebug() << "atempting to run with privelage";
|
2023-08-14 17:16:53 +01:00
|
|
|
connect(m_lnk, &FS::create_link::finishedPrivileged, this, [&](bool gotResults) {
|
2023-02-08 20:36:15 +00:00
|
|
|
if (gotResults) {
|
|
|
|
emitSucceeded();
|
|
|
|
} else {
|
2023-02-23 00:40:07 +00:00
|
|
|
qDebug() << "Privileged run exited without results!";
|
2023-02-08 20:36:15 +00:00
|
|
|
emitFailed();
|
|
|
|
}
|
2023-02-08 08:35:03 +00:00
|
|
|
});
|
2023-02-23 00:40:07 +00:00
|
|
|
m_lnk->runPrivileged();
|
2023-02-08 08:35:03 +00:00
|
|
|
} else {
|
2023-02-08 20:36:15 +00:00
|
|
|
qDebug() << "Link Failed!" << m_lnk->getOSError().value() << m_lnk->getOSError().message().c_str();
|
2023-08-14 17:16:53 +01:00
|
|
|
}
|
2023-02-08 08:35:03 +00:00
|
|
|
#else
|
|
|
|
qDebug() << "Link Failed!" << m_lnk->getOSError().value() << m_lnk->getOSError().message().c_str();
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
emitSucceeded();
|
|
|
|
}
|
2023-06-04 22:59:37 +01:00
|
|
|
}
|
2023-02-08 08:35:03 +00:00
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
FS::create_link* m_lnk;
|
2023-06-05 06:46:05 +01:00
|
|
|
[[maybe_unused]] bool m_useHard = false;
|
2023-02-08 08:35:03 +00:00
|
|
|
bool m_linkRecursive = true;
|
|
|
|
};
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
class FileSystemTest : public QObject {
|
2018-07-15 13:51:05 +01:00
|
|
|
Q_OBJECT
|
2015-12-26 01:44:33 +00:00
|
|
|
|
2018-07-15 13:51:05 +01:00
|
|
|
const QString bothSlash = "/foo/";
|
|
|
|
const QString trailingSlash = "foo/";
|
|
|
|
const QString leadingSlash = "/foo";
|
2015-12-26 01:44:33 +00:00
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
private slots:
|
2018-07-15 13:51:05 +01:00
|
|
|
void test_pathCombine()
|
|
|
|
{
|
|
|
|
QCOMPARE(QString("/foo/foo"), FS::PathCombine(bothSlash, bothSlash));
|
|
|
|
QCOMPARE(QString("foo/foo"), FS::PathCombine(trailingSlash, trailingSlash));
|
|
|
|
QCOMPARE(QString("/foo/foo"), FS::PathCombine(leadingSlash, leadingSlash));
|
|
|
|
|
|
|
|
QCOMPARE(QString("/foo/foo/foo"), FS::PathCombine(bothSlash, bothSlash, bothSlash));
|
|
|
|
QCOMPARE(QString("foo/foo/foo"), FS::PathCombine(trailingSlash, trailingSlash, trailingSlash));
|
|
|
|
QCOMPARE(QString("/foo/foo/foo"), FS::PathCombine(leadingSlash, leadingSlash, leadingSlash));
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_PathCombine1_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("result");
|
|
|
|
QTest::addColumn<QString>("path1");
|
|
|
|
QTest::addColumn<QString>("path2");
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
QTest::newRow("qt 1") << "/abc/def/ghi/jkl"
|
|
|
|
<< "/abc/def"
|
|
|
|
<< "ghi/jkl";
|
|
|
|
QTest::newRow("qt 2") << "/abc/def/ghi/jkl"
|
|
|
|
<< "/abc/def/"
|
|
|
|
<< "ghi/jkl";
|
2013-12-17 01:09:58 +00:00
|
|
|
#if defined(Q_OS_WIN)
|
2023-08-14 17:16:53 +01:00
|
|
|
QTest::newRow("win native, from C:") << "C:/abc"
|
|
|
|
<< "C:"
|
|
|
|
<< "abc";
|
|
|
|
QTest::newRow("win native 1") << "C:/abc/def/ghi/jkl"
|
|
|
|
<< "C:\\abc\\def"
|
|
|
|
<< "ghi\\jkl";
|
|
|
|
QTest::newRow("win native 2") << "C:/abc/def/ghi/jkl"
|
|
|
|
<< "C:\\abc\\def\\"
|
|
|
|
<< "ghi\\jkl";
|
2013-12-02 10:09:56 +00:00
|
|
|
#endif
|
2018-07-15 13:51:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void test_PathCombine1()
|
|
|
|
{
|
|
|
|
QFETCH(QString, result);
|
|
|
|
QFETCH(QString, path1);
|
|
|
|
QFETCH(QString, path2);
|
|
|
|
|
|
|
|
QCOMPARE(FS::PathCombine(path1, path2), result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_PathCombine2_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("result");
|
|
|
|
QTest::addColumn<QString>("path1");
|
|
|
|
QTest::addColumn<QString>("path2");
|
|
|
|
QTest::addColumn<QString>("path3");
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
QTest::newRow("qt 1") << "/abc/def/ghi/jkl"
|
|
|
|
<< "/abc"
|
|
|
|
<< "def"
|
|
|
|
<< "ghi/jkl";
|
|
|
|
QTest::newRow("qt 2") << "/abc/def/ghi/jkl"
|
|
|
|
<< "/abc/"
|
|
|
|
<< "def"
|
|
|
|
<< "ghi/jkl";
|
|
|
|
QTest::newRow("qt 3") << "/abc/def/ghi/jkl"
|
|
|
|
<< "/abc"
|
|
|
|
<< "def/"
|
|
|
|
<< "ghi/jkl";
|
|
|
|
QTest::newRow("qt 4") << "/abc/def/ghi/jkl"
|
|
|
|
<< "/abc/"
|
|
|
|
<< "def/"
|
|
|
|
<< "ghi/jkl";
|
2013-12-17 01:09:58 +00:00
|
|
|
#if defined(Q_OS_WIN)
|
2023-08-14 17:16:53 +01:00
|
|
|
QTest::newRow("win 1") << "C:/abc/def/ghi/jkl"
|
|
|
|
<< "C:\\abc"
|
|
|
|
<< "def"
|
|
|
|
<< "ghi\\jkl";
|
|
|
|
QTest::newRow("win 2") << "C:/abc/def/ghi/jkl"
|
|
|
|
<< "C:\\abc\\"
|
|
|
|
<< "def"
|
|
|
|
<< "ghi\\jkl";
|
|
|
|
QTest::newRow("win 3") << "C:/abc/def/ghi/jkl"
|
|
|
|
<< "C:\\abc"
|
|
|
|
<< "def\\"
|
|
|
|
<< "ghi\\jkl";
|
|
|
|
QTest::newRow("win 4") << "C:/abc/def/ghi/jkl"
|
|
|
|
<< "C:\\abc\\"
|
|
|
|
<< "def"
|
|
|
|
<< "ghi\\jkl";
|
2013-12-02 10:09:56 +00:00
|
|
|
#endif
|
2018-07-15 13:51:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void test_PathCombine2()
|
|
|
|
{
|
|
|
|
QFETCH(QString, result);
|
|
|
|
QFETCH(QString, path1);
|
|
|
|
QFETCH(QString, path2);
|
|
|
|
QFETCH(QString, path3);
|
|
|
|
|
|
|
|
QCOMPARE(FS::PathCombine(path1, path2, path3), result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_copy()
|
|
|
|
{
|
2022-09-11 21:25:18 +01:00
|
|
|
QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
|
2023-08-14 17:16:53 +01:00
|
|
|
auto f = [&folder]() {
|
2018-07-15 13:51:05 +01:00
|
|
|
QTemporaryDir tempDir;
|
|
|
|
tempDir.setAutoRemove(true);
|
|
|
|
qDebug() << "From:" << folder << "To:" << tempDir.path();
|
|
|
|
|
|
|
|
QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
|
|
|
|
qDebug() << tempDir.path();
|
|
|
|
qDebug() << target_dir.path();
|
|
|
|
FS::copy c(folder, target_dir.path());
|
|
|
|
c();
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
for (auto entry : target_dir.entryList()) {
|
2018-07-15 13:51:05 +01:00
|
|
|
qDebug() << entry;
|
|
|
|
}
|
|
|
|
QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
|
|
|
|
QVERIFY(target_dir.entryList().contains("assets"));
|
|
|
|
};
|
|
|
|
|
|
|
|
// first try variant without trailing /
|
|
|
|
QVERIFY(!folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
|
|
|
|
// then variant with trailing /
|
|
|
|
folder.append('/');
|
|
|
|
QVERIFY(folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
}
|
|
|
|
|
2022-09-12 17:12:55 +01:00
|
|
|
void test_copy_with_blacklist()
|
|
|
|
{
|
|
|
|
QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
|
2023-08-14 17:16:53 +01:00
|
|
|
auto f = [&folder]() {
|
2022-09-12 17:12:55 +01:00
|
|
|
QTemporaryDir tempDir;
|
|
|
|
tempDir.setAutoRemove(true);
|
|
|
|
qDebug() << "From:" << folder << "To:" << tempDir.path();
|
|
|
|
|
|
|
|
QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
|
|
|
|
qDebug() << tempDir.path();
|
|
|
|
qDebug() << target_dir.path();
|
|
|
|
FS::copy c(folder, target_dir.path());
|
2023-07-04 02:18:48 +01:00
|
|
|
RegexpMatcher re("[.]?mcmeta");
|
|
|
|
c.matcher(&re);
|
2022-09-12 17:12:55 +01:00
|
|
|
c();
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
for (auto entry : target_dir.entryList()) {
|
2022-09-12 17:12:55 +01:00
|
|
|
qDebug() << entry;
|
|
|
|
}
|
|
|
|
QVERIFY(!target_dir.entryList().contains("pack.mcmeta"));
|
|
|
|
QVERIFY(target_dir.entryList().contains("assets"));
|
|
|
|
};
|
|
|
|
|
|
|
|
// first try variant without trailing /
|
|
|
|
QVERIFY(!folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
|
|
|
|
// then variant with trailing /
|
|
|
|
folder.append('/');
|
|
|
|
QVERIFY(folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
}
|
|
|
|
|
2022-10-22 22:25:14 +01:00
|
|
|
void test_copy_with_whitelist()
|
|
|
|
{
|
|
|
|
QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
|
2023-08-14 17:16:53 +01:00
|
|
|
auto f = [&folder]() {
|
2022-10-22 22:25:14 +01:00
|
|
|
QTemporaryDir tempDir;
|
|
|
|
tempDir.setAutoRemove(true);
|
|
|
|
qDebug() << "From:" << folder << "To:" << tempDir.path();
|
|
|
|
|
|
|
|
QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
|
|
|
|
qDebug() << tempDir.path();
|
|
|
|
qDebug() << target_dir.path();
|
|
|
|
FS::copy c(folder, target_dir.path());
|
2023-07-04 02:18:48 +01:00
|
|
|
RegexpMatcher re("[.]?mcmeta");
|
|
|
|
c.matcher(&re);
|
2022-10-22 22:25:14 +01:00
|
|
|
c.whitelist(true);
|
|
|
|
c();
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
for (auto entry : target_dir.entryList()) {
|
2022-10-22 22:25:14 +01:00
|
|
|
qDebug() << entry;
|
|
|
|
}
|
|
|
|
QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
|
|
|
|
QVERIFY(!target_dir.entryList().contains("assets"));
|
|
|
|
};
|
|
|
|
|
|
|
|
// first try variant without trailing /
|
|
|
|
QVERIFY(!folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
|
|
|
|
// then variant with trailing /
|
|
|
|
folder.append('/');
|
|
|
|
QVERIFY(folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
}
|
|
|
|
|
2022-10-15 13:34:47 +01:00
|
|
|
void test_copy_with_dot_hidden()
|
|
|
|
{
|
|
|
|
QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
|
2023-08-14 17:16:53 +01:00
|
|
|
auto f = [&folder]() {
|
2022-10-15 13:34:47 +01:00
|
|
|
QTemporaryDir tempDir;
|
|
|
|
tempDir.setAutoRemove(true);
|
|
|
|
qDebug() << "From:" << folder << "To:" << tempDir.path();
|
|
|
|
|
|
|
|
QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
|
|
|
|
qDebug() << tempDir.path();
|
|
|
|
qDebug() << target_dir.path();
|
|
|
|
FS::copy c(folder, target_dir.path());
|
|
|
|
c();
|
|
|
|
|
|
|
|
auto filter = QDir::Filter::Files | QDir::Filter::Dirs | QDir::Filter::Hidden;
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
for (auto entry : target_dir.entryList(filter)) {
|
2022-10-15 13:34:47 +01:00
|
|
|
qDebug() << entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVERIFY(target_dir.entryList(filter).contains(".secret_folder"));
|
|
|
|
target_dir.cd(".secret_folder");
|
|
|
|
QVERIFY(target_dir.entryList(filter).contains(".secret_file.txt"));
|
|
|
|
};
|
|
|
|
|
|
|
|
// first try variant without trailing /
|
|
|
|
QVERIFY(!folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
|
|
|
|
// then variant with trailing /
|
|
|
|
folder.append('/');
|
|
|
|
QVERIFY(folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
}
|
|
|
|
|
2022-10-29 00:55:25 +01:00
|
|
|
void test_copy_single_file()
|
|
|
|
{
|
|
|
|
QTemporaryDir tempDir;
|
|
|
|
tempDir.setAutoRemove(true);
|
|
|
|
|
|
|
|
{
|
|
|
|
QString file = QFINDTESTDATA("testdata/FileSystem/test_folder/pack.mcmeta");
|
|
|
|
|
|
|
|
qDebug() << "From:" << file << "To:" << tempDir.path();
|
|
|
|
|
|
|
|
QDir target_dir(FS::PathCombine(tempDir.path(), "pack.mcmeta"));
|
|
|
|
qDebug() << tempDir.path();
|
|
|
|
qDebug() << target_dir.path();
|
|
|
|
FS::copy c(file, target_dir.filePath("pack.mcmeta"));
|
|
|
|
c();
|
|
|
|
|
|
|
|
auto filter = QDir::Filter::Files;
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
for (auto entry : target_dir.entryList(filter)) {
|
2022-10-29 00:55:25 +01:00
|
|
|
qDebug() << entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVERIFY(target_dir.entryList(filter).contains("pack.mcmeta"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-15 08:02:15 +01:00
|
|
|
void test_getDesktop()
|
|
|
|
{
|
|
|
|
QCOMPARE(FS::getDesktopDir(), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
|
|
|
|
}
|
2023-02-07 07:05:06 +00:00
|
|
|
|
|
|
|
void test_link()
|
|
|
|
{
|
|
|
|
QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
|
2023-08-14 17:16:53 +01:00
|
|
|
auto f = [&folder]() {
|
2023-02-07 07:05:06 +00:00
|
|
|
QTemporaryDir tempDir;
|
|
|
|
tempDir.setAutoRemove(true);
|
|
|
|
qDebug() << "From:" << folder << "To:" << tempDir.path();
|
|
|
|
|
|
|
|
QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
|
|
|
|
qDebug() << tempDir.path();
|
|
|
|
qDebug() << target_dir.path();
|
2023-02-08 08:35:03 +00:00
|
|
|
|
|
|
|
LinkTask lnk_tsk(folder, target_dir.path());
|
|
|
|
lnk_tsk.linkRecursively(false);
|
2023-08-14 17:16:53 +01:00
|
|
|
QObject::connect(&lnk_tsk, &Task::finished,
|
|
|
|
[&] { QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); });
|
2023-02-08 08:35:03 +00:00
|
|
|
lnk_tsk.start();
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
QVERIFY2(QTest::qWaitFor([&]() { return lnk_tsk.isFinished(); }, 100000), "Task didn't finish as it should.");
|
2023-02-07 07:05:06 +00:00
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
for (auto entry : target_dir.entryList()) {
|
2023-02-07 07:05:06 +00:00
|
|
|
qDebug() << entry;
|
|
|
|
QFileInfo entry_lnk_info(target_dir.filePath(entry));
|
2023-02-07 09:56:16 +00:00
|
|
|
if (!entry_lnk_info.isDir())
|
|
|
|
QVERIFY(!entry_lnk_info.isSymLink());
|
2023-02-07 07:05:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QFileInfo lnk_info(target_dir.path());
|
|
|
|
QVERIFY(lnk_info.exists());
|
2023-02-07 09:56:16 +00:00
|
|
|
QVERIFY(lnk_info.isSymLink());
|
2023-02-07 07:05:06 +00:00
|
|
|
|
|
|
|
QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
|
|
|
|
QVERIFY(target_dir.entryList().contains("assets"));
|
|
|
|
};
|
|
|
|
|
|
|
|
// first try variant without trailing /
|
|
|
|
QVERIFY(!folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
|
|
|
|
// then variant with trailing /
|
|
|
|
folder.append('/');
|
|
|
|
QVERIFY(folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_hard_link()
|
|
|
|
{
|
|
|
|
QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
|
2023-08-14 17:16:53 +01:00
|
|
|
auto f = [&folder]() {
|
2023-02-07 09:56:16 +00:00
|
|
|
// use working dir to prevent makeing a hard link to a tmpfs or across devices
|
2023-08-14 17:16:53 +01:00
|
|
|
QTemporaryDir tempDir("./tmp");
|
2023-02-07 07:05:06 +00:00
|
|
|
tempDir.setAutoRemove(true);
|
|
|
|
qDebug() << "From:" << folder << "To:" << tempDir.path();
|
|
|
|
|
|
|
|
QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
|
|
|
|
qDebug() << tempDir.path();
|
|
|
|
qDebug() << target_dir.path();
|
|
|
|
FS::create_link lnk(folder, target_dir.path());
|
|
|
|
lnk.useHardLinks(true);
|
|
|
|
lnk.debug(true);
|
2023-08-14 17:16:53 +01:00
|
|
|
if (!lnk()) {
|
2023-02-08 08:35:03 +00:00
|
|
|
qDebug() << "Link Failed!" << lnk.getOSError().value() << lnk.getOSError().message().c_str();
|
2023-02-07 07:05:06 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
for (auto entry : target_dir.entryList()) {
|
2023-02-07 07:05:06 +00:00
|
|
|
qDebug() << entry;
|
|
|
|
QFileInfo entry_lnk_info(target_dir.filePath(entry));
|
2023-02-07 09:56:16 +00:00
|
|
|
QVERIFY(!entry_lnk_info.isSymLink());
|
2023-02-07 07:05:06 +00:00
|
|
|
QFileInfo entry_orig_info(QDir(folder).filePath(entry));
|
|
|
|
if (!entry_lnk_info.isDir()) {
|
|
|
|
qDebug() << "hard link equivalency?" << entry_lnk_info.absoluteFilePath() << "vs" << entry_orig_info.absoluteFilePath();
|
2023-08-14 17:16:53 +01:00
|
|
|
QVERIFY(fs::equivalent(fs::path(StringUtils::toStdString(entry_lnk_info.absoluteFilePath())),
|
|
|
|
fs::path(StringUtils::toStdString(entry_orig_info.absoluteFilePath()))));
|
|
|
|
}
|
2023-02-07 07:05:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QFileInfo lnk_info(target_dir.path());
|
|
|
|
QVERIFY(lnk_info.exists());
|
2023-02-07 09:56:16 +00:00
|
|
|
QVERIFY(!lnk_info.isSymLink());
|
2023-02-07 07:05:06 +00:00
|
|
|
|
|
|
|
QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
|
|
|
|
QVERIFY(target_dir.entryList().contains("assets"));
|
|
|
|
};
|
|
|
|
|
|
|
|
// first try variant without trailing /
|
|
|
|
QVERIFY(!folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
|
|
|
|
// then variant with trailing /
|
|
|
|
folder.append('/');
|
|
|
|
QVERIFY(folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_link_with_blacklist()
|
|
|
|
{
|
|
|
|
QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
|
2023-08-14 17:16:53 +01:00
|
|
|
auto f = [&folder]() {
|
2023-02-07 07:05:06 +00:00
|
|
|
QTemporaryDir tempDir;
|
|
|
|
tempDir.setAutoRemove(true);
|
|
|
|
qDebug() << "From:" << folder << "To:" << tempDir.path();
|
|
|
|
|
|
|
|
QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
|
|
|
|
qDebug() << tempDir.path();
|
|
|
|
qDebug() << target_dir.path();
|
2023-02-08 08:35:03 +00:00
|
|
|
|
|
|
|
LinkTask lnk_tsk(folder, target_dir.path());
|
2023-07-04 02:18:48 +01:00
|
|
|
RegexpMatcher re("[.]?mcmeta");
|
|
|
|
lnk_tsk.matcher(&re);
|
2023-02-08 08:35:03 +00:00
|
|
|
lnk_tsk.linkRecursively(true);
|
2023-08-14 17:16:53 +01:00
|
|
|
QObject::connect(&lnk_tsk, &Task::finished,
|
|
|
|
[&] { QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); });
|
2023-02-08 08:35:03 +00:00
|
|
|
lnk_tsk.start();
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
QVERIFY2(QTest::qWaitFor([&]() { return lnk_tsk.isFinished(); }, 100000), "Task didn't finish as it should.");
|
2023-02-07 07:05:06 +00:00
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
for (auto entry : target_dir.entryList()) {
|
2023-02-07 07:05:06 +00:00
|
|
|
qDebug() << entry;
|
|
|
|
QFileInfo entry_lnk_info(target_dir.filePath(entry));
|
2023-02-07 09:56:16 +00:00
|
|
|
if (!entry_lnk_info.isDir())
|
|
|
|
QVERIFY(entry_lnk_info.isSymLink());
|
2023-02-07 07:05:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QFileInfo lnk_info(target_dir.path());
|
|
|
|
QVERIFY(lnk_info.exists());
|
|
|
|
|
|
|
|
QVERIFY(!target_dir.entryList().contains("pack.mcmeta"));
|
|
|
|
QVERIFY(target_dir.entryList().contains("assets"));
|
|
|
|
};
|
|
|
|
|
|
|
|
// first try variant without trailing /
|
|
|
|
QVERIFY(!folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
|
|
|
|
// then variant with trailing /
|
|
|
|
folder.append('/');
|
|
|
|
QVERIFY(folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_link_with_whitelist()
|
|
|
|
{
|
|
|
|
QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
|
2023-08-14 17:16:53 +01:00
|
|
|
auto f = [&folder]() {
|
2023-02-07 07:05:06 +00:00
|
|
|
QTemporaryDir tempDir;
|
|
|
|
tempDir.setAutoRemove(true);
|
|
|
|
qDebug() << "From:" << folder << "To:" << tempDir.path();
|
|
|
|
|
|
|
|
QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
|
|
|
|
qDebug() << tempDir.path();
|
|
|
|
qDebug() << target_dir.path();
|
2023-02-08 08:35:03 +00:00
|
|
|
|
|
|
|
LinkTask lnk_tsk(folder, target_dir.path());
|
2023-07-04 02:18:48 +01:00
|
|
|
RegexpMatcher re("[.]?mcmeta");
|
|
|
|
lnk_tsk.matcher(&re);
|
2023-02-08 08:35:03 +00:00
|
|
|
lnk_tsk.linkRecursively(true);
|
|
|
|
lnk_tsk.whitelist(true);
|
2023-08-14 17:16:53 +01:00
|
|
|
QObject::connect(&lnk_tsk, &Task::finished,
|
|
|
|
[&] { QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); });
|
2023-02-08 08:35:03 +00:00
|
|
|
lnk_tsk.start();
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
QVERIFY2(QTest::qWaitFor([&]() { return lnk_tsk.isFinished(); }, 100000), "Task didn't finish as it should.");
|
2023-02-07 07:05:06 +00:00
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
for (auto entry : target_dir.entryList()) {
|
2023-02-07 07:05:06 +00:00
|
|
|
qDebug() << entry;
|
|
|
|
QFileInfo entry_lnk_info(target_dir.filePath(entry));
|
2023-02-07 09:56:16 +00:00
|
|
|
if (!entry_lnk_info.isDir())
|
|
|
|
QVERIFY(entry_lnk_info.isSymLink());
|
2023-02-07 07:05:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QFileInfo lnk_info(target_dir.path());
|
|
|
|
QVERIFY(lnk_info.exists());
|
|
|
|
|
|
|
|
QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
|
|
|
|
QVERIFY(!target_dir.entryList().contains("assets"));
|
|
|
|
};
|
|
|
|
|
|
|
|
// first try variant without trailing /
|
|
|
|
QVERIFY(!folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
|
|
|
|
// then variant with trailing /
|
|
|
|
folder.append('/');
|
|
|
|
QVERIFY(folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_link_with_dot_hidden()
|
|
|
|
{
|
|
|
|
QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
|
2023-08-14 17:16:53 +01:00
|
|
|
auto f = [&folder]() {
|
2023-02-07 07:05:06 +00:00
|
|
|
QTemporaryDir tempDir;
|
|
|
|
tempDir.setAutoRemove(true);
|
|
|
|
qDebug() << "From:" << folder << "To:" << tempDir.path();
|
|
|
|
|
|
|
|
QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
|
|
|
|
qDebug() << tempDir.path();
|
|
|
|
qDebug() << target_dir.path();
|
2023-02-08 08:35:03 +00:00
|
|
|
|
|
|
|
LinkTask lnk_tsk(folder, target_dir.path());
|
|
|
|
lnk_tsk.linkRecursively(true);
|
2023-08-14 17:16:53 +01:00
|
|
|
QObject::connect(&lnk_tsk, &Task::finished,
|
|
|
|
[&] { QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); });
|
2023-02-08 08:35:03 +00:00
|
|
|
lnk_tsk.start();
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
QVERIFY2(QTest::qWaitFor([&]() { return lnk_tsk.isFinished(); }, 100000), "Task didn't finish as it should.");
|
2023-02-07 07:05:06 +00:00
|
|
|
|
|
|
|
auto filter = QDir::Filter::Files | QDir::Filter::Dirs | QDir::Filter::Hidden;
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
for (auto entry : target_dir.entryList(filter)) {
|
2023-02-07 07:05:06 +00:00
|
|
|
qDebug() << entry;
|
|
|
|
QFileInfo entry_lnk_info(target_dir.filePath(entry));
|
2023-02-07 09:56:16 +00:00
|
|
|
if (!entry_lnk_info.isDir())
|
|
|
|
QVERIFY(entry_lnk_info.isSymLink());
|
2023-02-07 07:05:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QFileInfo lnk_info(target_dir.path());
|
|
|
|
QVERIFY(lnk_info.exists());
|
|
|
|
|
|
|
|
QVERIFY(target_dir.entryList(filter).contains(".secret_folder"));
|
|
|
|
target_dir.cd(".secret_folder");
|
|
|
|
QVERIFY(target_dir.entryList(filter).contains(".secret_file.txt"));
|
|
|
|
};
|
|
|
|
|
|
|
|
// first try variant without trailing /
|
|
|
|
QVERIFY(!folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
|
|
|
|
// then variant with trailing /
|
|
|
|
folder.append('/');
|
|
|
|
QVERIFY(folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_link_single_file()
|
|
|
|
{
|
|
|
|
QTemporaryDir tempDir;
|
|
|
|
tempDir.setAutoRemove(true);
|
|
|
|
|
|
|
|
{
|
|
|
|
QString file = QFINDTESTDATA("testdata/FileSystem/test_folder/pack.mcmeta");
|
|
|
|
|
|
|
|
qDebug() << "From:" << file << "To:" << tempDir.path();
|
|
|
|
|
|
|
|
QDir target_dir(FS::PathCombine(tempDir.path(), "pack.mcmeta"));
|
|
|
|
qDebug() << tempDir.path();
|
|
|
|
qDebug() << target_dir.path();
|
2023-02-08 08:35:03 +00:00
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
LinkTask lnk_tsk(file, target_dir.filePath("pack.mcmeta"));
|
|
|
|
QObject::connect(&lnk_tsk, &Task::finished,
|
|
|
|
[&] { QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); });
|
2023-02-08 08:35:03 +00:00
|
|
|
lnk_tsk.start();
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
QVERIFY2(QTest::qWaitFor([&]() { return lnk_tsk.isFinished(); }, 100000), "Task didn't finish as it should.");
|
2023-02-07 07:05:06 +00:00
|
|
|
|
|
|
|
auto filter = QDir::Filter::Files;
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
for (auto entry : target_dir.entryList(filter)) {
|
2023-02-07 07:05:06 +00:00
|
|
|
qDebug() << entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
QFileInfo lnk_info(target_dir.filePath("pack.mcmeta"));
|
|
|
|
QVERIFY(lnk_info.exists());
|
2023-02-07 09:56:16 +00:00
|
|
|
QVERIFY(lnk_info.isSymLink());
|
2023-02-07 07:05:06 +00:00
|
|
|
|
|
|
|
QVERIFY(target_dir.entryList(filter).contains("pack.mcmeta"));
|
|
|
|
}
|
|
|
|
}
|
2023-02-10 02:48:40 +00:00
|
|
|
|
|
|
|
void test_link_with_max_depth()
|
|
|
|
{
|
|
|
|
QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
|
2023-08-14 17:16:53 +01:00
|
|
|
auto f = [&folder]() {
|
2023-02-10 02:48:40 +00:00
|
|
|
QTemporaryDir tempDir;
|
|
|
|
tempDir.setAutoRemove(true);
|
|
|
|
qDebug() << "From:" << folder << "To:" << tempDir.path();
|
|
|
|
|
|
|
|
QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
|
|
|
|
qDebug() << tempDir.path();
|
|
|
|
qDebug() << target_dir.path();
|
|
|
|
|
|
|
|
LinkTask lnk_tsk(folder, target_dir.path());
|
|
|
|
lnk_tsk.linkRecursively(true);
|
|
|
|
lnk_tsk.setMaxDepth(0);
|
2023-08-14 17:16:53 +01:00
|
|
|
QObject::connect(&lnk_tsk, &Task::finished,
|
|
|
|
[&] { QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); });
|
2023-02-10 02:48:40 +00:00
|
|
|
lnk_tsk.start();
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
QVERIFY2(QTest::qWaitFor([&]() { return lnk_tsk.isFinished(); }, 100000), "Task didn't finish as it should.");
|
2023-02-10 02:48:40 +00:00
|
|
|
|
|
|
|
QVERIFY(!QFileInfo(target_dir.path()).isSymLink());
|
|
|
|
|
|
|
|
auto filter = QDir::Filter::Files | QDir::Filter::Dirs | QDir::Filter::Hidden;
|
2023-08-14 17:16:53 +01:00
|
|
|
for (auto entry : target_dir.entryList(filter)) {
|
2023-02-10 02:48:40 +00:00
|
|
|
qDebug() << entry;
|
2023-08-14 17:16:53 +01:00
|
|
|
if (entry == "." || entry == "..")
|
|
|
|
continue;
|
2023-02-10 02:48:40 +00:00
|
|
|
QFileInfo entry_lnk_info(target_dir.filePath(entry));
|
|
|
|
QVERIFY(entry_lnk_info.isSymLink());
|
|
|
|
}
|
|
|
|
|
|
|
|
QFileInfo lnk_info(target_dir.path());
|
|
|
|
QVERIFY(lnk_info.exists());
|
|
|
|
QVERIFY(!lnk_info.isSymLink());
|
|
|
|
|
|
|
|
QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
|
|
|
|
QVERIFY(target_dir.entryList().contains("assets"));
|
|
|
|
};
|
|
|
|
|
|
|
|
// first try variant without trailing /
|
|
|
|
QVERIFY(!folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
|
|
|
|
// then variant with trailing /
|
|
|
|
folder.append('/');
|
|
|
|
QVERIFY(folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_link_with_no_max_depth()
|
|
|
|
{
|
|
|
|
QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
|
2023-08-14 17:16:53 +01:00
|
|
|
auto f = [&folder]() {
|
2023-02-10 02:48:40 +00:00
|
|
|
QTemporaryDir tempDir;
|
|
|
|
tempDir.setAutoRemove(true);
|
|
|
|
qDebug() << "From:" << folder << "To:" << tempDir.path();
|
|
|
|
|
|
|
|
QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
|
|
|
|
qDebug() << tempDir.path();
|
|
|
|
qDebug() << target_dir.path();
|
|
|
|
|
|
|
|
LinkTask lnk_tsk(folder, target_dir.path());
|
|
|
|
lnk_tsk.linkRecursively(true);
|
|
|
|
lnk_tsk.setMaxDepth(-1);
|
2023-08-14 17:16:53 +01:00
|
|
|
QObject::connect(&lnk_tsk, &Task::finished,
|
|
|
|
[&] { QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); });
|
2023-02-10 02:48:40 +00:00
|
|
|
lnk_tsk.start();
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
QVERIFY2(QTest::qWaitFor([&]() { return lnk_tsk.isFinished(); }, 100000), "Task didn't finish as it should.");
|
2023-02-10 02:48:40 +00:00
|
|
|
|
|
|
|
std::function<void(QString)> verify_check = [&](QString check_path) {
|
|
|
|
QDir check_dir(check_path);
|
|
|
|
auto filter = QDir::Filter::Files | QDir::Filter::Dirs | QDir::Filter::Hidden;
|
2023-08-14 17:16:53 +01:00
|
|
|
for (auto entry : check_dir.entryList(filter)) {
|
2023-02-10 02:48:40 +00:00
|
|
|
QFileInfo entry_lnk_info(check_dir.filePath(entry));
|
|
|
|
qDebug() << entry << check_dir.filePath(entry);
|
2023-08-14 17:16:53 +01:00
|
|
|
if (!entry_lnk_info.isDir()) {
|
2023-02-10 02:48:40 +00:00
|
|
|
QVERIFY(entry_lnk_info.isSymLink());
|
|
|
|
} else if (entry != "." && entry != "..") {
|
|
|
|
qDebug() << "Decending tree to verify symlinks:" << check_dir.filePath(entry);
|
|
|
|
verify_check(entry_lnk_info.filePath());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2023-08-14 17:16:53 +01:00
|
|
|
|
2023-02-10 02:48:40 +00:00
|
|
|
verify_check(target_dir.path());
|
|
|
|
|
|
|
|
QFileInfo lnk_info(target_dir.path());
|
|
|
|
QVERIFY(lnk_info.exists());
|
|
|
|
|
|
|
|
QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
|
|
|
|
QVERIFY(target_dir.entryList().contains("assets"));
|
|
|
|
};
|
|
|
|
|
|
|
|
// first try variant without trailing /
|
|
|
|
QVERIFY(!folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
|
|
|
|
// then variant with trailing /
|
|
|
|
folder.append('/');
|
|
|
|
QVERIFY(folder.endsWith('/'));
|
|
|
|
f();
|
|
|
|
}
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
void test_path_depth()
|
|
|
|
{
|
2023-04-01 04:22:07 +01:00
|
|
|
QCOMPARE(FS::pathDepth(""), 0);
|
|
|
|
QCOMPARE(FS::pathDepth("."), 0);
|
|
|
|
QCOMPARE(FS::pathDepth("foo.txt"), 0);
|
|
|
|
QCOMPARE(FS::pathDepth("./foo.txt"), 0);
|
|
|
|
QCOMPARE(FS::pathDepth("./bar/foo.txt"), 1);
|
|
|
|
QCOMPARE(FS::pathDepth("../bar/foo.txt"), 0);
|
|
|
|
QCOMPARE(FS::pathDepth("/bar/foo.txt"), 1);
|
|
|
|
QCOMPARE(FS::pathDepth("baz/bar/foo.txt"), 2);
|
|
|
|
QCOMPARE(FS::pathDepth("/baz/bar/foo.txt"), 2);
|
|
|
|
QCOMPARE(FS::pathDepth("./baz/bar/foo.txt"), 2);
|
|
|
|
QCOMPARE(FS::pathDepth("/baz/../bar/foo.txt"), 1);
|
2023-02-10 02:48:40 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
void test_path_trunc()
|
|
|
|
{
|
2023-04-01 04:22:07 +01:00
|
|
|
QCOMPARE(FS::pathTruncate("", 0), QDir::toNativeSeparators(""));
|
|
|
|
QCOMPARE(FS::pathTruncate("foo.txt", 0), QDir::toNativeSeparators(""));
|
|
|
|
QCOMPARE(FS::pathTruncate("foo.txt", 1), QDir::toNativeSeparators(""));
|
|
|
|
QCOMPARE(FS::pathTruncate("./bar/foo.txt", 0), QDir::toNativeSeparators("./bar"));
|
|
|
|
QCOMPARE(FS::pathTruncate("./bar/foo.txt", 1), QDir::toNativeSeparators("./bar"));
|
|
|
|
QCOMPARE(FS::pathTruncate("/bar/foo.txt", 1), QDir::toNativeSeparators("/bar"));
|
|
|
|
QCOMPARE(FS::pathTruncate("bar/foo.txt", 1), QDir::toNativeSeparators("bar"));
|
|
|
|
QCOMPARE(FS::pathTruncate("baz/bar/foo.txt", 2), QDir::toNativeSeparators("baz/bar"));
|
2023-02-10 06:07:07 +00:00
|
|
|
#if defined(Q_OS_WIN)
|
2023-04-01 04:22:07 +01:00
|
|
|
QCOMPARE(FS::pathTruncate("C:\\bar\\foo.txt", 1), QDir::toNativeSeparators("C:\\bar"));
|
2023-02-10 06:07:07 +00:00
|
|
|
#endif
|
2023-02-10 02:48:40 +00:00
|
|
|
}
|
2013-12-02 10:09:56 +00:00
|
|
|
};
|
|
|
|
|
2015-12-26 01:44:33 +00:00
|
|
|
QTEST_GUILESS_MAIN(FileSystemTest)
|
2013-12-02 10:09:56 +00:00
|
|
|
|
2016-04-14 00:23:54 +01:00
|
|
|
#include "FileSystem_test.moc"
|