Test range selection and recursive file tree transfers
This commit is contained in:
1 parent
400b9fa93c
commit
8785fc358a
1 file changed
+102
@@ -25,6 +25,7 @@
|
||||
#include <QMouseEvent>
|
||||
#include <QScopeGuard>
|
||||
#include <QChildEvent>
|
||||
#include <QMenu>
|
||||
#include <functional>
|
||||
extern "C" {
|
||||
#include "member_files/member_files.h"
|
||||
@@ -104,6 +105,107 @@ private slots:
|
||||
}
|
||||
void init() { transfers.clear(); cancelled.clear(); ready = true; transferStarted = {}; requestStarted = {}; }
|
||||
|
||||
void selectionAndRecursiveClipboard() {
|
||||
QTemporaryDir cache; QVERIFY(cache.isValid()); QByteArray oldCache = qgetenv("XDG_CACHE_HOME");
|
||||
qputenv("XDG_CACHE_HOME", cache.path().toUtf8());
|
||||
auto restore = qScopeGuard([oldCache] { qputenv("XDG_CACHE_HOME", oldCache); QApplication::clipboard()->clear(); });
|
||||
sqlite3* sql = nullptr; QCOMPARE(sqlite3_open(":memory:", &sql), SQLITE_OK);
|
||||
QCOMPARE(sqlite3_exec(sql, "CREATE TABLE accounts(node_id INTEGER,display_name TEXT);"
|
||||
"INSERT INTO accounts VALUES(22,'Me'),(33,'Server');"
|
||||
"CREATE TABLE peers_42(node_id INTEGER,adm_tags TEXT,adm_tags_sig BLOB,deleted INTEGER,source INTEGER);"
|
||||
"INSERT INTO peers_42 VALUES(22,'{}',NULL,0,0),(33,'{\"storage\":\"yes\"}',zeroblob(64),0,0);",
|
||||
nullptr, nullptr, nullptr), SQLITE_OK);
|
||||
DbManager db; db.setDb(sql); db.setMyNodeId(22);
|
||||
{
|
||||
MemberFileBrowser browser(&db); browser.setChannel("42", 22); browser.show(); browser.activateWindow();
|
||||
auto* tree = browser.findChild<QTreeWidget*>();
|
||||
for (const auto& name : {"folder", "loose.txt", "skip.txt", "last.txt"}) {
|
||||
auto* item = new QTreeWidgetItem(tree, {name}); item->setData(0, Qt::UserRole, name);
|
||||
item->setData(0, Qt::UserRole + 1, QString(name) == "folder" ? MF_DIRECTORY : MF_FILE);
|
||||
item->setData(0, Qt::UserRole + 2, QByteArray(16, '\7'));
|
||||
}
|
||||
tree->setFocus(); QTRY_VERIFY(tree->hasFocus());
|
||||
auto click = [tree](int row, Qt::KeyboardModifiers modifiers) {
|
||||
QTest::mouseClick(tree->viewport(), Qt::LeftButton, modifiers, tree->visualItemRect(tree->topLevelItem(row)).center());
|
||||
};
|
||||
click(0, Qt::NoModifier); click(2, Qt::ShiftModifier); QCOMPARE(tree->selectedItems().size(), 3);
|
||||
click(1, Qt::ControlModifier); QCOMPARE(tree->selectedItems().size(), 2);
|
||||
QTest::keyClick(tree, Qt::Key_A, Qt::ControlModifier); QCOMPARE(tree->selectedItems().size(), 4);
|
||||
click(0, Qt::NoModifier); click(1, Qt::ShiftModifier); QCOMPARE(tree->selectedItems().size(), 2);
|
||||
QTimer::singleShot(0, [] { if (auto* menu = qobject_cast<QMenu*>(QApplication::activePopupWidget())) menu->close(); });
|
||||
tree->customContextMenuRequested(tree->visualItemRect(tree->topLevelItem(1)).center());
|
||||
QCOMPARE(tree->selectedItems().size(), 2);
|
||||
QMap<QString, QStringList> directories{{"folder", {"empty", "nested", "inside.txt"}}, {"folder/empty", {}},
|
||||
{"folder/nested", {"deep.txt"}}};
|
||||
int pages = 0, verified = 0;
|
||||
requestStarted = [&](mf_gui_request request) {
|
||||
QTimer::singleShot(0, &browser, [&, request] {
|
||||
mf_message r = request.message; r.kind = MF_RESPONSE; r.status = MF_OK; r.data_len = 0;
|
||||
QString path = QString::fromUtf8(r.path); r.type = directories.contains(path) ? MF_DIRECTORY : MF_FILE;
|
||||
memset(r.version, 7, 16);
|
||||
if (r.command == MF_LIST) {
|
||||
pages++; auto names = directories.value(path);
|
||||
if (r.cursor < quint64(names.size())) {
|
||||
QByteArray name = names[int(r.cursor)].toUtf8(); QString child = path + '/' + QString::fromUtf8(name);
|
||||
r.data[0] = uint8_t(name.size()); r.data[2] = directories.contains(child) ? MF_DIRECTORY : MF_FILE;
|
||||
memset(r.data + 19, 7, 16); memcpy(r.data + MF_ENTRY_HEADER, name.constData(), name.size());
|
||||
r.data_len = MF_ENTRY_HEADER + name.size(); r.cursor++; r.more = r.cursor < quint64(names.size());
|
||||
}
|
||||
} else if (r.command == MF_STAT) verified++;
|
||||
else return;
|
||||
uint8_t bytes[16 + MF_WIRE_MAX]; mf_put64(bytes, request.group); mf_put64(bytes + 8, request.server);
|
||||
int size = mf_encode(&r, bytes + 16, MF_WIRE_MAX); QVERIFY(size > 0); browser.onResponse(bytes, size + 16);
|
||||
});
|
||||
};
|
||||
transferStarted = [&](mf_transfer_request request) {
|
||||
QTimer::singleShot(0, &browser, [&, request] {
|
||||
QFile file(QString::fromUtf8(request.local)); QVERIFY(file.open(QIODevice::WriteOnly));
|
||||
QByteArray bytes(request.remote); QCOMPARE(file.write(bytes), qint64(bytes.size())); file.close(); complete(browser, request);
|
||||
});
|
||||
};
|
||||
auto* copy = browser.findChild<QAction*>("memberFilesCopy"); copy->trigger();
|
||||
QTRY_VERIFY(copy->isEnabled()); QCOMPARE(pages, 5); QCOMPARE(verified, 3); QCOMPARE(transfers.size(), 3);
|
||||
auto urls = QApplication::clipboard()->mimeData()->urls(); QCOMPARE(urls.size(), 2);
|
||||
QString folder = urls[0].toLocalFile(); QVERIFY(QFileInfo(folder + "/empty").isDir());
|
||||
QFile deep(folder + "/nested/deep.txt"); QVERIFY(deep.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(deep.readAll(), QByteArray("folder/nested/deep.txt"));
|
||||
QVERIFY(QFileInfo(urls[1].toLocalFile()).isFile());
|
||||
requestStarted = {}; transferStarted = {};
|
||||
}
|
||||
db.setDb(nullptr); QCOMPARE(sqlite3_close(sql), SQLITE_OK);
|
||||
}
|
||||
|
||||
void recursiveUploadAndPreflight() {
|
||||
QTemporaryDir root; QVERIFY(root.isValid()); QVERIFY(QDir(root.path()).mkpath("folder/empty"));
|
||||
QVERIFY(QDir(root.path()).mkpath("folder/nested"));
|
||||
QString source = root.filePath("folder/nested/file.txt");
|
||||
{ QFile file(source); QVERIFY(file.open(QIODevice::WriteOnly)); QCOMPARE(file.write("data"), 4LL); }
|
||||
MemberFileBatch batch(42, 33, 22, MemberFileBatch::Upload, nullptr);
|
||||
bool done = false, success = false; QString summary; QStringList created;
|
||||
batch.progress = [](const QString&, int) {};
|
||||
batch.conflict = [](const QString&, bool) { return int(QMessageBox::Cancel); };
|
||||
batch.finished = [&](bool ok, const QString& status, const QStringList&) { done = true; success = ok; summary = status; };
|
||||
requestStarted = [&](mf_gui_request request) {
|
||||
QTimer::singleShot(0, &batch, [&, request] {
|
||||
mf_message response = request.message; response.kind = MF_RESPONSE;
|
||||
response.status = response.command == MF_STAT ? MF_NOT_FOUND : MF_OK;
|
||||
if (response.command == MF_MKDIR) created.append(QString::fromUtf8(response.path));
|
||||
QVERIFY(batch.response(response));
|
||||
});
|
||||
};
|
||||
transferStarted = [&](mf_transfer_request request) {
|
||||
QCOMPARE(QString::fromUtf8(request.remote), QString("destination/folder/nested/file.txt"));
|
||||
QVERIFY(created.contains("destination/folder/nested")); QCOMPARE(QString::fromUtf8(request.local), source);
|
||||
QTimer::singleShot(0, &batch, [&, request] {
|
||||
uint8_t bytes[51]{}; mf_put64(bytes, request.id); bytes[50] = 2; QVERIFY(batch.transfer(bytes, sizeof(bytes)));
|
||||
});
|
||||
};
|
||||
batch.upload({root.filePath("folder"), source}, "destination");
|
||||
QTRY_VERIFY(done); QVERIFY2(success, qPrintable(summary)); QCOMPARE(transfers.size(), 1);
|
||||
QVERIFY(created.contains("destination/folder/empty")); QCOMPARE(created.size(), 3);
|
||||
requestStarted = {}; transferStarted = {};
|
||||
}
|
||||
|
||||
void deleteAndParentShortcuts() {
|
||||
sqlite3* sql = nullptr; QCOMPARE(sqlite3_open(":memory:", &sql), SQLITE_OK);
|
||||
QCOMPARE(sqlite3_exec(sql, "CREATE TABLE accounts(node_id INTEGER,display_name TEXT);"
|
||||
|
||||
Reference in new issue
Block a user