diff options
author | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2019-08-02 09:32:49 +0900 |
---|---|---|
committer | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2019-08-02 09:32:49 +0900 |
commit | 35cfef7a4253d49a37e5ce21c337fbb3d2633c42 (patch) | |
tree | dfcc77c4e404b6b8f07a4c9ee6283e70e4723883 /examples | |
parent | 5b37e15d6a57d3b689c88f5cfce7afea9787a034 (diff) | |
parent | 5b236dfe895c7766002559570aa29c9033009228 (diff) | |
download | libquotient-35cfef7a4253d49a37e5ce21c337fbb3d2633c42.tar.gz libquotient-35cfef7a4253d49a37e5ce21c337fbb3d2633c42.zip |
Merge branch 'master' into use-clang-format
Diffstat (limited to 'examples')
-rw-r--r-- | examples/qmc-example.cpp | 255 |
1 files changed, 146 insertions, 109 deletions
diff --git a/examples/qmc-example.cpp b/examples/qmc-example.cpp index 36fc61c4..d6cba76a 100644 --- a/examples/qmc-example.cpp +++ b/examples/qmc-example.cpp @@ -1,17 +1,21 @@ #include "connection.h" +#include "room.h" +#include "user.h" + #include "csapi/joining.h" #include "csapi/leaving.h" #include "csapi/room_send.h" + +#include "events/reactionevent.h" #include "events/simplestateevents.h" -#include "room.h" -#include "user.h" #include <QtCore/QCoreApplication> #include <QtCore/QFileInfo> #include <QtCore/QStringBuilder> #include <QtCore/QTemporaryFile> #include <QtCore/QTimer> + #include <functional> #include <iostream> @@ -22,28 +26,33 @@ using namespace std::placeholders; class QMCTest : public QObject { - public: +public: QMCTest(Connection* conn, QString testRoomName, QString source); - private slots: +private slots: + // clang-format off void setupAndRun(); void onNewRoom(Room* r); void run(); void doTests(); - void loadMembers(); - void sendMessage(); - void sendFile(); - void checkFileSendingOutcome(const QString& txnId, const QString& fileName); - void setTopic(); - void addAndRemoveTag(); - void sendAndRedact(); - bool checkRedactionOutcome(const QString& evtIdToRedact); - void markDirectChat(); - void checkDirectChatOutcome(const Connection::DirectChatsMap& added); + void loadMembers(); + void sendMessage(); + void sendReaction(const QString& targetEvtId); + void sendFile(); + void checkFileSendingOutcome(const QString& txnId, + const QString& fileName); + void setTopic(); + void addAndRemoveTag(); + void sendAndRedact(); + bool checkRedactionOutcome(const QString& evtIdToRedact); + void markDirectChat(); + void checkDirectChatOutcome( + const Connection::DirectChatsMap& added); void conclude(); void finalize(); + // clang-format on - private: +private: QScopedPointer<Connection, QScopedPointerDeleteLater> c; QStringList running; QStringList succeeded; @@ -55,37 +64,37 @@ class QMCTest : public QObject bool validatePendingEvent(const QString& txnId); }; -#define QMC_CHECK(description, condition) \ - { \ - Q_ASSERT(running.removeOne(description)); \ - if (!!(condition)) { \ - succeeded.push_back(description); \ - cout << (description) << " successful" << endl; \ - if (targetRoom) \ - targetRoom->postMessage(origin % ": " % (description) \ - % " successful", \ - MessageEventType::Notice); \ - } else { \ - failed.push_back(description); \ - cout << (description) << " FAILED" << endl; \ - if (targetRoom) \ - targetRoom->postPlainText(origin % ": " % (description) \ - % " FAILED"); \ - } \ +#define QMC_CHECK(description, condition) \ + { \ + Q_ASSERT(running.removeOne(description)); \ + if (!!(condition)) { \ + succeeded.push_back(description); \ + cout << (description) << " successful" << endl; \ + if (targetRoom) \ + targetRoom->postMessage(origin % ": " % (description) \ + % " successful", \ + MessageEventType::Notice); \ + } else { \ + failed.push_back(description); \ + cout << (description) << " FAILED" << endl; \ + if (targetRoom) \ + targetRoom->postPlainText(origin % ": " % (description) \ + % " FAILED"); \ + } \ } bool QMCTest::validatePendingEvent(const QString& txnId) { auto it = targetRoom->findPendingEvent(txnId); return it != targetRoom->pendingEvents().end() - && it->deliveryStatus() == EventStatus::Submitted - && (*it)->transactionId() == txnId; + && it->deliveryStatus() == EventStatus::Submitted + && (*it)->transactionId() == txnId; } QMCTest::QMCTest(Connection* conn, QString testRoomName, QString source) - : c(conn), - origin(std::move(source)), - targetRoomName(std::move(testRoomName)) + : c(conn) + , origin(std::move(source)) + , targetRoomName(std::move(testRoomName)) { if (!origin.isEmpty()) cout << "Origin for the test message: " << origin.toStdString() << endl; @@ -114,9 +123,8 @@ void QMCTest::setupAndRun() QMC_CHECK("Join room", false); conclude(); }); - // Connection::joinRoom() creates a Room object upon - // JoinRoomJob::success but this object is empty until the first sync is - // done. + // Connection::joinRoom() creates a Room object upon JoinRoomJob::success + // but this object is empty until the first sync is done. connect(joinJob, &BaseJob::success, this, [this, joinJob] { targetRoom = c->room(joinJob->roomId(), JoinState::Join); QMC_CHECK("Join room", targetRoom != nullptr); @@ -183,13 +191,10 @@ void QMCTest::doTests() void QMCTest::loadMembers() { running.push_back("Loading members"); - // The dedicated qmc-test room is too small to test - // lazy-loading-then-full-loading; use #qmatrixclient:matrix.org instead. - // TODO: #264 - auto* r = c->room(QStringLiteral("!PCzUtxtOjUySxSelof:matrix.org")); + auto* r = c->roomByAlias(QStringLiteral("#quotient:matrix.org"), + JoinState::Join); if (!r) { - cout << "#test:matrix.org is not found in the test user's rooms" - << endl; + cout << "#test:matrix.org is not found in the test user's rooms" << endl; QMC_CHECK("Loading members", false); return; } @@ -219,23 +224,60 @@ void QMCTest::sendMessage() return; } - connectUntil(targetRoom, &Room::pendingEventAboutToMerge, this, - [this, txnId](const RoomEvent* evt, int pendingIdx) { - const auto& pendingEvents = targetRoom->pendingEvents(); - Q_ASSERT(pendingIdx >= 0 - && pendingIdx < int(pendingEvents.size())); - - if (evt->transactionId() != txnId) - return false; - - QMC_CHECK("Message sending", - is<RoomMessageEvent>(*evt) - && !evt->id().isEmpty() - && pendingEvents[size_t(pendingIdx)] - ->transactionId() - == evt->transactionId()); - return true; - }); + connectUntil( + targetRoom, &Room::pendingEventAboutToMerge, this, + [this, txnId](const RoomEvent* evt, int pendingIdx) { + const auto& pendingEvents = targetRoom->pendingEvents(); + Q_ASSERT(pendingIdx >= 0 && pendingIdx < int(pendingEvents.size())); + + if (evt->transactionId() != txnId) + return false; + + QMC_CHECK("Message sending", + is<RoomMessageEvent>(*evt) && !evt->id().isEmpty() + && pendingEvents[size_t(pendingIdx)]->transactionId() + == evt->transactionId()); + sendReaction(evt->id()); + return true; + }); +} + +void QMCTest::sendReaction(const QString& targetEvtId) +{ + running.push_back("Reaction sending"); + cout << "Reacting to the newest message in the room" << endl; + Q_ASSERT(targetRoom->timelineSize() > 0); + const auto key = QStringLiteral("+1"); + auto txnId = targetRoom->postReaction(targetEvtId, key); + if (!validatePendingEvent(txnId)) { + cout << "Invalid pending event right after submitting" << endl; + QMC_CHECK("Reaction sending", false); + return; + } + + // TODO: Check that it came back as a reaction event and that it attached to + // the right event + connectUntil( + targetRoom, &Room::updatedEvent, this, + [this, txnId, key, targetEvtId](const QString& actualTargetEvtId) { + if (actualTargetEvtId != targetEvtId) + return false; + const auto reactions = targetRoom->relatedEvents( + targetEvtId, EventRelation::Annotation()); + // It's a test room, assuming no interference there should + // be exactly one reaction + if (reactions.size() != 1) { + QMC_CHECK("Reaction sending", false); + } else { + const auto* evt = + eventCast<const ReactionEvent>(reactions.back()); + QMC_CHECK("Reaction sending", + is<ReactionEvent>(*evt) && !evt->id().isEmpty() + && evt->relation().key == key + && evt->transactionId() == txnId); + } + return true; + }); } void QMCTest::sendFile() @@ -254,8 +296,8 @@ void QMCTest::sendFile() // the full path const auto tfName = QFileInfo(*tf).fileName(); cout << "Sending file" << tfName.toStdString() << endl; - const auto txnId = targetRoom->postFile( - "Test file", QUrl::fromLocalFile(tf->fileName())); + const auto txnId = + targetRoom->postFile("Test file", QUrl::fromLocalFile(tf->fileName())); if (!validatePendingEvent(txnId)) { cout << "Invalid pending event right after submitting" << endl; QMC_CHECK("File sending", false); @@ -307,41 +349,37 @@ void QMCTest::checkFileSendingOutcome(const QString& txnId, } connectUntil( - targetRoom, &Room::pendingEventAboutToMerge, this, - [this, txnId, fileName](const RoomEvent* evt, int pendingIdx) { - const auto& pendingEvents = targetRoom->pendingEvents(); - Q_ASSERT(pendingIdx >= 0 - && pendingIdx < int(pendingEvents.size())); - - if (evt->transactionId() != txnId) - return false; - - cout << "File event " << txnId.toStdString() - << " arrived in the timeline" << endl; - visit(*evt, - [&](const RoomMessageEvent& e) { - QMC_CHECK("File sending", - !e.id().isEmpty() - && pendingEvents[size_t(pendingIdx)] - ->transactionId() - == txnId - && e.hasFileContent() - && e.content()->fileInfo() - ->originalName - == fileName); - }, - [this](const RoomEvent&) { - QMC_CHECK("File sending", false); - }); - return true; - }); + targetRoom, &Room::pendingEventAboutToMerge, this, + [this, txnId, fileName](const RoomEvent* evt, int pendingIdx) { + const auto& pendingEvents = targetRoom->pendingEvents(); + Q_ASSERT(pendingIdx >= 0 && pendingIdx < int(pendingEvents.size())); + + if (evt->transactionId() != txnId) + return false; + + cout << "File event " << txnId.toStdString() + << " arrived in the timeline" << endl; + visit( + *evt, + [&](const RoomMessageEvent& e) { + QMC_CHECK( + "File sending", + !e.id().isEmpty() + && pendingEvents[size_t(pendingIdx)]->transactionId() + == txnId + && e.hasFileContent() + && e.content()->fileInfo()->originalName == fileName); + }, + [this](const RoomEvent&) { QMC_CHECK("File sending", false); }); + return true; + }); } void QMCTest::setTopic() { static const char* const stateTestName = "State setting test"; static const char* const fakeStateTestName = - "Fake state event immunity test"; + "Fake state event immunity test"; running.push_back(stateTestName); running.push_back(fakeStateTestName); auto initialTopic = targetRoom->topic(); @@ -368,8 +406,7 @@ void QMCTest::setTopic() connectUntil(targetRoom, &Room::pendingEventAboutToMerge, this, [this, fakeTopic, initialTopic](const RoomEvent* e, int) { - if (e->contentJson().value("topic").toString() - != fakeTopic) + if (e->contentJson().value("topic").toString() != fakeTopic) return false; // Wait on for the right event QMC_CHECK(fakeStateTestName, !e->isStateEvent()); @@ -420,9 +457,10 @@ void QMCTest::sendAndRedact() cout << "Redacting the message" << endl; targetRoom->redactEvent(evtId, origin); - connectUntil( - targetRoom, &Room::addedMessages, this, - [this, evtId] { return checkRedactionOutcome(evtId); }); + connectUntil(targetRoom, &Room::addedMessages, this, + [this, evtId] { + return checkRedactionOutcome(evtId); + }); }); } @@ -449,8 +487,7 @@ bool QMCTest::checkRedactionOutcome(const QString& evtIdToRedact) QMC_CHECK("Redaction", newEvent->isRedacted() - && newEvent->redactionReason() - == origin); + && newEvent->redactionReason() == origin); return true; }); } @@ -498,23 +535,23 @@ void QMCTest::conclude() c->stopSync(); auto succeededRec = QString::number(succeeded.size()) + " tests succeeded"; if (!failed.isEmpty() || !running.isEmpty()) - succeededRec += " of " - % QString::number(succeeded.size() + failed.size() - + running.size()) - % " total"; + succeededRec += + " of " + % QString::number(succeeded.size() + failed.size() + running.size()) + % " total"; QString plainReport = origin % ": Testing complete, " % succeededRec; QString color = failed.isEmpty() && running.isEmpty() ? "00AA00" : "AA0000"; QString htmlReport = origin % ": <strong><font data-mx-color='#" % color - % "' color='#" % color % "'>Testing complete</font></strong>, " - % succeededRec; + % "' color='#" % color + % "'>Testing complete</font></strong>, " % succeededRec; if (!failed.isEmpty()) { plainReport += "\nFAILED: " % failed.join(", "); htmlReport += "<br><strong>Failed:</strong> " % failed.join(", "); } if (!running.isEmpty()) { plainReport += "\nDID NOT FINISH: " % running.join(", "); - htmlReport += - "<br><strong>Did not finish:</strong> " % running.join(", "); + htmlReport += "<br><strong>Did not finish:</strong> " + % running.join(", "); } cout << plainReport.toStdString() << endl; |