test_event_federation.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2018 New Vector Ltd
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the 'License');
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an 'AS IS' BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import tests.unittest
  16. import tests.utils
  17. class EventFederationWorkerStoreTestCase(tests.unittest.HomeserverTestCase):
  18. def prepare(self, reactor, clock, hs):
  19. self.store = hs.get_datastore()
  20. def test_get_prev_events_for_room(self):
  21. room_id = "@ROOM:local"
  22. # add a bunch of events and hashes to act as forward extremities
  23. def insert_event(txn, i):
  24. event_id = "$event_%i:local" % i
  25. txn.execute(
  26. (
  27. "INSERT INTO events ("
  28. " room_id, event_id, type, depth, topological_ordering,"
  29. " content, processed, outlier, stream_ordering) "
  30. "VALUES (?, ?, 'm.test', ?, ?, 'test', ?, ?, ?)"
  31. ),
  32. (room_id, event_id, i, i, True, False, i),
  33. )
  34. txn.execute(
  35. (
  36. "INSERT INTO event_forward_extremities (room_id, event_id) "
  37. "VALUES (?, ?)"
  38. ),
  39. (room_id, event_id),
  40. )
  41. txn.execute(
  42. (
  43. "INSERT INTO event_reference_hashes "
  44. "(event_id, algorithm, hash) "
  45. "VALUES (?, 'sha256', ?)"
  46. ),
  47. (event_id, bytearray(b"ffff")),
  48. )
  49. for i in range(0, 20):
  50. self.get_success(
  51. self.store.db_pool.runInteraction("insert", insert_event, i)
  52. )
  53. # this should get the last ten
  54. r = self.get_success(self.store.get_prev_events_for_room(room_id))
  55. self.assertEqual(10, len(r))
  56. for i in range(0, 10):
  57. self.assertEqual("$event_%i:local" % (19 - i), r[i])
  58. def test_get_rooms_with_many_extremities(self):
  59. room1 = "#room1"
  60. room2 = "#room2"
  61. room3 = "#room3"
  62. def insert_event(txn, i, room_id):
  63. event_id = "$event_%i:local" % i
  64. txn.execute(
  65. (
  66. "INSERT INTO event_forward_extremities (room_id, event_id) "
  67. "VALUES (?, ?)"
  68. ),
  69. (room_id, event_id),
  70. )
  71. for i in range(0, 20):
  72. self.get_success(
  73. self.store.db_pool.runInteraction("insert", insert_event, i, room1)
  74. )
  75. self.get_success(
  76. self.store.db_pool.runInteraction("insert", insert_event, i, room2)
  77. )
  78. self.get_success(
  79. self.store.db_pool.runInteraction("insert", insert_event, i, room3)
  80. )
  81. # Test simple case
  82. r = self.get_success(self.store.get_rooms_with_many_extremities(5, 5, []))
  83. self.assertEqual(len(r), 3)
  84. # Does filter work?
  85. r = self.get_success(self.store.get_rooms_with_many_extremities(5, 5, [room1]))
  86. self.assertTrue(room2 in r)
  87. self.assertTrue(room3 in r)
  88. self.assertEqual(len(r), 2)
  89. r = self.get_success(
  90. self.store.get_rooms_with_many_extremities(5, 5, [room1, room2])
  91. )
  92. self.assertEqual(r, [room3])
  93. # Does filter and limit work?
  94. r = self.get_success(self.store.get_rooms_with_many_extremities(5, 1, [room1]))
  95. self.assertTrue(r == [room2] or r == [room3])
  96. def test_auth_difference(self):
  97. room_id = "@ROOM:local"
  98. # The silly auth graph we use to test the auth difference algorithm,
  99. # where the top are the most recent events.
  100. #
  101. # A B
  102. # \ /
  103. # D E
  104. # \ |
  105. # ` F C
  106. # | /|
  107. # G ´ |
  108. # | \ |
  109. # H I
  110. # | |
  111. # K J
  112. auth_graph = {
  113. "a": ["e"],
  114. "b": ["e"],
  115. "c": ["g", "i"],
  116. "d": ["f"],
  117. "e": ["f"],
  118. "f": ["g"],
  119. "g": ["h", "i"],
  120. "h": ["k"],
  121. "i": ["j"],
  122. "k": [],
  123. "j": [],
  124. }
  125. depth_map = {
  126. "a": 7,
  127. "b": 7,
  128. "c": 4,
  129. "d": 6,
  130. "e": 6,
  131. "f": 5,
  132. "g": 3,
  133. "h": 2,
  134. "i": 2,
  135. "k": 1,
  136. "j": 1,
  137. }
  138. # We rudely fiddle with the appropriate tables directly, as that's much
  139. # easier than constructing events properly.
  140. def insert_event(txn, event_id, stream_ordering):
  141. depth = depth_map[event_id]
  142. self.store.db_pool.simple_insert_txn(
  143. txn,
  144. table="events",
  145. values={
  146. "event_id": event_id,
  147. "room_id": room_id,
  148. "depth": depth,
  149. "topological_ordering": depth,
  150. "type": "m.test",
  151. "processed": True,
  152. "outlier": False,
  153. "stream_ordering": stream_ordering,
  154. },
  155. )
  156. self.store.db_pool.simple_insert_many_txn(
  157. txn,
  158. table="event_auth",
  159. values=[
  160. {"event_id": event_id, "room_id": room_id, "auth_id": a}
  161. for a in auth_graph[event_id]
  162. ],
  163. )
  164. next_stream_ordering = 0
  165. for event_id in auth_graph:
  166. next_stream_ordering += 1
  167. self.get_success(
  168. self.store.db_pool.runInteraction(
  169. "insert", insert_event, event_id, next_stream_ordering
  170. )
  171. )
  172. # Now actually test that various combinations give the right result:
  173. difference = self.get_success(
  174. self.store.get_auth_chain_difference([{"a"}, {"b"}])
  175. )
  176. self.assertSetEqual(difference, {"a", "b"})
  177. difference = self.get_success(
  178. self.store.get_auth_chain_difference([{"a"}, {"b"}, {"c"}])
  179. )
  180. self.assertSetEqual(difference, {"a", "b", "c", "e", "f"})
  181. difference = self.get_success(
  182. self.store.get_auth_chain_difference([{"a", "c"}, {"b"}])
  183. )
  184. self.assertSetEqual(difference, {"a", "b", "c"})
  185. difference = self.get_success(
  186. self.store.get_auth_chain_difference([{"a"}, {"b"}, {"d"}])
  187. )
  188. self.assertSetEqual(difference, {"a", "b", "d", "e"})
  189. difference = self.get_success(
  190. self.store.get_auth_chain_difference([{"a"}, {"b"}, {"c"}, {"d"}])
  191. )
  192. self.assertSetEqual(difference, {"a", "b", "c", "d", "e", "f"})
  193. difference = self.get_success(
  194. self.store.get_auth_chain_difference([{"a"}, {"b"}, {"e"}])
  195. )
  196. self.assertSetEqual(difference, {"a", "b"})
  197. difference = self.get_success(self.store.get_auth_chain_difference([{"a"}]))
  198. self.assertSetEqual(difference, set())