diff options
-rw-r--r-- | examples/qmc-example.cpp | 62 | ||||
-rw-r--r-- | lib/room.cpp | 3 |
2 files changed, 45 insertions, 20 deletions
diff --git a/examples/qmc-example.cpp b/examples/qmc-example.cpp index f4067009..c948a39b 100644 --- a/examples/qmc-example.cpp +++ b/examples/qmc-example.cpp @@ -375,42 +375,64 @@ void QMCTest::checkFileSendingOutcome(const QString& txnId, void QMCTest::setTopic() { static const char* const stateTestName = "State setting test"; - static const char* const fakeStateTestName = - "Fake state event immunity test"; running.push_back(stateTestName); - running.push_back(fakeStateTestName); auto initialTopic = targetRoom->topic(); - const auto newTopic = c->generateTxnId(); + const auto newTopic = c->generateTxnId(); // Just a way to get a unique id targetRoom->setTopic(newTopic); // Sets the state by proper means const auto fakeTopic = c->generateTxnId(); - targetRoom->postJson(RoomTopicEvent::matrixTypeId(), // Fake state event - RoomTopicEvent(fakeTopic).contentJson()); + const auto fakeTxnId = + targetRoom->postJson(RoomTopicEvent::matrixTypeId(), // Fake state event + RoomTopicEvent(fakeTopic).contentJson()); connectUntil(targetRoom, &Room::topicChanged, this, [this, newTopic, fakeTopic, initialTopic] { if (targetRoom->topic() == newTopic) { QMC_CHECK(stateTestName, true); - // Don't reset the topic yet if the negative test still - // runs - if (!running.contains(fakeStateTestName)) - targetRoom->setTopic(initialTopic); - return true; } return false; }); - connectUntil(targetRoom, &Room::pendingEventAboutToMerge, this, - [this, fakeTopic, initialTopic](const RoomEvent* e, int) { - if (e->contentJson().value("topic").toString() != fakeTopic) - return false; // Wait on for the right event + // Older Synapses allowed sending fake state events through, although + // did not process them; // https://github.com/matrix-org/synapse/pull/5805 + // changed that and now Synapse 400's in response to fake state events. + // The following two-step approach handles both cases, assuming that + // Room::pendingEventChanged() with EventStatus::ReachedServer is guaranteed + // to be emitted before Room::pendingEventAboutToMerge. + connectUntil( + targetRoom, &Room::pendingEventChanged, this, + [this, fakeTopic, initialTopic, fakeTxnId](int pendingIdx) { + const auto& pendingEvents = targetRoom->pendingEvents(); + Q_ASSERT(pendingIdx >= 0 && pendingIdx < int(pendingEvents.size())); + const auto& evt = pendingEvents[pendingIdx]; + if (evt->transactionId() != fakeTxnId) + return false; - QMC_CHECK(fakeStateTestName, !e->isStateEvent()); - if (!running.contains(fakeStateTestName)) - targetRoom->setTopic(initialTopic); - return true; - }); + if (evt.deliveryStatus() == EventStatus::SendingFailed) { + QMC_CHECK("Fake state event immunity test", true); + return true; + } + if (evt.deliveryStatus() != EventStatus::ReachedServer) + return false; + + // All before was just a preparation, this is where the test starts. + // (If Synapse rejected the event the library immunity can't be + // tested.) + static const char* const fakeStateTestName = + "Fake state event immunity test"; + running.push_back(fakeStateTestName); + connectUntil( + targetRoom, &Room::pendingEventAboutToMerge, this, + [this, fakeTopic, initialTopic](const RoomEvent* e, int) { + if (e->contentJson().value("topic").toString() != fakeTopic) + return false; // Wait on for the right event + + QMC_CHECK(fakeStateTestName, !e->isStateEvent()); + return true; + }); + return true; + }); } void QMCTest::addAndRemoveTag() diff --git a/lib/room.cpp b/lib/room.cpp index b32d3492..95dba857 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1520,6 +1520,7 @@ QString Room::retryMessage(const QString& txnId) " events are likely to be in the timeline after retry"; } it->resetStatus(); + emit pendingEventChanged(int(it - d->unsyncedEvents.begin())); return d->doSendEvent(it->event()); } @@ -2189,6 +2190,8 @@ Room::Changes Room::Private::addNewMessageEvents(RoomEvents&& events) auto* nextPendingEvt = nextPending->get(); const auto pendingEvtIdx = int(nextPendingPair.second - unsyncedEvents.begin()); + nextPendingPair.second->setReachedServer(nextPendingEvt->id()); + emit q->pendingEventChanged(pendingEvtIdx); emit q->pendingEventAboutToMerge(nextPendingEvt, pendingEvtIdx); qDebug(EVENTS) << "Merging pending event from transaction" << nextPendingEvt->transactionId() << "into" |