summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Cloke <patrickc@matrix.org>2022-07-14 13:47:52 -0400
committerPatrick Cloke <patrickc@matrix.org>2022-08-05 08:18:31 -0400
commitf0ab6a7f4c03b693d1be45dd7dd1a1c1d49a4489 (patch)
tree2d8ba2dda4971485a11648411bfbf103a3a55ee0
parentAdd an experimental config flag. (diff)
downloadsynapse-f0ab6a7f4c03b693d1be45dd7dd1a1c1d49a4489.tar.xz
Add test script.
-rw-r--r--thread_test.py190
1 files changed, 190 insertions, 0 deletions
diff --git a/thread_test.py b/thread_test.py
new file mode 100644
index 0000000000..61affb4277
--- /dev/null
+++ b/thread_test.py
@@ -0,0 +1,190 @@
+import json
+from time import monotonic
+
+import requests
+
+HOMESERVER = "http://localhost:8080"
+
+USER_1_TOK = "syt_dGVzdGVy_AywuFarQjsYrHuPkOUvg_25XLNK"
+USER_1_HEADERS = {"Authorization": f"Bearer {USER_1_TOK}"}
+
+USER_2_TOK = "syt_b3RoZXI_jtiTnwtlBjMGMixlHIBM_4cxesB"
+USER_2_HEADERS = {"Authorization": f"Bearer {USER_2_TOK}"}
+
+
+def _check_for_status(result):
+    # Similar to raise_for_status, but prints the error.
+    if 400 <= result.status_code:
+        error_msg = result.json()
+        result.raise_for_status()
+        print(error_msg)
+        exit(0)
+
+
+def _sync_and_show(room_id):
+    print("Syncing . . .")
+    result = requests.get(
+        f"{HOMESERVER}/_matrix/client/v3/sync",
+        headers=USER_1_HEADERS,
+        params={
+            "filter": json.dumps(
+                {
+                    "room": {
+                        "timeline": {"limit": 30, "unread_thread_notifications": True}
+                    }
+                }
+            )
+        },
+    )
+    _check_for_status(result)
+    sync_response = result.json()
+
+    room = sync_response["rooms"]["join"][room_id]
+
+    # Find read receipts (this assumes non-overlapping).
+    read_receipts = {}  # thread -> event ID -> users
+    for event in room["ephemeral"]["events"]:
+        if event["type"] != "m.receipt":
+            continue
+
+        for event_id, content in event["content"].items():
+            for mxid, receipt in content["m.read"].items():
+                print(mxid, receipt)
+                # Just care about the localpart of the MXID.
+                mxid = mxid.split(":", 1)[0]
+                read_receipts.setdefault(receipt.get("thread_id"), {}).setdefault(
+                    event_id, []
+                ).append(mxid)
+
+    print(room["unread_notifications"])
+    print(room.get("unread_thread_notifications"))
+    print()
+
+    # Convert events to their threads.
+    threads = {}
+    for event in room["timeline"]["events"]:
+        if event["type"] != "m.room.message":
+            continue
+
+        event_id = event["event_id"]
+
+        parent_id = event["content"].get("m.relates_to", {}).get("event_id")
+        if parent_id:
+            threads[parent_id][1].append(event)
+        else:
+            threads[event_id] = (event, [])
+
+    for root_event_id, (root, thread) in threads.items():
+        msg = root["content"]["body"]
+        print(f"{root_event_id}: {msg}")
+
+        for event in thread:
+            thread_event_id = event["event_id"]
+
+            msg = event["content"]["body"]
+            print(f"\t{thread_event_id}: {msg}")
+
+            if thread_event_id in read_receipts.get(root_event_id, {}):
+                user_ids = ", ".join(read_receipts[root_event_id][thread_event_id])
+                print(f"\t^--------- {user_ids} ---------^")
+
+        if root_event_id in read_receipts[None]:
+            user_ids = ", ".join(read_receipts[None][root_event_id])
+            print(f"^--------- {user_ids} ---------^")
+
+    print()
+    print()
+
+
+def _send_event(room_id, body, thread_id=None):
+    content = {
+        "msgtype": "m.text",
+        "body": body,
+    }
+    if thread_id:
+        content["m.relates_to"] = {
+            "rel_type": "m.thread",
+            "event_id": thread_id,
+        }
+
+    # Send a msg to the room.
+    result = requests.put(
+        f"{HOMESERVER}/_matrix/client/v3/rooms/{room_id}/send/m.room.message/msg{monotonic()}",
+        json=content,
+        headers=USER_2_HEADERS,
+    )
+    _check_for_status(result)
+    return result.json()["event_id"]
+
+
+def main():
+    # Create a new room as user 2, add a bunch of messages.
+    result = requests.post(
+        f"{HOMESERVER}/_matrix/client/v3/createRoom",
+        json={"visibility": "public", "name": f"Thread Read Receipts ({monotonic()})"},
+        headers=USER_2_HEADERS,
+    )
+    _check_for_status(result)
+    room_id = result.json()["room_id"]
+
+    # Second user joins the room.
+    result = requests.post(
+        f"{HOMESERVER}/_matrix/client/v3/rooms/{room_id}/join", headers=USER_1_HEADERS
+    )
+    _check_for_status(result)
+
+    # Sync user 1.
+    _sync_and_show(room_id)
+
+    # User 2 sends some messages.
+    event_ids = []
+
+    def _send_and_append(body, thread_id=None):
+        event_id = _send_event(room_id, body, thread_id)
+        event_ids.append(event_id)
+        return event_id
+
+    for msg in range(5):
+        root_message_id = _send_and_append(f"Message {msg}")
+    for msg in range(10):
+        if msg % 2:
+            _send_and_append(f"More message {msg}")
+        else:
+            _send_and_append(f"Thread Message {msg}", root_message_id)
+
+    # User 2 sends a read receipt.
+    print("@second reads main timeline")
+    result = requests.post(
+        f"{HOMESERVER}/_matrix/client/v3/rooms/{room_id}/receipt/m.read/{event_ids[3]}",
+        headers=USER_2_HEADERS,
+        json={},
+    )
+    _check_for_status(result)
+
+    _sync_and_show(room_id)
+
+    # User 1 sends a read receipt.
+    print("@test reads main timeline")
+    result = requests.post(
+        f"{HOMESERVER}/_matrix/client/v3/rooms/{room_id}/receipt/m.read/{event_ids[-5]}",
+        headers=USER_1_HEADERS,
+        json={},
+    )
+    _check_for_status(result)
+
+    _sync_and_show(room_id)
+
+    # User 1 sends another read receipt.
+    print("@test reads thread")
+    result = requests.post(
+        f"{HOMESERVER}/_matrix/client/v3/rooms/{room_id}/receipt/m.read/{event_ids[-4]}/{root_message_id}",
+        headers=USER_1_HEADERS,
+        json={},
+    )
+    _check_for_status(result)
+
+    _sync_and_show(room_id)
+
+
+if __name__ == "__main__":
+    main()