From 004ebf8d5ba095ca1b11e30d86cedc2ff8c0cfe7 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 18 Jul 2021 18:22:28 +0200 Subject: Room::postFile(): adjust to the changed RoomMessageEvent API 9a5fa623 dropped one of RoomMessageEvent constructors for Qt 6 in order to address #483 - breaking the build with Qt 6 along the way, as Room::postFile() relied on that constructor. This commit changes Room::postFile() in turn, deprecating the current signature and adding a new one that accepts an EventContent object rather than a path to a file. In order to achieve that, FileInfo and ImageInfo classes have gained new constructors that accept QFileInfo instead of the legacy series of parameters, streamlining usage of EventContent structures. --- quotest/quotest.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'quotest/quotest.cpp') diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp index a0914c72..5646d54d 100644 --- a/quotest/quotest.cpp +++ b/quotest/quotest.cpp @@ -397,15 +397,16 @@ TEST_IMPL(sendFile) } tf->write("Test"); tf->close(); + QFileInfo tfi { *tf }; // QFileInfo::fileName brings only the file name; QFile::fileName brings // the full path - const auto tfName = QFileInfo(*tf).fileName(); + const auto tfName = tfi.fileName(); clog << "Sending file " << tfName.toStdString() << endl; - const auto txnId = - targetRoom->postFile("Test file", QUrl::fromLocalFile(tf->fileName())); + const auto txnId = targetRoom->postFile( + "Test file", new EventContent::FileContent(tfi)); if (!validatePendingEvent(txnId)) { clog << "Invalid pending event right after submitting" << endl; - delete tf; + tf->deleteLater(); FAIL_TEST(); } -- cgit v1.2.3 From 7ee1681d7640b7e7683f7bb40bf768704a48832c Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Fri, 30 Jul 2021 08:22:13 +0200 Subject: Clean up after the previous commit RoomAliasesEvent is no more even registered (meaning that the library will load m.room.aliases as unknown state events); quotest code updated to use historyEdge() instead of timelineEdge(). --- quotest/quotest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'quotest/quotest.cpp') diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp index 5646d54d..ec7d4dcb 100644 --- a/quotest/quotest.cpp +++ b/quotest/quotest.cpp @@ -557,7 +557,7 @@ bool TestSuite::checkRedactionOutcome(const QByteArray& thisTest, // redacted at the next sync, or the nearest sync completes with // the unredacted event but the next one brings redaction. auto it = targetRoom->findInTimeline(evtIdToRedact); - if (it == targetRoom->timelineEdge()) + if (it == targetRoom->historyEdge()) return false; // Waiting for the next sync if ((*it)->isRedacted()) { -- cgit v1.2.3 From 693b5da2920f173a9e3f723b845d35a7b4aa9823 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 12 Sep 2021 04:35:43 +0200 Subject: Add a download test to quotest --- quotest/quotest.cpp | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) (limited to 'quotest/quotest.cpp') diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp index ec7d4dcb..3f886676 100644 --- a/quotest/quotest.cpp +++ b/quotest/quotest.cpp @@ -5,6 +5,7 @@ #include "room.h" #include "user.h" #include "uriresolver.h" +#include "networkaccessmanager.h" #include "csapi/joining.h" #include "csapi/leaving.h" @@ -20,6 +21,8 @@ #include #include #include +#include +#include #include #include @@ -435,6 +438,27 @@ TEST_IMPL(sendFile) return false; } +bool testDownload(const QUrl& url) +{ + // Move out actual test from the multithreaded code + // to help debugging + auto results = + QtConcurrent::blockingMapped(QVector { 1, 2, 3 }, [url](int) { + QEventLoop el; + auto reply = + NetworkAccessManager::instance()->get(QNetworkRequest(url)); + QObject::connect( + reply, &QNetworkReply::finished, &el, [&el] { el.exit(); }, + Qt::QueuedConnection); + el.exec(); + return reply->error(); + }); + return std::all_of(results.cbegin(), results.cend(), + [](QNetworkReply::NetworkError ne) { + return ne == QNetworkReply::NoError; + }); +} + bool TestSuite::checkFileSendingOutcome(const TestToken& thisTest, const QString& txnId, const QString& fileName) @@ -465,14 +489,15 @@ bool TestSuite::checkFileSendingOutcome(const TestToken& thisTest, return visit( *evt, [&](const RoomMessageEvent& e) { - // TODO: actually try to download it to check, e.g., #366 - // (and #368 would help to test against bad file names). + // TODO: check #366 once #368 is implemented FINISH_TEST( !e.id().isEmpty() - && pendingEvents[size_t(pendingIdx)]->transactionId() - == txnId - && e.hasFileContent() - && e.content()->fileInfo()->originalName == fileName); + && pendingEvents[size_t(pendingIdx)]->transactionId() + == txnId + && e.hasFileContent() + && e.content()->fileInfo()->originalName == fileName + && testDownload(targetRoom->connection()->makeMediaUrl( + e.content()->fileInfo()->url))); }, [this, thisTest](const RoomEvent&) { FAIL_TEST(); }); }); -- cgit v1.2.3 From 167509514587aa22d837b42a8d30d7c1128e0a45 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 12 Sep 2021 04:52:41 +0200 Subject: Fix building with older Qt --- quotest/quotest.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'quotest/quotest.cpp') diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp index 3f886676..31a0b6d6 100644 --- a/quotest/quotest.cpp +++ b/quotest/quotest.cpp @@ -438,21 +438,30 @@ TEST_IMPL(sendFile) return false; } +// Can be replaced with a lambda once QtConcurrent is able to resolve return +// types from lambda invocations (Qt 6 can, not sure about earlier) +struct DownloadRunner { + QUrl url; + + using result_type = QNetworkReply::NetworkError; + + QNetworkReply::NetworkError operator()(int) const { + QEventLoop el; + auto reply = NetworkAccessManager::instance()->get(QNetworkRequest(url)); + QObject::connect( + reply, &QNetworkReply::finished, &el, [&el] { el.exit(); }, + Qt::QueuedConnection); + el.exec(); + return reply->error(); + } +}; + bool testDownload(const QUrl& url) { // Move out actual test from the multithreaded code // to help debugging - auto results = - QtConcurrent::blockingMapped(QVector { 1, 2, 3 }, [url](int) { - QEventLoop el; - auto reply = - NetworkAccessManager::instance()->get(QNetworkRequest(url)); - QObject::connect( - reply, &QNetworkReply::finished, &el, [&el] { el.exit(); }, - Qt::QueuedConnection); - el.exec(); - return reply->error(); - }); + auto results = QtConcurrent::blockingMapped(QVector { 1, 2, 3 }, + DownloadRunner { url }); return std::all_of(results.cbegin(), results.cend(), [](QNetworkReply::NetworkError ne) { return ne == QNetworkReply::NoError; -- cgit v1.2.3 From bcaab611840a0a2ad284e6f1e7c2f0b4de10222d Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 12 Sep 2021 05:22:53 +0200 Subject: Fix a memory leak in DownloadRunner --- quotest/quotest.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'quotest/quotest.cpp') diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp index 31a0b6d6..4142c718 100644 --- a/quotest/quotest.cpp +++ b/quotest/quotest.cpp @@ -445,11 +445,14 @@ struct DownloadRunner { using result_type = QNetworkReply::NetworkError; - QNetworkReply::NetworkError operator()(int) const { + QNetworkReply::NetworkError operator()(int) const + { QEventLoop el; - auto reply = NetworkAccessManager::instance()->get(QNetworkRequest(url)); + QScopedPointer reply { + NetworkAccessManager::instance()->get(QNetworkRequest(url)) + }; QObject::connect( - reply, &QNetworkReply::finished, &el, [&el] { el.exit(); }, + reply.data(), &QNetworkReply::finished, &el, [&el] { el.exit(); }, Qt::QueuedConnection); el.exec(); return reply->error(); -- cgit v1.2.3 From 9f43d34c590a825504b72be7f6b238d0ff2c915a Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 12 Sep 2021 04:39:44 +0200 Subject: Use C++ instead of commenting --- quotest/quotest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'quotest/quotest.cpp') diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp index 4142c718..3a77eb01 100644 --- a/quotest/quotest.cpp +++ b/quotest/quotest.cpp @@ -51,7 +51,7 @@ private: QByteArrayList running {}, succeeded {}, failed {}; }; -using TestToken = QByteArray; // return value of QMetaMethod::name +using TestToken = decltype(std::declval().name()); Q_DECLARE_METATYPE(TestToken) // For now, the token itself is the test name but that may change. -- cgit v1.2.3 From 062d534a0024959117e310f8c2a964434acb9fa0 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 4 Oct 2021 09:53:33 +0200 Subject: Add tests for prettyPrint() --- quotest/quotest.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'quotest/quotest.cpp') diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp index 3a77eb01..44d82adf 100644 --- a/quotest/quotest.cpp +++ b/quotest/quotest.cpp @@ -108,6 +108,7 @@ private slots: TEST_DECL(addAndRemoveTag) TEST_DECL(markDirectChat) TEST_DECL(visitResources) + TEST_DECL(prettyPrintTests) // Add more tests above here public: @@ -140,7 +141,7 @@ private: // connectUntil() to break the QMetaObject::Connection upon finishing the test // item. #define FINISH_TEST(Condition) \ - return (finishTest(thisTest, Condition, __FILE__, __LINE__), true) + return (finishTest(thisTest, (Condition), __FILE__, __LINE__), true) #define FAIL_TEST() FINISH_TEST(false) @@ -824,6 +825,52 @@ TEST_IMPL(visitResources) FINISH_TEST(true); } +bool checkPrettyPrint( + std::initializer_list> tests) +{ + bool result = true; + for (const auto& [test, etalon] : tests) { + const auto is = prettyPrint(test).toStdString(); + const auto shouldBe = std::string("") + + etalon + ""; + if (is == shouldBe) + continue; + clog << is << " != " << shouldBe << endl; + result = false; + } + return result; +} + +TEST_IMPL(prettyPrintTests) +{ + const bool prettyPrintTestResult = checkPrettyPrint( + { { "https://www.matrix.org", + R"(https://www.matrix.org)" }, +// { "www.matrix.org", // Doesn't work yet +// R"(www.matrix.org)" }, + { "smb://somewhere/file", "smb://somewhere/file" }, // Disallowed scheme + { "https:/something", "https:/something" }, // Malformed URL + { "https://matrix.to/#/!roomid:example.org", + R"(https://matrix.to/#/!roomid:example.org)" }, + { "https://matrix.to/#/@user_id:example.org", + R"(https://matrix.to/#/@user_id:example.org)" }, + { "https://matrix.to/#/#roomalias:example.org", + R"(https://matrix.to/#/#roomalias:example.org)" }, + { "https://matrix.to/#/##ircroomalias:example.org", + R"(https://matrix.to/#/##ircroomalias:example.org)" }, + { "me@example.org", + R"(me@example.org)" }, + { "mailto:me@example.org", + R"(mailto:me@example.org)" }, + { "!room_id:example.org", + R"(!room_id:example.org)" }, + { "@user_id:example.org", + R"(@user_id:example.org)" }, + { "#room_alias:example.org", + R"(#room_alias:example.org)" } }); + FINISH_TEST(prettyPrintTestResult); +} + void TestManager::conclude() { // Clean up the room (best effort) -- cgit v1.2.3 From 7b516cdf0b987e542b1e4cd4556ecb2bfbde3ff9 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 5 Oct 2021 03:52:19 +0200 Subject: Quotest: return non-zero when things go really wrong ...such as stuck login or failure to join the room. Closes #496. --- quotest/quotest.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'quotest/quotest.cpp') diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp index 44d82adf..d006c7fb 100644 --- a/quotest/quotest.cpp +++ b/quotest/quotest.cpp @@ -245,7 +245,7 @@ void TestManager::setupAndRun() clog << "Sync " << ++i << " complete" << endl; if (auto* r = testSuite->room()) { clog << "Test room timeline size = " << r->timelineSize(); - if (r->pendingEvents().empty()) + if (!r->pendingEvents().empty()) clog << ", pending size = " << r->pendingEvents().size(); clog << endl; } @@ -939,10 +939,22 @@ void TestManager::conclude() void TestManager::finalize() { + if (!c->isUsable() || !c->isLoggedIn()) { + clog << "No usable connection reached" << endl; + QCoreApplication::exit(-2); + return; // NB: QCoreApplication::exit() does return to the caller + } clog << "Logging out" << endl; c->logout(); - connect(c, &Connection::loggedOut, this, - [this] { QCoreApplication::exit(failed.size() + running.size()); }, + connect( + c, &Connection::loggedOut, this, + [this] { + QCoreApplication::exit(!testSuite ? -3 + : succeeded.empty() && failed.empty() + && running.empty() + ? -4 + : failed.size() + running.size()); + }, Qt::QueuedConnection); } -- cgit v1.2.3 From ae0ad49f36e8ba5983839581302ed16ddbd75d5f Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 2 Dec 2021 14:04:49 +0100 Subject: visit(Event, ...) -> switchOnType() It has not much to do with the Visitor design pattern; also, std::visit() has different conventions on the order of parameters. --- quotest/quotest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'quotest/quotest.cpp') diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp index d006c7fb..764d5dfd 100644 --- a/quotest/quotest.cpp +++ b/quotest/quotest.cpp @@ -498,8 +498,8 @@ bool TestSuite::checkFileSendingOutcome(const TestToken& thisTest, clog << "File event " << txnId.toStdString() << " arrived in the timeline" << endl; - // This part tests visit() - return visit( + // This part tests switchOnType() + return switchOnType( *evt, [&](const RoomMessageEvent& e) { // TODO: check #366 once #368 is implemented -- cgit v1.2.3 From e5256e0b1e4c43ce96d99d1b82ca5d98a1baded6 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Fri, 17 Dec 2021 08:07:07 +0100 Subject: RoomMemberEvent: fix an off-by-one error Also: extended quotest to cover member renames, not just user profile renames. --- quotest/quotest.cpp | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'quotest/quotest.cpp') diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp index 764d5dfd..8703efb2 100644 --- a/quotest/quotest.cpp +++ b/quotest/quotest.cpp @@ -214,6 +214,7 @@ TestManager::TestManager(int& argc, char** argv) // Big countdown watchdog QTimer::singleShot(180000, this, [this] { + clog << "Time is up, stopping the session"; if (testSuite) conclude(); else @@ -537,14 +538,32 @@ TEST_IMPL(setTopic) TEST_IMPL(changeName) { - auto* const localUser = connection()->user(); - const auto& newName = connection()->generateTxnId(); // See setTopic() - clog << "Renaming the user to " << newName.toStdString() << endl; - localUser->rename(newName); - connectUntil(localUser, &User::defaultNameChanged, this, - [this, thisTest, localUser, newName] { - FINISH_TEST(localUser->name() == newName); - }); + connectSingleShot(targetRoom, &Room::allMembersLoaded, this, [this, thisTest] { + auto* const localUser = connection()->user(); + const auto& newName = connection()->generateTxnId(); // See setTopic() + clog << "Renaming the user to " << newName.toStdString() + << " in the target room" << endl; + localUser->rename(newName, targetRoom); + connectUntil(targetRoom, &Room::memberRenamed, this, + [this, thisTest, localUser, newName](const User* u) { + if (localUser != u) + return false; + if (localUser->name(targetRoom) != newName) + FAIL_TEST(); + + clog + << "Member rename successful, renaming the account" + << endl; + const auto newN = newName.mid(0, 5); + localUser->rename(newN); + connectUntil(localUser, &User::defaultNameChanged, + this, [this, thisTest, localUser, newN] { + targetRoom->localUser()->rename({}); + FINISH_TEST(localUser->name() == newN); + }); + return true; + }); + }); return false; } -- cgit v1.2.3 From 24a562cc64e8fac6c55108ae2b7b6997ecdd2010 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 19 Dec 2021 10:43:33 +0100 Subject: Quotest: add a missing \n in the output --- quotest/quotest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'quotest/quotest.cpp') diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp index 8703efb2..7bd9c5c3 100644 --- a/quotest/quotest.cpp +++ b/quotest/quotest.cpp @@ -214,7 +214,7 @@ TestManager::TestManager(int& argc, char** argv) // Big countdown watchdog QTimer::singleShot(180000, this, [this] { - clog << "Time is up, stopping the session"; + clog << "Time is up, stopping the session\n"; if (testSuite) conclude(); else -- cgit v1.2.3