Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F112556
D163.1732334339.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
D163.1732334339.diff
View Options
diff --git a/src/client/room/room-model.cpp b/src/client/room/room-model.cpp
--- a/src/client/room/room-model.cpp
+++ b/src/client/room/room-model.cpp
@@ -130,9 +130,17 @@
r.timeline = sortedUniqueMerge(r.timeline, eventIds, exists, key);
- // TODO need other way to determine whether it is limited
- // in a pagination request (/messages does not have that field)
- if ((! a.limited.has_value() || a.limited.value())
+ // If this is a pagination request, gapEventId
+ // should have value. If this is a sync request,
+ // gapEventId does not have value. The pagination
+ // request does not have the limited field, and
+ // whether it has more paginate back token is determined
+ // by the presence of the prevBatch parameter.
+ // In sync request, limited may not be specified,
+ // and thus, if limited does not have value, it means
+ // it is not limited.
+ if (((a.limited.has_value() && a.limited.value())
+ || a.gapEventId.has_value())
&& a.prevBatch.has_value()) {
// this sync is limited, add a Gap here
if (!eventIds.empty()) {
diff --git a/src/tests/client/paginate-test.cpp b/src/tests/client/paginate-test.cpp
--- a/src/tests/client/paginate-test.cpp
+++ b/src/tests/client/paginate-test.cpp
@@ -172,41 +172,57 @@
});
}
-TEST_CASE("Pagination should remove the original gap and record a new one", "[client][paginate]")
+TEST_CASE("Pagination should remove the original gap; it should record a new one iff end property is present", "[client][paginate]")
{
- using namespace Kazv::CursorOp;
-
- boost::asio::io_context io;
- AsioPromiseHandler ph{io.get_executor()};
- ClientModel m = makeClient(
- withRoom(makeRoom(
- withRoomId("!foo:example.org")
- | withRoomTimeline({event1, event2})
- | withRoomTimelineGaps({{event1.id(), "prevBatchForEvent1"}})
- ))
- );
-
- auto store = createTestClientStoreFrom(m, ph);
-
- auto resp = makeResponse(
- "GetRoomEvents",
- withResponseJsonBody(paginateResponseJson)
- | withResponseDataKV("roomId", "!foo:example.org")
- | withResponseDataKV("gapEventId", "$event1:example.org")
- );
-
- auto client = Client(store.reader().map([](auto c) { return SdkModel{c}; }), store,
- std::nullopt);
-
- store.dispatch(ProcessResponseAction{resp});
- io.run();
-
- auto r = client.room("!foo:example.org");
-
- auto timelineGaps = +r.timelineGaps();
+ auto testFunc = [](const json &j, bool hasEnd) {
+ using namespace Kazv::CursorOp;
+
+ boost::asio::io_context io;
+ AsioPromiseHandler ph{io.get_executor()};
+ ClientModel m = makeClient(
+ withRoom(makeRoom(
+ withRoomId("!foo:example.org")
+ | withRoomTimeline({event1, event2})
+ | withRoomTimelineGaps({{event1.id(), "prevBatchForEvent1"}})
+ ))
+ );
+
+ auto store = createTestClientStoreFrom(m, ph);
+
+ auto resp = makeResponse(
+ "GetRoomEvents",
+ withResponseJsonBody(j)
+ | withResponseDataKV("roomId", "!foo:example.org")
+ | withResponseDataKV("gapEventId", "$event1:example.org")
+ );
+
+ auto client = Client(store.reader().map([](auto c) { return SdkModel{c}; }), store,
+ std::nullopt);
+
+ store.dispatch(ProcessResponseAction{resp});
+ io.run();
+
+ auto r = client.room("!foo:example.org");
+
+ auto timelineGaps = +r.timelineGaps();
+
+ REQUIRE(! timelineGaps.find("$event1:example.org"));
+ if (hasEnd) {
+ REQUIRE(timelineGaps.at("$first:example.org") == "anotherPrevBatch");
+ } else {
+ REQUIRE(!timelineGaps.find("$first:example.org"));
+ }
+ };
+
+ WHEN("no end property") {
+ auto j = paginateResponseJson;
+ j.erase("end");
+ testFunc(j, false);
+ }
- REQUIRE(! timelineGaps.find("$event1:example.org"));
- REQUIRE(timelineGaps.at("$first:example.org") == "anotherPrevBatch");
+ WHEN("has end property") {
+ testFunc(paginateResponseJson, true);
+ }
}
TEST_CASE("Pagination should erase all gaps in (start-of-fetched-batch, orig-gapped-event]", "[client][paginate]")
diff --git a/src/tests/client/sync-test.cpp b/src/tests/client/sync-test.cpp
--- a/src/tests/client/sync-test.cpp
+++ b/src/tests/client/sync-test.cpp
@@ -569,3 +569,58 @@
});
}
}
+
+TEST_CASE("it does not add a gap when the limited field in the timeline is not present (conduwuit)", "[client][sync]")
+{
+ auto body = R"({
+ "device_one_time_keys_count": {
+ "signed_curve25519": 721
+ },
+ "device_unused_fallback_key_types": null,
+ "next_batch": "some",
+ "rooms": {
+ "join": {
+ "!foo:example.com": {
+ "ephemeral": {
+ "events": []
+ },
+ "timeline": {
+ "events": [
+ {
+ "content": {
+ },
+ "event_id": "$1",
+ "origin_server_ts": 1723379000000,
+ "sender": "@foo:example.com",
+ "type": "m.room.message",
+ "unsigned": {
+ "age": 1,
+ "transaction_id": "xxxxxx"
+ }
+ }
+ ],
+ "prev_batch": "prev-batch"
+ },
+ "unread_notifications": {
+ "highlight_count": 0,
+ "notification_count": 0
+ }
+ }
+ }
+ }
+ })"_json;
+ auto resp = makeResponse(
+ "Sync",
+ withResponseJsonBody(body)
+ | withResponseDataKV("is", "incremental")
+ );
+
+ ClientModel m = makeClient(
+ withRoom(makeRoom(
+ withRoomId("!foo:example.com"))));
+
+ auto [next, _] = processResponse(m, SyncResponse{resp});
+ auto room = next.roomList.rooms.at("!foo:example.com");
+ REQUIRE(room.timelineGaps.size() == 0);
+ REQUIRE(room.messages.count("$1") != 0);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 22, 7:58 PM (2 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39065
Default Alt Text
D163.1732334339.diff (6 KB)
Attached To
Mode
D163: Fix gap incorrectly introduced when limited field is missing from sync
Attached
Detach File
Event Timeline
Log In to Comment