aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/qmc-example.cpp62
-rw-r--r--lib/room.cpp3
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"