Skip to content

Commit

Permalink
Room/qmc-example: consider fake state event rejection as valid
Browse files Browse the repository at this point in the history
This is an addition in matrix-org/synapse#5805 -
Synapse no more tolerates fake state events (which actually obviates
the need for this test but fake state events still go through on older
Synapses). To allow checking for both cases Room behaviour has been
slightly changed (without compat breakage) to make sure the pending
event status is set to ReachedServer (and pendingEventChanged() is
emitted, if necessary) before merging the pending event into the
timeline.
  • Loading branch information
KitsuneRal committed Aug 2, 2019
1 parent c05ade8 commit 16ed527
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 20 deletions.
62 changes: 42 additions & 20 deletions examples/qmc-example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
3 changes: 3 additions & 0 deletions lib/room.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}

Expand Down Expand Up @@ -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"
Expand Down

0 comments on commit 16ed527

Please sign in to comment.