Verify file command success against the real storage service

This commit is contained in:
evgeny committed 2026-10-28 00:58:59 +01:00
1 parent 83f8b0cbe2
commit ba44e243a9
1 file changed
+81 -2
@@ -13,6 +13,7 @@
#include <QScopeGuard>
extern "C" {
#include "utun_instance.h"
#include "chat/chat_core.h"
#include "member_files/member_files.h"
#include "debug_config.h"
#include "mem.h"
@@ -80,7 +81,8 @@ private slots:
gui_bridge_set_member_files_response_cb(nullptr); gui_bridge_set_member_files_transfer_cb(nullptr);
}
void cleanup() {
activeBatch = nullptr; activeBrowser = nullptr; responses.clear(); transfers.clear();
activeBatch = nullptr; activeBrowser = nullptr;
QCoreApplication::processEvents(); responses.clear(); transfers.clear();
#ifdef UTUN_TEST_FILE_ALLOC_FAILURES
failAllocation = 0;
#endif
@@ -320,7 +322,7 @@ private slots:
#ifdef UTUN_TEST_FILE_ALLOC_FAILURES
QCOMPARE(failAllocation, 0);
#endif
core.attach(); QVERIFY(download->isEnabled());
core.attach(); item->setSelected(false); item->setSelected(true); QVERIFY(download->isEnabled());
QTimer::singleShot(0, [&] {
auto* dialog = qobject_cast<QFileDialog*>(QApplication::activeModalWidget());
if (dialog) { dialog->selectFile(destination); QMetaObject::invokeMethod(dialog, "accept"); }
@@ -331,6 +333,83 @@ private slots:
}
QCOMPARE(u_get_allocated_count(), before);
}
void realStorageRoundTrip() {
const size_t before = u_get_allocated_count();
{
QTemporaryDir root; QVERIFY(root.isValid());
UASYNC* ua = uasync_create(); QVERIFY(ua); UTUN_INSTANCE* instance = nullptr; QTimer poll;
const auto cleanup = qScopeGuard([&] {
activeBatch = nullptr; poll.stop(); gui_bridge_set_inst(nullptr); gui_bridge_set_uasync(nullptr);
uasync_mark_stopped(ua);
if (instance) utun_instance_destroy(instance);
uasync_destroy(ua, 0); QCoreApplication::processEvents();
});
const QByteArray config = "[global]\nauto_sockets=no\ntun_enabled=no\n"
"my_private_key=704f2e012c8fa8768130cb0f988a997dccb628372bc5ceccacc78dcbfec5916f\n"
"my_public_key=b3193173def895bd0fcea6f86af077c7d77216f10395275f627ac18242ec0f01\n"
"[chatserver]\ngroup_autoconnect=0\nstorage_autoload=0\nmember_files_enabled=1\n"
"local_invites_enabled=0\nlocal_broadcasts_enabled=0\nmember_files_path=" + root.path().toUtf8() +
"/storage\n[ntp]\nenabled=no\n";
instance = utun_instance_create_from_str(ua, config.constData()); QVERIFY(instance);
QCOMPARE(utun_core_start(instance), 0); QCOMPARE(chat_service_start(instance), 0);
const uint64_t group = chat_core_create_channel_auto(instance, "Files"); QVERIFY(group);
const QByteArray channel = QByteArray::number(group); const uint64_t node = instance->node_id;
auto* tags = chat_member_tags_load(instance, channel.constData(), node); QVERIFY(tags);
const int set = chat_member_tags_set(tags, "storage", "yes");
const int commit = set ? set : chat_member_tags_commit(instance, tags); chat_member_tags_free(tags); QCOMPARE(commit, 0);
chat_event_set_handler(instance, [](UTUN_INSTANCE*, int event, const uint8_t* data, int size) {
gui_bridge_post(event, data, size);
});
uasync_mark_running(ua); gui_bridge_set_uasync(ua); gui_bridge_set_inst(instance);
connect(&poll, &QTimer::timeout, this, [ua] { uasync_poll(ua, 0); }); poll.start(1);
// Дождаться ответа готового storage, не подменяя асинхронный старт его worker.
bool ready = false;
for (int attempt = 0; attempt < 20 && !ready; attempt++) {
mf_message q{}; q.kind = MF_REQUEST; q.command = MF_QUOTA; q.request_id = 100 + attempt; q.owner = node;
const auto count = responses.size(); QCOMPARE(gui_bridge_member_files_request(group, node, &q), 0);
QTRY_COMPARE_WITH_TIMEOUT(responses.size(), count + 1, 3000); mf_message r{};
const auto& bytes = responses.last();
QCOMPARE(mf_decode((const uint8_t*)bytes.constData() + 16, bytes.size() - 16, &r), 0);
QVERIFY(r.status == MF_OK || r.status == MF_BUSY); ready = r.status == MF_OK;
}
QVERIFY(ready);
const QByteArray payload(20000, 'f'); const QString source = root.filePath("source.txt");
{ QFile file(source); QVERIFY(file.open(QIODevice::WriteOnly)); QCOMPARE(file.write(payload), qint64(payload.size())); }
int completed = 0; bool success = false; QString summary;
auto finished = [&](bool ok, const QString& text, const QStringList&) { completed++; success = ok; summary = text; };
const QString stored = root.filePath("storage/" + QString::number(group) + '/' + QString::number(node) + "/source.txt");
{
MemberFileBatch batch(group, node, node, MemberFileBatch::Upload, nullptr); activeBatch = &batch;
batch.progress = [](const QString&, int) {}; batch.finished = finished;
batch.upload({source}, {}); QTRY_COMPARE_WITH_TIMEOUT(completed, 1, 5000); QVERIFY2(success, qPrintable(summary));
}
{ QFile file(stored); QVERIFY(file.open(QIODevice::ReadOnly)); QCOMPARE(file.readAll(), payload); }
mf_message q{}; q.kind = MF_REQUEST; q.command = MF_STAT; q.request_id = 1000; q.owner = node; strcpy(q.path, "source.txt");
const auto count = responses.size(); QCOMPARE(gui_bridge_member_files_request(group, node, &q), 0);
QTRY_COMPARE_WITH_TIMEOUT(responses.size(), count + 1, 3000); mf_message info{};
const auto bytes = responses.last();
QCOMPARE(mf_decode((const uint8_t*)bytes.constData() + 16, bytes.size() - 16, &info), 0); QCOMPARE(info.status, uint16_t(MF_OK));
const QString destination = root.filePath("download.txt");
const QByteArray version((const char*)info.version, 16); completed = 0; success = false;
{
MemberFileBatch batch(group, node, node, MemberFileBatch::Download, nullptr); activeBatch = &batch;
batch.progress = [](const QString&, int) {}; batch.finished = finished;
batch.start({{"source.txt", destination, version, false}});
QTRY_COMPARE_WITH_TIMEOUT(completed, 1, 5000); QVERIFY2(success, qPrintable(summary));
}
{ QFile file(destination); QVERIFY(file.open(QIODevice::ReadOnly)); QCOMPARE(file.readAll(), payload); }
completed = 0; success = false;
{
MemberFileBatch batch(group, node, node, MemberFileBatch::Remove, nullptr); activeBatch = &batch;
batch.progress = [](const QString&, int) {}; batch.finished = finished;
batch.start({{"source.txt", {}, version, false}});
QTRY_COMPARE_WITH_TIMEOUT(completed, 1, 5000); QVERIFY2(success, qPrintable(summary));
}
QVERIFY(!QFile::exists(stored)); QVERIFY(QFile::exists(source)); QVERIFY(QFile::exists(destination));
}
QCOMPARE(u_get_allocated_count(), before);
}
};
QTEST_MAIN(FileLifecycleTest)