Browse Source

Test recursive removal against real disk storage

master
evgeny 3 days ago
parent
commit
b4a9339459
  1. 82
      tools/chatgui/tests/test_member_files_browser.cpp

82
tools/chatgui/tests/test_member_files_browser.cpp

@ -29,6 +29,7 @@
#include <functional>
extern "C" {
#include "member_files/member_files.h"
#include "member_files/storage.h"
#include "mem.h"
#include "debug_config.h"
}
@ -261,6 +262,87 @@ private slots:
requestStarted = {}; transferStarted = {};
}
void recursiveDeletion_data() {
QTest::addColumn<QString>("scenario");
for (const auto* scenario : {"complete", "cancel-scan", "cancel-remove", "changed-file", "new-child", "changed-page"})
QTest::newRow(scenario) << QString::fromLatin1(scenario);
}
void recursiveDeletion() {
QFETCH(QString, scenario);
QTemporaryDir root; QVERIFY(root.isValid());
QString user = root.path() + "/42/22";
QVERIFY(QDir().mkpath(user + "/folder/nested/empty")); QVERIFY(QDir().mkpath(user + "/other"));
auto write = [&](const QString& path, const QByteArray& contents) {
QFile file(user + '/' + path); QVERIFY(file.open(QIODevice::WriteOnly)); QCOMPARE(file.write(contents), qint64(contents.size()));
};
// Длинные имена вынуждают настоящий storage выдавать несколько страниц LIST.
for (int i = 0; i < 40; i++) write("folder/" + QString::number(i) + QString(220, 'x'), "payload");
write("folder/nested/file.txt", "nested"); write("loose.txt", "selected"); write("keep.txt", "unselected");
auto* storage = mf_storage_create(root.path().toUtf8().constData(), 1000000, 200000);
QVERIFY(storage); auto destroy = qScopeGuard([&] { mf_storage_destroy(storage); });
QCOMPARE(mf_storage_initialize(storage), int(MF_OK));
QList<MemberFileEntry> entries;
for (const auto* path : {"folder", "loose.txt", "other"}) {
mf_message q{}, r{}; q.kind = MF_REQUEST; q.command = MF_STAT; q.owner = 22; q.request_id = entries.size() + 1;
strcpy(q.path, path); mf_storage_execute(storage, 42, 22, &q, &r); QCOMPARE(r.status, uint16_t(MF_OK));
entries.append({QString::fromUtf8(path), {}, QByteArray((const char*)r.version, 16), r.type == MF_DIRECTORY});
}
MemberFileBatch batch(42, 33, 22, MemberFileBatch::Remove, nullptr);
bool done = false, success = false, injected = false; QString summary, changed;
int pages = 0, removed = 0, requests = 0, rootStats = 0;
batch.progress = [](const QString&, int) {};
batch.finished = [&](bool ok, const QString& status, const QStringList&) { done = true; success = ok; summary = status; };
auto reset = qScopeGuard([] { requestStarted = {}; });
requestStarted = [&](mf_gui_request request) {
requests++;
QTimer::singleShot(0, &batch, [&, request] {
const auto& q = request.message; QString path = QString::fromUtf8(q.path);
if (q.command == MF_STAT && path == "folder") {
rootStats++;
if (scenario == "new-child" && rootStats == 2) { write("folder/arrived.txt", "new arrival"); injected = true; }
}
if (q.command == MF_LIST) {
QCOMPARE(removed, 0); pages++;
QVERIFY(!mf_zero(q.version, 16));
if (scenario == "changed-page" && q.cursor) { write("folder/arrived.txt", "new arrival"); injected = true; }
}
if (q.command == MF_REMOVE_PATH) {
QVERIFY(pages >= 4); // folder: две страницы, nested и empty: по одной.
if (scenario == "changed-file" && !injected) { changed = path; write(path, "changed contents"); injected = true; }
}
mf_message response{}; mf_storage_execute(storage, request.group, request.message.owner, &q, &response);
if (q.command == MF_REMOVE_PATH && !response.status) {
removed++; QVERIFY(!QFileInfo::exists(user + '/' + path));
}
if (scenario == "cancel-scan" && response.more) {
batch.cancel(); QVERIFY(!batch.response(response)); return;
}
QVERIFY(batch.response(response));
if (scenario == "cancel-remove" && removed == 1) { batch.cancel(); QVERIFY(!batch.response(response)); }
});
};
batch.start(entries); QTRY_VERIFY(done);
int stopped = requests; QCoreApplication::processEvents(); QCOMPARE(requests, stopped);
QFile keep(user + "/keep.txt"); QVERIFY(keep.open(QIODevice::ReadOnly)); QCOMPARE(keep.readAll(), QByteArray("unselected"));
if (scenario == "complete") {
QVERIFY2(success, qPrintable(summary)); QCOMPARE(removed, 46);
QVERIFY(!QFileInfo::exists(user + "/folder")); QVERIFY(!QFileInfo::exists(user + "/other"));
QVERIFY(!QFileInfo::exists(user + "/loose.txt")); QVERIFY(summary.contains("Completed: 46"));
} else {
QVERIFY(!success); QVERIFY(QFileInfo::exists(user + "/folder"));
if (scenario == "cancel-scan" || scenario == "changed-page" || scenario == "changed-file") QCOMPARE(removed, 0);
if (scenario == "cancel-remove") { QCOMPARE(removed, 1); QVERIFY(summary.contains("Completed: 1")); }
if (scenario.startsWith("cancel-")) QVERIFY(summary.contains("Deletion cancelled"));
if (scenario == "changed-file") { QVERIFY(injected); QVERIFY(QFileInfo::exists(user + '/' + changed)); }
if (scenario == "new-child") {
QVERIFY(injected); QVERIFY(QFileInfo::exists(user + "/folder/arrived.txt"));
QVERIFY(summary.contains(QString::fromUtf8(mf_status_text(MF_DIRECTORY_NOT_EMPTY))));
}
if (scenario == "changed-page") QVERIFY(summary.contains(QString::fromUtf8(mf_status_text(MF_STALE))));
}
}
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