test_events.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. # Copyright 2016 OpenMarket Ltd
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from twisted.internet import defer
  15. from synapse.events import FrozenEvent, _EventInternalMetadata
  16. from synapse.events.snapshot import EventContext
  17. from synapse.replication.slave.storage.events import SlavedEventStore
  18. from synapse.storage.roommember import RoomsForUser
  19. from ._base import BaseSlavedStoreTestCase
  20. USER_ID = "@feeling:blue"
  21. USER_ID_2 = "@bright:blue"
  22. OUTLIER = {"outlier": True}
  23. ROOM_ID = "!room:blue"
  24. def dict_equals(self, other):
  25. return self.__dict__ == other.__dict__
  26. def patch__eq__(cls):
  27. eq = getattr(cls, "__eq__", None)
  28. cls.__eq__ = dict_equals
  29. def unpatch():
  30. if eq is not None:
  31. cls.__eq__ = eq
  32. return unpatch
  33. class SlavedEventStoreTestCase(BaseSlavedStoreTestCase):
  34. STORE_TYPE = SlavedEventStore
  35. def setUp(self):
  36. # Patch up the equality operator for events so that we can check
  37. # whether lists of events match using assertEquals
  38. self.unpatches = [
  39. patch__eq__(_EventInternalMetadata),
  40. patch__eq__(FrozenEvent),
  41. ]
  42. return super(SlavedEventStoreTestCase, self).setUp()
  43. def tearDown(self):
  44. [unpatch() for unpatch in self.unpatches]
  45. @defer.inlineCallbacks
  46. def test_get_latest_event_ids_in_room(self):
  47. create = yield self.persist(type="m.room.create", key="", creator=USER_ID)
  48. yield self.replicate()
  49. yield self.check(
  50. "get_latest_event_ids_in_room", (ROOM_ID,), [create.event_id]
  51. )
  52. join = yield self.persist(
  53. type="m.room.member", key=USER_ID, membership="join",
  54. prev_events=[(create.event_id, {})],
  55. )
  56. yield self.replicate()
  57. yield self.check(
  58. "get_latest_event_ids_in_room", (ROOM_ID,), [join.event_id]
  59. )
  60. @defer.inlineCallbacks
  61. def test_redactions(self):
  62. yield self.persist(type="m.room.create", key="", creator=USER_ID)
  63. yield self.persist(type="m.room.member", key=USER_ID, membership="join")
  64. msg = yield self.persist(
  65. type="m.room.message", msgtype="m.text", body="Hello"
  66. )
  67. yield self.replicate()
  68. yield self.check("get_event", [msg.event_id], msg)
  69. redaction = yield self.persist(
  70. type="m.room.redaction", redacts=msg.event_id
  71. )
  72. yield self.replicate()
  73. msg_dict = msg.get_dict()
  74. msg_dict["content"] = {}
  75. msg_dict["unsigned"]["redacted_by"] = redaction.event_id
  76. msg_dict["unsigned"]["redacted_because"] = redaction
  77. redacted = FrozenEvent(msg_dict, msg.internal_metadata.get_dict())
  78. yield self.check("get_event", [msg.event_id], redacted)
  79. @defer.inlineCallbacks
  80. def test_backfilled_redactions(self):
  81. yield self.persist(type="m.room.create", key="", creator=USER_ID)
  82. yield self.persist(type="m.room.member", key=USER_ID, membership="join")
  83. msg = yield self.persist(
  84. type="m.room.message", msgtype="m.text", body="Hello"
  85. )
  86. yield self.replicate()
  87. yield self.check("get_event", [msg.event_id], msg)
  88. redaction = yield self.persist(
  89. type="m.room.redaction", redacts=msg.event_id, backfill=True
  90. )
  91. yield self.replicate()
  92. msg_dict = msg.get_dict()
  93. msg_dict["content"] = {}
  94. msg_dict["unsigned"]["redacted_by"] = redaction.event_id
  95. msg_dict["unsigned"]["redacted_because"] = redaction
  96. redacted = FrozenEvent(msg_dict, msg.internal_metadata.get_dict())
  97. yield self.check("get_event", [msg.event_id], redacted)
  98. @defer.inlineCallbacks
  99. def test_invites(self):
  100. yield self.check("get_invited_rooms_for_user", [USER_ID_2], [])
  101. event = yield self.persist(
  102. type="m.room.member", key=USER_ID_2, membership="invite"
  103. )
  104. yield self.replicate()
  105. yield self.check("get_invited_rooms_for_user", [USER_ID_2], [RoomsForUser(
  106. ROOM_ID, USER_ID, "invite", event.event_id,
  107. event.internal_metadata.stream_ordering
  108. )])
  109. @defer.inlineCallbacks
  110. def test_push_actions_for_user(self):
  111. yield self.persist(type="m.room.create", creator=USER_ID)
  112. yield self.persist(type="m.room.join", key=USER_ID, membership="join")
  113. yield self.persist(
  114. type="m.room.join", sender=USER_ID, key=USER_ID_2, membership="join"
  115. )
  116. event1 = yield self.persist(
  117. type="m.room.message", msgtype="m.text", body="hello"
  118. )
  119. yield self.replicate()
  120. yield self.check(
  121. "get_unread_event_push_actions_by_room_for_user",
  122. [ROOM_ID, USER_ID_2, event1.event_id],
  123. {"highlight_count": 0, "notify_count": 0}
  124. )
  125. yield self.persist(
  126. type="m.room.message", msgtype="m.text", body="world",
  127. push_actions=[(USER_ID_2, ["notify"])],
  128. )
  129. yield self.replicate()
  130. yield self.check(
  131. "get_unread_event_push_actions_by_room_for_user",
  132. [ROOM_ID, USER_ID_2, event1.event_id],
  133. {"highlight_count": 0, "notify_count": 1}
  134. )
  135. yield self.persist(
  136. type="m.room.message", msgtype="m.text", body="world",
  137. push_actions=[(USER_ID_2, [
  138. "notify", {"set_tweak": "highlight", "value": True}
  139. ])],
  140. )
  141. yield self.replicate()
  142. yield self.check(
  143. "get_unread_event_push_actions_by_room_for_user",
  144. [ROOM_ID, USER_ID_2, event1.event_id],
  145. {"highlight_count": 1, "notify_count": 2}
  146. )
  147. event_id = 0
  148. @defer.inlineCallbacks
  149. def persist(
  150. self, sender=USER_ID, room_id=ROOM_ID, type={}, key=None, internal={},
  151. state=None, reset_state=False, backfill=False,
  152. depth=None, prev_events=[], auth_events=[], prev_state=[], redacts=None,
  153. push_actions=[],
  154. **content
  155. ):
  156. """
  157. Returns:
  158. synapse.events.FrozenEvent: The event that was persisted.
  159. """
  160. if depth is None:
  161. depth = self.event_id
  162. if not prev_events:
  163. latest_event_ids = yield self.master_store.get_latest_event_ids_in_room(
  164. room_id
  165. )
  166. prev_events = [(ev_id, {}) for ev_id in latest_event_ids]
  167. event_dict = {
  168. "sender": sender,
  169. "type": type,
  170. "content": content,
  171. "event_id": "$%d:blue" % (self.event_id,),
  172. "room_id": room_id,
  173. "depth": depth,
  174. "origin_server_ts": self.event_id,
  175. "prev_events": prev_events,
  176. "auth_events": auth_events,
  177. }
  178. if key is not None:
  179. event_dict["state_key"] = key
  180. event_dict["prev_state"] = prev_state
  181. if redacts is not None:
  182. event_dict["redacts"] = redacts
  183. event = FrozenEvent(event_dict, internal_metadata_dict=internal)
  184. self.event_id += 1
  185. if state is not None:
  186. state_ids = {
  187. key: e.event_id for key, e in state.items()
  188. }
  189. context = EventContext.with_state(
  190. state_group=None,
  191. current_state_ids=state_ids,
  192. prev_state_ids=state_ids
  193. )
  194. else:
  195. state_handler = self.hs.get_state_handler()
  196. context = yield state_handler.compute_event_context(event)
  197. yield self.master_store.add_push_actions_to_staging(
  198. event.event_id, {
  199. user_id: actions
  200. for user_id, actions in push_actions
  201. },
  202. )
  203. ordering = None
  204. if backfill:
  205. yield self.master_store.persist_events(
  206. [(event, context)], backfilled=True
  207. )
  208. else:
  209. ordering, _ = yield self.master_store.persist_event(
  210. event, context,
  211. )
  212. if ordering:
  213. event.internal_metadata.stream_ordering = ordering
  214. defer.returnValue(event)