Skip to content

Commit 7ed787b

Browse files
authored
Fix bug in getRoomUpgradeHistory's verifyLinks functionality (#3089)
1 parent a58a36e commit 7ed787b

File tree

2 files changed

+122
-22
lines changed

2 files changed

+122
-22
lines changed

spec/unit/matrix-client.spec.ts

+119-21
Original file line numberDiff line numberDiff line change
@@ -2205,7 +2205,7 @@ describe("MatrixClient", function () {
22052205
"creator": "@daryl:alexandria.example.com",
22062206
"m.federate": true,
22072207
"predecessor": {
2208-
event_id: "spec_is_not_clear_what_id_this_is",
2208+
event_id: "id_of_last_event",
22092209
room_id: predecessorRoomId,
22102210
},
22112211
"room_version": "9",
@@ -2278,34 +2278,34 @@ describe("MatrixClient", function () {
22782278
});
22792279

22802280
describe("getRoomUpgradeHistory", () => {
2281-
function createRoomHistory(): [Room, Room, Room, Room] {
2281+
/**
2282+
* Create a chain of room history with create events and tombstones.
2283+
*
2284+
* @param creates include create events (default=true)
2285+
* @param tombstones include tomstone events (default=true)
2286+
* @returns 4 rooms chained together with tombstones and create
2287+
* events, in order from oldest to latest.
2288+
*/
2289+
function createRoomHistory(creates = true, tombstones = true): [Room, Room, Room, Room] {
22822290
const room1 = new Room("room1", client, "@carol:alexandria.example.com");
22832291
const room2 = new Room("room2", client, "@daryl:alexandria.example.com");
22842292
const room3 = new Room("room3", client, "@rick:helicopter.example.com");
22852293
const room4 = new Room("room4", client, "@michonne:hawthorne.example.com");
22862294

2287-
room1.addLiveEvents([tombstoneEvent(room2.roomId, room1.roomId)], {});
2288-
room2.addLiveEvents([roomCreateEvent(room2.roomId, room1.roomId)]);
2289-
2290-
room2.addLiveEvents([tombstoneEvent(room3.roomId, room2.roomId)], {});
2291-
room3.addLiveEvents([roomCreateEvent(room3.roomId, room2.roomId)]);
2295+
if (creates) {
2296+
room2.addLiveEvents([roomCreateEvent(room2.roomId, room1.roomId)]);
2297+
room3.addLiveEvents([roomCreateEvent(room3.roomId, room2.roomId)]);
2298+
room4.addLiveEvents([roomCreateEvent(room4.roomId, room3.roomId)]);
2299+
}
22922300

2293-
room3.addLiveEvents([tombstoneEvent(room4.roomId, room3.roomId)], {});
2294-
room4.addLiveEvents([roomCreateEvent(room4.roomId, room3.roomId)]);
2301+
if (tombstones) {
2302+
room1.addLiveEvents([tombstoneEvent(room2.roomId, room1.roomId)], {});
2303+
room2.addLiveEvents([tombstoneEvent(room3.roomId, room2.roomId)], {});
2304+
room3.addLiveEvents([tombstoneEvent(room4.roomId, room3.roomId)], {});
2305+
}
22952306

22962307
mocked(store.getRoom).mockImplementation((roomId: string) => {
2297-
switch (roomId) {
2298-
case "room1":
2299-
return room1;
2300-
case "room2":
2301-
return room2;
2302-
case "room3":
2303-
return room3;
2304-
case "room4":
2305-
return room4;
2306-
default:
2307-
return null;
2308-
}
2308+
return { room1, room2, room3, room4 }[roomId] || null;
23092309
});
23102310

23112311
return [room1, room2, room3, room4];
@@ -2334,6 +2334,49 @@ describe("MatrixClient", function () {
23342334
]);
23352335
});
23362336

2337+
it("Returns the predecessors of this room (with verify links)", () => {
2338+
const [room1, room2, room3, room4] = createRoomHistory();
2339+
const verifyLinks = true;
2340+
const history = client.getRoomUpgradeHistory(room4.roomId, verifyLinks);
2341+
expect(history.map((room) => room.roomId)).toEqual([
2342+
room1.roomId,
2343+
room2.roomId,
2344+
room3.roomId,
2345+
room4.roomId,
2346+
]);
2347+
});
2348+
2349+
it("With verify links, rejects predecessors that don't point forwards", () => {
2350+
// Given successors point back with create events, but
2351+
// predecessors do not point forwards with tombstones
2352+
const [, , , room4] = createRoomHistory(true, false);
2353+
2354+
// When I ask for history with verifyLinks on
2355+
const verifyLinks = true;
2356+
const history = client.getRoomUpgradeHistory(room4.roomId, verifyLinks);
2357+
2358+
// Then the predecessors are not included in the history
2359+
expect(history.map((room) => room.roomId)).toEqual([room4.roomId]);
2360+
});
2361+
2362+
it("Without verify links, includes predecessors that don't point forwards", () => {
2363+
// Given successors point back with create events, but
2364+
// predecessors do not point forwards with tombstones
2365+
const [room1, room2, room3, room4] = createRoomHistory(true, false);
2366+
2367+
// When I ask for history with verifyLinks off
2368+
const verifyLinks = false;
2369+
const history = client.getRoomUpgradeHistory(room4.roomId, verifyLinks);
2370+
2371+
// Then the predecessors are included in the history
2372+
expect(history.map((room) => room.roomId)).toEqual([
2373+
room1.roomId,
2374+
room2.roomId,
2375+
room3.roomId,
2376+
room4.roomId,
2377+
]);
2378+
});
2379+
23372380
it("Returns the subsequent rooms", () => {
23382381
const [room1, room2, room3, room4] = createRoomHistory();
23392382
const history = client.getRoomUpgradeHistory(room1.roomId);
@@ -2345,6 +2388,49 @@ describe("MatrixClient", function () {
23452388
]);
23462389
});
23472390

2391+
it("Returns the subsequent rooms (with verify links)", () => {
2392+
const [room1, room2, room3, room4] = createRoomHistory();
2393+
const verifyLinks = true;
2394+
const history = client.getRoomUpgradeHistory(room1.roomId, verifyLinks);
2395+
expect(history.map((room) => room.roomId)).toEqual([
2396+
room1.roomId,
2397+
room2.roomId,
2398+
room3.roomId,
2399+
room4.roomId,
2400+
]);
2401+
});
2402+
2403+
it("With verify links, rejects successors that don't point backwards", () => {
2404+
// Given predecessors point forwards with tombstones, but
2405+
// successors do not point back with create events.
2406+
const [room1, , ,] = createRoomHistory(false, true);
2407+
2408+
// When I ask for history with verifyLinks on
2409+
const verifyLinks = true;
2410+
const history = client.getRoomUpgradeHistory(room1.roomId, verifyLinks);
2411+
2412+
// Then the successors are not included in the history
2413+
expect(history.map((room) => room.roomId)).toEqual([room1.roomId]);
2414+
});
2415+
2416+
it("Without verify links, includes predecessors that don't point forwards", () => {
2417+
// Given predecessors point forwards with tombstones, but
2418+
// successors do not point back with create events.
2419+
const [room1, room2, room3, room4] = createRoomHistory(false, true);
2420+
2421+
// When I ask for history with verifyLinks off
2422+
const verifyLinks = false;
2423+
const history = client.getRoomUpgradeHistory(room1.roomId, verifyLinks);
2424+
2425+
// Then the successors are included in the history
2426+
expect(history.map((room) => room.roomId)).toEqual([
2427+
room1.roomId,
2428+
room2.roomId,
2429+
room3.roomId,
2430+
room4.roomId,
2431+
]);
2432+
});
2433+
23482434
it("Returns the predecessors and subsequent rooms", () => {
23492435
const [room1, room2, room3, room4] = createRoomHistory();
23502436
const history = client.getRoomUpgradeHistory(room3.roomId);
@@ -2355,6 +2441,18 @@ describe("MatrixClient", function () {
23552441
room4.roomId,
23562442
]);
23572443
});
2444+
2445+
it("Returns the predecessors and subsequent rooms (with verify links)", () => {
2446+
const [room1, room2, room3, room4] = createRoomHistory();
2447+
const verifyLinks = true;
2448+
const history = client.getRoomUpgradeHistory(room3.roomId, verifyLinks);
2449+
expect(history.map((room) => room.roomId)).toEqual([
2450+
room1.roomId,
2451+
room2.roomId,
2452+
room3.roomId,
2453+
room4.roomId,
2454+
]);
2455+
});
23582456
});
23592457
});
23602458
});

src/client.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -4996,6 +4996,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
49964996
const upgradeHistory = [currentRoom];
49974997

49984998
// Work backwards first, looking at create events.
4999+
let successorRoomId = currentRoom.roomId;
49995000
let createEvent = currentRoom.currentState.getStateEvents(EventType.RoomCreate, "");
50005001
while (createEvent) {
50015002
const predecessor = createEvent.getContent()["predecessor"];
@@ -5006,13 +5007,14 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
50065007
if (verifyLinks) {
50075008
const tombstone = refRoom.currentState.getStateEvents(EventType.RoomTombstone, "");
50085009

5009-
if (!tombstone || tombstone.getContent()["replacement_room"] !== refRoom.roomId) {
5010+
if (!tombstone || tombstone.getContent()["replacement_room"] !== successorRoomId) {
50105011
break;
50115012
}
50125013
}
50135014

50145015
// Insert at the front because we're working backwards from the currentRoom
50155016
upgradeHistory.splice(0, 0, refRoom);
5017+
successorRoomId = refRoom.roomId;
50165018
createEvent = refRoom.currentState.getStateEvents(EventType.RoomCreate, "");
50175019
} else {
50185020
// No further create events to look at

0 commit comments

Comments
 (0)