Browse Source

Test range selection and recursive file tree transfers

master
evgeny 3 days ago
parent
commit
8785fc358a
  1. 102
      tools/chatgui/tests/test_member_files_browser.cpp

102
tools/chatgui/tests/test_member_files_browser.cpp

@ -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);"

Loading…
Cancel
Save