test_receipts.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. # Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com>
  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 copy import deepcopy
  15. from typing import List
  16. from parameterized import parameterized
  17. from synapse.api.constants import EduTypes, ReceiptTypes
  18. from synapse.types import JsonDict
  19. from tests import unittest
  20. class ReceiptsTestCase(unittest.HomeserverTestCase):
  21. def prepare(self, reactor, clock, hs):
  22. self.event_source = hs.get_event_sources().sources.receipt
  23. @parameterized.expand(
  24. [ReceiptTypes.READ_PRIVATE, ReceiptTypes.UNSTABLE_READ_PRIVATE]
  25. )
  26. def test_filters_out_private_receipt(self, receipt_type: str) -> None:
  27. self._test_filters_private(
  28. [
  29. {
  30. "content": {
  31. "$1435641916114394fHBLK:matrix.org": {
  32. receipt_type: {
  33. "@rikj:jki.re": {
  34. "ts": 1436451550453,
  35. }
  36. }
  37. }
  38. },
  39. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  40. "type": EduTypes.RECEIPT,
  41. }
  42. ],
  43. [],
  44. )
  45. @parameterized.expand(
  46. [ReceiptTypes.READ_PRIVATE, ReceiptTypes.UNSTABLE_READ_PRIVATE]
  47. )
  48. def test_filters_out_private_receipt_and_ignores_rest(
  49. self, receipt_type: str
  50. ) -> None:
  51. self._test_filters_private(
  52. [
  53. {
  54. "content": {
  55. "$1dgdgrd5641916114394fHBLK:matrix.org": {
  56. receipt_type: {
  57. "@rikj:jki.re": {
  58. "ts": 1436451550453,
  59. },
  60. },
  61. ReceiptTypes.READ: {
  62. "@user:jki.re": {
  63. "ts": 1436451550453,
  64. },
  65. },
  66. },
  67. },
  68. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  69. "type": EduTypes.RECEIPT,
  70. }
  71. ],
  72. [
  73. {
  74. "content": {
  75. "$1dgdgrd5641916114394fHBLK:matrix.org": {
  76. ReceiptTypes.READ: {
  77. "@user:jki.re": {
  78. "ts": 1436451550453,
  79. }
  80. }
  81. }
  82. },
  83. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  84. "type": EduTypes.RECEIPT,
  85. }
  86. ],
  87. )
  88. @parameterized.expand(
  89. [ReceiptTypes.READ_PRIVATE, ReceiptTypes.UNSTABLE_READ_PRIVATE]
  90. )
  91. def test_filters_out_event_with_only_private_receipts_and_ignores_the_rest(
  92. self, receipt_type: str
  93. ) -> None:
  94. self._test_filters_private(
  95. [
  96. {
  97. "content": {
  98. "$14356419edgd14394fHBLK:matrix.org": {
  99. receipt_type: {
  100. "@rikj:jki.re": {
  101. "ts": 1436451550453,
  102. },
  103. }
  104. },
  105. "$1435641916114394fHBLK:matrix.org": {
  106. ReceiptTypes.READ: {
  107. "@user:jki.re": {
  108. "ts": 1436451550453,
  109. }
  110. }
  111. },
  112. },
  113. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  114. "type": EduTypes.RECEIPT,
  115. }
  116. ],
  117. [
  118. {
  119. "content": {
  120. "$1435641916114394fHBLK:matrix.org": {
  121. ReceiptTypes.READ: {
  122. "@user:jki.re": {
  123. "ts": 1436451550453,
  124. }
  125. }
  126. }
  127. },
  128. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  129. "type": EduTypes.RECEIPT,
  130. }
  131. ],
  132. )
  133. def test_handles_empty_event(self) -> None:
  134. self._test_filters_private(
  135. [
  136. {
  137. "content": {
  138. "$143564gdfg6114394fHBLK:matrix.org": {},
  139. "$1435641916114394fHBLK:matrix.org": {
  140. ReceiptTypes.READ: {
  141. "@user:jki.re": {
  142. "ts": 1436451550453,
  143. }
  144. }
  145. },
  146. },
  147. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  148. "type": EduTypes.RECEIPT,
  149. }
  150. ],
  151. [
  152. {
  153. "content": {
  154. "$1435641916114394fHBLK:matrix.org": {
  155. ReceiptTypes.READ: {
  156. "@user:jki.re": {
  157. "ts": 1436451550453,
  158. }
  159. }
  160. },
  161. },
  162. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  163. "type": EduTypes.RECEIPT,
  164. }
  165. ],
  166. )
  167. @parameterized.expand(
  168. [ReceiptTypes.READ_PRIVATE, ReceiptTypes.UNSTABLE_READ_PRIVATE]
  169. )
  170. def test_filters_out_receipt_event_with_only_private_receipt_and_ignores_rest(
  171. self, receipt_type: str
  172. ) -> None:
  173. self._test_filters_private(
  174. [
  175. {
  176. "content": {
  177. "$14356419edgd14394fHBLK:matrix.org": {
  178. receipt_type: {
  179. "@rikj:jki.re": {
  180. "ts": 1436451550453,
  181. },
  182. }
  183. },
  184. },
  185. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  186. "type": EduTypes.RECEIPT,
  187. },
  188. {
  189. "content": {
  190. "$1435641916114394fHBLK:matrix.org": {
  191. ReceiptTypes.READ: {
  192. "@user:jki.re": {
  193. "ts": 1436451550453,
  194. }
  195. }
  196. },
  197. },
  198. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  199. "type": EduTypes.RECEIPT,
  200. },
  201. ],
  202. [
  203. {
  204. "content": {
  205. "$1435641916114394fHBLK:matrix.org": {
  206. ReceiptTypes.READ: {
  207. "@user:jki.re": {
  208. "ts": 1436451550453,
  209. }
  210. }
  211. }
  212. },
  213. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  214. "type": EduTypes.RECEIPT,
  215. }
  216. ],
  217. )
  218. def test_handles_string_data(self) -> None:
  219. """
  220. Tests that an invalid shape for read-receipts is handled.
  221. Context: https://github.com/matrix-org/synapse/issues/10603
  222. """
  223. self._test_filters_private(
  224. [
  225. {
  226. "content": {
  227. "$14356419edgd14394fHBLK:matrix.org": {
  228. ReceiptTypes.READ: {
  229. "@rikj:jki.re": "string",
  230. }
  231. },
  232. },
  233. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  234. "type": EduTypes.RECEIPT,
  235. },
  236. ],
  237. [
  238. {
  239. "content": {
  240. "$14356419edgd14394fHBLK:matrix.org": {
  241. ReceiptTypes.READ: {
  242. "@rikj:jki.re": "string",
  243. }
  244. },
  245. },
  246. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  247. "type": EduTypes.RECEIPT,
  248. },
  249. ],
  250. )
  251. @parameterized.expand(
  252. [ReceiptTypes.READ_PRIVATE, ReceiptTypes.UNSTABLE_READ_PRIVATE]
  253. )
  254. def test_leaves_our_private_and_their_public(self, receipt_type: str) -> None:
  255. self._test_filters_private(
  256. [
  257. {
  258. "content": {
  259. "$1dgdgrd5641916114394fHBLK:matrix.org": {
  260. receipt_type: {
  261. "@me:server.org": {
  262. "ts": 1436451550453,
  263. },
  264. },
  265. ReceiptTypes.READ: {
  266. "@rikj:jki.re": {
  267. "ts": 1436451550453,
  268. },
  269. },
  270. "a.receipt.type": {
  271. "@rikj:jki.re": {
  272. "ts": 1436451550453,
  273. },
  274. },
  275. },
  276. },
  277. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  278. "type": EduTypes.RECEIPT,
  279. }
  280. ],
  281. [
  282. {
  283. "content": {
  284. "$1dgdgrd5641916114394fHBLK:matrix.org": {
  285. receipt_type: {
  286. "@me:server.org": {
  287. "ts": 1436451550453,
  288. },
  289. },
  290. ReceiptTypes.READ: {
  291. "@rikj:jki.re": {
  292. "ts": 1436451550453,
  293. },
  294. },
  295. "a.receipt.type": {
  296. "@rikj:jki.re": {
  297. "ts": 1436451550453,
  298. },
  299. },
  300. }
  301. },
  302. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  303. "type": EduTypes.RECEIPT,
  304. }
  305. ],
  306. )
  307. @parameterized.expand(
  308. [ReceiptTypes.READ_PRIVATE, ReceiptTypes.UNSTABLE_READ_PRIVATE]
  309. )
  310. def test_we_do_not_mutate(self, receipt_type: str) -> None:
  311. """Ensure the input values are not modified."""
  312. events = [
  313. {
  314. "content": {
  315. "$1435641916114394fHBLK:matrix.org": {
  316. receipt_type: {
  317. "@rikj:jki.re": {
  318. "ts": 1436451550453,
  319. }
  320. }
  321. }
  322. },
  323. "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  324. "type": EduTypes.RECEIPT,
  325. }
  326. ]
  327. original_events = deepcopy(events)
  328. self._test_filters_private(events, [])
  329. # Since the events are fed in from a cache they should not be modified.
  330. self.assertEqual(events, original_events)
  331. def _test_filters_private(
  332. self, events: List[JsonDict], expected_output: List[JsonDict]
  333. ) -> None:
  334. """Tests that the _filter_out_private returns the expected output"""
  335. filtered_events = self.event_source.filter_out_private_receipts(
  336. events, "@me:server.org"
  337. )
  338. self.assertEqual(filtered_events, expected_output)