3624
|
1 #!/usr/bin/env python3 |
|
2 |
|
3 # Libervia: an XMPP client |
|
4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) |
|
5 |
|
6 # This program is free software: you can redistribute it and/or modify |
|
7 # it under the terms of the GNU Affero General Public License as published by |
|
8 # the Free Software Foundation, either version 3 of the License, or |
|
9 # (at your option) any later version. |
|
10 |
|
11 # This program is distributed in the hope that it will be useful, |
|
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 # GNU Affero General Public License for more details. |
|
15 |
|
16 # You should have received a copy of the GNU Affero General Public License |
|
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
18 |
|
19 from twisted.internet import defer |
|
20 from pytest_twisted import ensureDeferred as ed |
|
21 from unittest.mock import MagicMock, patch |
|
22 from sat.memory.sqla import PubsubNode, SyncState |
|
23 from sat.core.constants import Const as C |
|
24 |
|
25 |
|
26 class TestPubsubCache: |
|
27 |
|
28 @ed |
|
29 async def test_cache_is_used_transparently(self, host, client): |
|
30 """Cache is used when a pubsub getItems operation is done""" |
|
31 items_ret = defer.Deferred() |
|
32 items_ret.callback(([], {})) |
|
33 client.pubsub_client.items = MagicMock(return_value=items_ret) |
|
34 host.memory.storage.getPubsubNode.return_value = None |
|
35 pubsub_node = host.memory.storage.setPubsubNode.return_value = PubsubNode( |
|
36 sync_state = None |
|
37 ) |
|
38 with patch.object(host.plugins["PUBSUB_CACHE"], "cacheNode") as cacheNode: |
|
39 await host.plugins["XEP-0060"].getItems( |
|
40 client, |
|
41 None, |
|
42 "urn:xmpp:microblog:0", |
|
43 ) |
|
44 assert cacheNode.call_count == 1 |
|
45 assert cacheNode.call_args.args[-1] == pubsub_node |
|
46 |
|
47 @ed |
|
48 async def test_cache_is_skipped_with_use_cache_false(self, host, client): |
|
49 """Cache is skipped when 'use_cache' extra field is False""" |
|
50 items_ret = defer.Deferred() |
|
51 items_ret.callback(([], {})) |
|
52 client.pubsub_client.items = MagicMock(return_value=items_ret) |
|
53 host.memory.storage.getPubsubNode.return_value = None |
|
54 host.memory.storage.setPubsubNode.return_value = PubsubNode( |
|
55 sync_state = None |
|
56 ) |
|
57 with patch.object(host.plugins["PUBSUB_CACHE"], "cacheNode") as cacheNode: |
|
58 await host.plugins["XEP-0060"].getItems( |
|
59 client, |
|
60 None, |
|
61 "urn:xmpp:microblog:0", |
|
62 extra = {C.KEY_USE_CACHE: False} |
|
63 ) |
|
64 assert not cacheNode.called |
|
65 |
|
66 @ed |
|
67 async def test_cache_is_not_used_when_no_cache(self, host, client): |
|
68 """Cache is skipped when 'pubsub_cache_strategy' is set to 'no_cache'""" |
|
69 with host.use_option_and_reload(None, "pubsub_cache_strategy", "no_cache"): |
|
70 items_ret = defer.Deferred() |
|
71 items_ret.callback(([], {})) |
|
72 client.pubsub_client.items = MagicMock(return_value=items_ret) |
|
73 host.memory.storage.getPubsubNode.return_value = None |
|
74 host.memory.storage.setPubsubNode.return_value = PubsubNode( |
|
75 sync_state = None |
|
76 ) |
|
77 with patch.object(host.plugins["PUBSUB_CACHE"], "cacheNode") as cacheNode: |
|
78 await host.plugins["XEP-0060"].getItems( |
|
79 client, |
|
80 None, |
|
81 "urn:xmpp:microblog:0", |
|
82 ) |
|
83 assert not cacheNode.called |
|
84 |
|
85 |
|
86 @ed |
|
87 async def test_no_pubsub_get_when_cache_completed(self, host, client): |
|
88 """No pubsub get is emitted when items are fully cached""" |
|
89 items_ret = defer.Deferred() |
|
90 items_ret.callback(([], {})) |
|
91 client.pubsub_client.items = MagicMock(return_value=items_ret) |
|
92 host.memory.storage.getPubsubNode.return_value = PubsubNode( |
|
93 sync_state = SyncState.COMPLETED |
|
94 ) |
|
95 with patch.object( |
|
96 host.plugins["PUBSUB_CACHE"], |
|
97 "getItemsFromCache" |
|
98 ) as getItemsFromCache: |
|
99 getItemsFromCache.return_value = ([], {}) |
|
100 await host.plugins["XEP-0060"].getItems( |
|
101 client, |
|
102 None, |
|
103 "urn:xmpp:microblog:0", |
|
104 ) |
|
105 assert getItemsFromCache.call_count == 1 |
|
106 assert not client.pubsub_client.items.called |
|
107 |
|
108 @ed |
|
109 async def test_pubsub_get_when_cache_in_progress(self, host, client): |
|
110 """Pubsub get is emitted when items are currently being cached""" |
|
111 items_ret = defer.Deferred() |
|
112 items_ret.callback(([], {})) |
|
113 client.pubsub_client.items = MagicMock(return_value=items_ret) |
|
114 host.memory.storage.getPubsubNode.return_value = PubsubNode( |
|
115 sync_state = SyncState.IN_PROGRESS |
|
116 ) |
|
117 with patch.object(host.plugins["PUBSUB_CACHE"], "analyseNode") as analyseNode: |
|
118 analyseNode.return_value = {"to_sync": True} |
|
119 with patch.object( |
|
120 host.plugins["PUBSUB_CACHE"], |
|
121 "getItemsFromCache" |
|
122 ) as getItemsFromCache: |
|
123 getItemsFromCache.return_value = ([], {}) |
|
124 assert client.pubsub_client.items.call_count == 0 |
|
125 await host.plugins["XEP-0060"].getItems( |
|
126 client, |
|
127 None, |
|
128 "urn:xmpp:microblog:0", |
|
129 ) |
|
130 assert not getItemsFromCache.called |
|
131 assert client.pubsub_client.items.call_count == 1 |