-
Notifications
You must be signed in to change notification settings - Fork 148
/
test_decorators.py
159 lines (113 loc) · 4.33 KB
/
test_decorators.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import asyncio
import pytest
import random
from unittest import mock
from aiocache import cached, cached_stampede, multi_cached
async def return_dict(keys=None):
ret = {}
for value, key in enumerate(keys or ['a', 'd', 'z', 'y']):
ret[key] = str(value)
return ret
async def stub(*args, key=None, seconds=0, **kwargs):
await asyncio.sleep(seconds)
if key:
return str(key)
return str(random.randint(1, 50))
class TestCached:
@pytest.fixture(autouse=True)
def default_cache(self, mocker, cache):
mocker.patch("aiocache.decorators._get_cache", return_value=cache)
@pytest.mark.asyncio
async def test_cached_ttl(self, cache):
@cached(ttl=1, key=pytest.KEY)
async def fn():
return str(random.randint(1, 50))
resp1 = await fn()
resp2 = await fn()
assert await cache.get(pytest.KEY) == resp1 == resp2
await asyncio.sleep(1)
assert await cache.get(pytest.KEY) is None
@pytest.mark.asyncio
async def test_cached_key_builder(self, cache):
def build_key(self, a, b):
return "{}_{}_{}".format(self, a, b)
@cached(key_builder=build_key)
async def fn(self, a, b=2):
return "1"
await fn('self', 1, 3)
assert await cache.exists(build_key('self', 1, 3)) is True
class TestCachedStampede:
@pytest.fixture(autouse=True)
def default_cache(self, mocker, cache):
mocker.patch("aiocache.decorators._get_cache", return_value=cache)
@pytest.mark.asyncio
async def test_cached_stampede(self, mocker, cache):
mocker.spy(cache, 'get')
mocker.spy(cache, 'set')
decorator = cached_stampede(ttl=10, lease=2)
await asyncio.gather(
decorator(stub)(1),
decorator(stub)(1))
cache.get.assert_called_with('acceptance.test_decoratorsstub(1,)[]')
assert cache.get.call_count == 4
cache.set.assert_called_with(
'acceptance.test_decoratorsstub(1,)[]', mock.ANY, ttl=10)
assert cache.set.call_count == 1
@pytest.mark.asyncio
async def test_locking_dogpile_lease_expiration(self, mocker, cache):
mocker.spy(cache, 'get')
mocker.spy(cache, 'set')
decorator = cached_stampede(ttl=10, lease=1)
await asyncio.gather(
decorator(stub)(1, seconds=2),
decorator(stub)(1, seconds=2))
assert cache.get.call_count == 4
assert cache.set.call_count == 2
class TestMultiCachedDecorator:
@pytest.fixture(autouse=True)
def default_cache(self, mocker, cache):
mocker.patch("aiocache.decorators._get_cache", return_value=cache)
@pytest.mark.asyncio
async def test_multi_cached(self, cache):
multi_cached_decorator = multi_cached('keys')
default_keys = {'a', 'd', 'z', 'y'}
await multi_cached_decorator(return_dict)(keys=default_keys)
for key in default_keys:
assert await cache.get(key) is not None
@pytest.mark.asyncio
async def test_multi_cached_key_builder(self, cache):
def build_key(key, self, keys, market='ES'):
return "{}_{}".format(key, market)
@multi_cached(keys_from_attr='keys', key_builder=build_key)
async def fn(self, keys, market='ES'):
return {'a': 1, 'b': 2}
await fn('self', keys=['a', 'b'])
assert await cache.exists('a_ES') is True
assert await cache.exists('b_ES') is True
@pytest.mark.asyncio
async def test_fn_with_args(self, cache):
@multi_cached('keys')
async def fn(keys, *args):
assert len(args) == 1
return {'a': 1}
await fn(['a'], 1)
assert await cache.exists('a') is True
@pytest.mark.asyncio
async def test_keys_without_kwarg(self, cache):
@multi_cached('keys')
async def fn(keys):
return {'a': 1}
await fn(['a'])
assert await cache.exists('a') is True
@pytest.mark.asyncio
async def test_double_decorator(self, cache):
def dummy_d(fn):
async def wrapper(*args, **kwargs):
await fn(*args, **kwargs)
return wrapper
@dummy_d
@multi_cached('keys')
async def fn(keys):
return {'a': 1}
await fn(['a'])
assert await cache.exists('a') is True