test_utils.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2015, 2016 OpenMarket 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. from synapse.api.room_versions import RoomVersions
  16. from synapse.events import make_event_from_dict
  17. from synapse.events.utils import (
  18. copy_power_levels_contents,
  19. prune_event,
  20. serialize_event,
  21. )
  22. from synapse.util.frozenutils import freeze
  23. from tests import unittest
  24. def MockEvent(**kwargs):
  25. if "event_id" not in kwargs:
  26. kwargs["event_id"] = "fake_event_id"
  27. if "type" not in kwargs:
  28. kwargs["type"] = "fake_type"
  29. return make_event_from_dict(kwargs)
  30. class PruneEventTestCase(unittest.TestCase):
  31. """ Asserts that a new event constructed with `evdict` will look like
  32. `matchdict` when it is redacted. """
  33. def run_test(self, evdict, matchdict, **kwargs):
  34. self.assertEquals(
  35. prune_event(make_event_from_dict(evdict, **kwargs)).get_dict(), matchdict
  36. )
  37. def test_minimal(self):
  38. self.run_test(
  39. {"type": "A", "event_id": "$test:domain"},
  40. {
  41. "type": "A",
  42. "event_id": "$test:domain",
  43. "content": {},
  44. "signatures": {},
  45. "unsigned": {},
  46. },
  47. )
  48. def test_basic_keys(self):
  49. self.run_test(
  50. {
  51. "type": "A",
  52. "room_id": "!1:domain",
  53. "sender": "@2:domain",
  54. "event_id": "$3:domain",
  55. "origin": "domain",
  56. },
  57. {
  58. "type": "A",
  59. "room_id": "!1:domain",
  60. "sender": "@2:domain",
  61. "event_id": "$3:domain",
  62. "origin": "domain",
  63. "content": {},
  64. "signatures": {},
  65. "unsigned": {},
  66. },
  67. )
  68. def test_unsigned_age_ts(self):
  69. self.run_test(
  70. {"type": "B", "event_id": "$test:domain", "unsigned": {"age_ts": 20}},
  71. {
  72. "type": "B",
  73. "event_id": "$test:domain",
  74. "content": {},
  75. "signatures": {},
  76. "unsigned": {"age_ts": 20},
  77. },
  78. )
  79. self.run_test(
  80. {
  81. "type": "B",
  82. "event_id": "$test:domain",
  83. "unsigned": {"other_key": "here"},
  84. },
  85. {
  86. "type": "B",
  87. "event_id": "$test:domain",
  88. "content": {},
  89. "signatures": {},
  90. "unsigned": {},
  91. },
  92. )
  93. def test_content(self):
  94. self.run_test(
  95. {"type": "C", "event_id": "$test:domain", "content": {"things": "here"}},
  96. {
  97. "type": "C",
  98. "event_id": "$test:domain",
  99. "content": {},
  100. "signatures": {},
  101. "unsigned": {},
  102. },
  103. )
  104. self.run_test(
  105. {
  106. "type": "m.room.create",
  107. "event_id": "$test:domain",
  108. "content": {"creator": "@2:domain", "other_field": "here"},
  109. },
  110. {
  111. "type": "m.room.create",
  112. "event_id": "$test:domain",
  113. "content": {"creator": "@2:domain"},
  114. "signatures": {},
  115. "unsigned": {},
  116. },
  117. )
  118. def test_alias_event(self):
  119. """Alias events have special behavior up through room version 6."""
  120. self.run_test(
  121. {
  122. "type": "m.room.aliases",
  123. "event_id": "$test:domain",
  124. "content": {"aliases": ["test"]},
  125. },
  126. {
  127. "type": "m.room.aliases",
  128. "event_id": "$test:domain",
  129. "content": {"aliases": ["test"]},
  130. "signatures": {},
  131. "unsigned": {},
  132. },
  133. )
  134. def test_msc2432_alias_event(self):
  135. """After MSC2432, alias events have no special behavior."""
  136. self.run_test(
  137. {"type": "m.room.aliases", "content": {"aliases": ["test"]}},
  138. {
  139. "type": "m.room.aliases",
  140. "content": {},
  141. "signatures": {},
  142. "unsigned": {},
  143. },
  144. room_version=RoomVersions.V6,
  145. )
  146. class SerializeEventTestCase(unittest.TestCase):
  147. def serialize(self, ev, fields):
  148. return serialize_event(ev, 1479807801915, only_event_fields=fields)
  149. def test_event_fields_works_with_keys(self):
  150. self.assertEquals(
  151. self.serialize(
  152. MockEvent(sender="@alice:localhost", room_id="!foo:bar"), ["room_id"]
  153. ),
  154. {"room_id": "!foo:bar"},
  155. )
  156. def test_event_fields_works_with_nested_keys(self):
  157. self.assertEquals(
  158. self.serialize(
  159. MockEvent(
  160. sender="@alice:localhost",
  161. room_id="!foo:bar",
  162. content={"body": "A message"},
  163. ),
  164. ["content.body"],
  165. ),
  166. {"content": {"body": "A message"}},
  167. )
  168. def test_event_fields_works_with_dot_keys(self):
  169. self.assertEquals(
  170. self.serialize(
  171. MockEvent(
  172. sender="@alice:localhost",
  173. room_id="!foo:bar",
  174. content={"key.with.dots": {}},
  175. ),
  176. [r"content.key\.with\.dots"],
  177. ),
  178. {"content": {"key.with.dots": {}}},
  179. )
  180. def test_event_fields_works_with_nested_dot_keys(self):
  181. self.assertEquals(
  182. self.serialize(
  183. MockEvent(
  184. sender="@alice:localhost",
  185. room_id="!foo:bar",
  186. content={
  187. "not_me": 1,
  188. "nested.dot.key": {"leaf.key": 42, "not_me_either": 1},
  189. },
  190. ),
  191. [r"content.nested\.dot\.key.leaf\.key"],
  192. ),
  193. {"content": {"nested.dot.key": {"leaf.key": 42}}},
  194. )
  195. def test_event_fields_nops_with_unknown_keys(self):
  196. self.assertEquals(
  197. self.serialize(
  198. MockEvent(
  199. sender="@alice:localhost",
  200. room_id="!foo:bar",
  201. content={"foo": "bar"},
  202. ),
  203. ["content.foo", "content.notexists"],
  204. ),
  205. {"content": {"foo": "bar"}},
  206. )
  207. def test_event_fields_nops_with_non_dict_keys(self):
  208. self.assertEquals(
  209. self.serialize(
  210. MockEvent(
  211. sender="@alice:localhost",
  212. room_id="!foo:bar",
  213. content={"foo": ["I", "am", "an", "array"]},
  214. ),
  215. ["content.foo.am"],
  216. ),
  217. {},
  218. )
  219. def test_event_fields_nops_with_array_keys(self):
  220. self.assertEquals(
  221. self.serialize(
  222. MockEvent(
  223. sender="@alice:localhost",
  224. room_id="!foo:bar",
  225. content={"foo": ["I", "am", "an", "array"]},
  226. ),
  227. ["content.foo.1"],
  228. ),
  229. {},
  230. )
  231. def test_event_fields_all_fields_if_empty(self):
  232. self.assertEquals(
  233. self.serialize(
  234. MockEvent(
  235. type="foo",
  236. event_id="test",
  237. room_id="!foo:bar",
  238. content={"foo": "bar"},
  239. ),
  240. [],
  241. ),
  242. {
  243. "type": "foo",
  244. "event_id": "test",
  245. "room_id": "!foo:bar",
  246. "content": {"foo": "bar"},
  247. "unsigned": {},
  248. },
  249. )
  250. def test_event_fields_fail_if_fields_not_str(self):
  251. with self.assertRaises(TypeError):
  252. self.serialize(
  253. MockEvent(room_id="!foo:bar", content={"foo": "bar"}), ["room_id", 4]
  254. )
  255. class CopyPowerLevelsContentTestCase(unittest.TestCase):
  256. def setUp(self) -> None:
  257. self.test_content = {
  258. "ban": 50,
  259. "events": {"m.room.name": 100, "m.room.power_levels": 100},
  260. "events_default": 0,
  261. "invite": 50,
  262. "kick": 50,
  263. "notifications": {"room": 20},
  264. "redact": 50,
  265. "state_default": 50,
  266. "users": {"@example:localhost": 100},
  267. "users_default": 0,
  268. }
  269. def _test(self, input):
  270. a = copy_power_levels_contents(input)
  271. self.assertEqual(a["ban"], 50)
  272. self.assertEqual(a["events"]["m.room.name"], 100)
  273. # make sure that changing the copy changes the copy and not the orig
  274. a["ban"] = 10
  275. a["events"]["m.room.power_levels"] = 20
  276. self.assertEqual(input["ban"], 50)
  277. self.assertEqual(input["events"]["m.room.power_levels"], 100)
  278. def test_unfrozen(self):
  279. self._test(self.test_content)
  280. def test_frozen(self):
  281. input = freeze(self.test_content)
  282. self._test(input)