Skip to content

Commit 6a5e471

Browse files
cthoytshaypal5
authored andcommitted
Add tests for memory core
@shaypal5 these are copied from the pickle tests, the only one failing is test_memory_being_calculated. I could use your help with the implementation of the relevant function becuase I don't think I understand the threading part
1 parent 37eef3a commit 6a5e471

File tree

1 file changed

+270
-0
lines changed

1 file changed

+270
-0
lines changed

tests/test_memory_core.py

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
"""Test for the in-memory implementation of the Cachier python package."""
2+
3+
import hashlib
4+
import queue
5+
import threading
6+
from datetime import timedelta
7+
from random import random
8+
from time import sleep, time
9+
10+
import pandas as pd
11+
12+
from cachier import cachier
13+
14+
15+
@cachier(backend='memory', next_time=False)
16+
def _takes_5_seconds(arg_1, arg_2):
17+
"""Some function."""
18+
sleep(5)
19+
return 'arg_1:{}, arg_2:{}'.format(arg_1, arg_2)
20+
21+
22+
def test_memory_core():
23+
"""Basic memory core functionality."""
24+
_takes_5_seconds.clear_cache()
25+
_takes_5_seconds('a', 'b')
26+
start = time()
27+
_takes_5_seconds('a', 'b', verbose_cache=True)
28+
end = time()
29+
assert end - start < 1
30+
_takes_5_seconds.clear_cache()
31+
32+
33+
SECONDS_IN_DELTA = 3
34+
DELTA = timedelta(seconds=SECONDS_IN_DELTA)
35+
36+
37+
@cachier(backend='memory', stale_after=DELTA, next_time=False)
38+
def _stale_after_seconds(arg_1, arg_2):
39+
"""Some function."""
40+
return random()
41+
42+
43+
def test_stale_after():
44+
"""Testing the stale_after functionality."""
45+
_stale_after_seconds.clear_cache()
46+
val1 = _stale_after_seconds(1, 2)
47+
val2 = _stale_after_seconds(1, 2)
48+
val3 = _stale_after_seconds(1, 3)
49+
assert val1 == val2
50+
assert val1 != val3
51+
sleep(3)
52+
val4 = _stale_after_seconds(1, 2)
53+
assert val4 != val1
54+
_stale_after_seconds.clear_cache()
55+
56+
57+
@cachier(backend='memory', stale_after=DELTA, next_time=True)
58+
def _stale_after_next_time(arg_1, arg_2):
59+
"""Some function."""
60+
return random()
61+
62+
63+
def test_stale_after_next_time():
64+
"""Testing the stale_after with next_time functionality."""
65+
_stale_after_next_time.clear_cache()
66+
val1 = _stale_after_next_time(1, 2)
67+
val2 = _stale_after_next_time(1, 2)
68+
val3 = _stale_after_next_time(1, 3)
69+
assert val1 == val2
70+
assert val1 != val3
71+
sleep(SECONDS_IN_DELTA + 1)
72+
val4 = _stale_after_next_time(1, 2)
73+
assert val4 == val1
74+
sleep(0.5)
75+
val5 = _stale_after_next_time(1, 2)
76+
assert val5 != val1
77+
_stale_after_next_time.clear_cache()
78+
79+
80+
@cachier(backend='memory')
81+
def _random_num():
82+
return random()
83+
84+
85+
@cachier(backend='memory')
86+
def _random_num_with_arg(a):
87+
# print(a)
88+
return random()
89+
90+
91+
def test_overwrite_cache():
92+
"""Tests that the overwrite feature works correctly."""
93+
_random_num.clear_cache()
94+
int1 = _random_num()
95+
int2 = _random_num()
96+
assert int2 == int1
97+
int3 = _random_num(overwrite_cache=True)
98+
assert int3 != int1
99+
int4 = _random_num()
100+
assert int4 == int3
101+
_random_num.clear_cache()
102+
103+
_random_num_with_arg.clear_cache()
104+
int1 = _random_num_with_arg('a')
105+
int2 = _random_num_with_arg('a')
106+
assert int2 == int1
107+
int3 = _random_num_with_arg('a', overwrite_cache=True)
108+
assert int3 != int1
109+
int4 = _random_num_with_arg('a')
110+
assert int4 == int3
111+
_random_num_with_arg.clear_cache()
112+
113+
114+
def test_ignore_cache():
115+
"""Tests that the ignore_cache feature works correctly."""
116+
_random_num.clear_cache()
117+
int1 = _random_num()
118+
int2 = _random_num()
119+
assert int2 == int1
120+
int3 = _random_num(ignore_cache=True)
121+
assert int3 != int1
122+
int4 = _random_num()
123+
assert int4 != int3
124+
assert int4 == int1
125+
_random_num.clear_cache()
126+
127+
_random_num_with_arg.clear_cache()
128+
int1 = _random_num_with_arg('a')
129+
int2 = _random_num_with_arg('a')
130+
assert int2 == int1
131+
int3 = _random_num_with_arg('a', ignore_cache=True)
132+
assert int3 != int1
133+
int4 = _random_num_with_arg('a')
134+
assert int4 != int3
135+
assert int4 == int1
136+
_random_num_with_arg.clear_cache()
137+
138+
139+
@cachier(backend='memory')
140+
def _takes_time(arg_1, arg_2):
141+
"""Some function."""
142+
sleep(2) # this has to be enough time for check_calculation to run twice
143+
return random() + arg_1 + arg_2
144+
145+
146+
def _calls_takes_time(res_queue):
147+
res = _takes_time(0.13, 0.02)
148+
res_queue.put(res)
149+
150+
151+
def test_memory_being_calculated():
152+
"""Testing memory core handling of being calculated scenarios."""
153+
_takes_time.clear_cache()
154+
res_queue = queue.Queue()
155+
thread1 = threading.Thread(target=_calls_takes_time, kwargs={'res_queue': res_queue})
156+
thread2 = threading.Thread(target=_calls_takes_time, kwargs={'res_queue': res_queue})
157+
thread1.start()
158+
sleep(0.5)
159+
thread2.start()
160+
thread1.join()
161+
thread2.join()
162+
assert res_queue.qsize() == 2
163+
res1 = res_queue.get()
164+
res2 = res_queue.get()
165+
assert res1 == res2
166+
167+
168+
@cachier(backend='memory', stale_after=timedelta(seconds=1), next_time=True)
169+
def _being_calc_next_time(arg_1, arg_2):
170+
"""Some function."""
171+
sleep(1)
172+
return random() + arg_1 + arg_2
173+
174+
175+
def _calls_being_calc_next_time(res_queue):
176+
res = _being_calc_next_time(0.13, 0.02)
177+
res_queue.put(res)
178+
179+
180+
def test_being_calc_next_time():
181+
"""Testing memory core handling of being calculated scenarios."""
182+
_takes_time.clear_cache()
183+
_being_calc_next_time(0.13, 0.02)
184+
sleep(1.1)
185+
res_queue = queue.Queue()
186+
thread1 = threading.Thread(
187+
target=_calls_being_calc_next_time, kwargs={'res_queue': res_queue})
188+
thread2 = threading.Thread(
189+
target=_calls_being_calc_next_time, kwargs={'res_queue': res_queue})
190+
thread1.start()
191+
sleep(0.5)
192+
thread2.start()
193+
thread1.join()
194+
thread2.join()
195+
assert res_queue.qsize() == 2
196+
res1 = res_queue.get()
197+
res2 = res_queue.get()
198+
assert res1 == res2
199+
200+
201+
@cachier(backend='memory')
202+
def _bad_cache(arg_1, arg_2):
203+
"""Some function."""
204+
sleep(1)
205+
return random() + arg_1 + arg_2
206+
207+
208+
@cachier(backend='memory')
209+
def _delete_cache(arg_1, arg_2):
210+
"""Some function."""
211+
sleep(1)
212+
return random() + arg_1 + arg_2
213+
214+
215+
def test_clear_being_calculated():
216+
"""Test memory core clear `being calculated` functionality."""
217+
_takes_time.clear_being_calculated()
218+
219+
220+
@cachier(backend='memory', stale_after=timedelta(seconds=1), next_time=True)
221+
def _error_throwing_func(arg1):
222+
if not hasattr(_error_throwing_func, 'count'):
223+
_error_throwing_func.count = 0
224+
_error_throwing_func.count += 1
225+
if _error_throwing_func.count > 1:
226+
raise ValueError("Tiny Rick!")
227+
return 7
228+
229+
230+
def test_error_throwing_func():
231+
# with
232+
res1 = _error_throwing_func(4)
233+
sleep(1.5)
234+
res2 = _error_throwing_func(4)
235+
assert res1 == res2
236+
237+
238+
def test_callable_hash_param():
239+
def _hash_params(args, kwargs):
240+
def _hash(obj):
241+
if isinstance(obj, pd.core.frame.DataFrame):
242+
return hashlib.sha256(pd.util.hash_pandas_object(obj).values.tobytes()).hexdigest()
243+
return obj
244+
245+
k_args = tuple(map(_hash, args))
246+
k_kwargs = tuple(sorted({k: _hash(v) for k, v in kwargs.items()}.items()))
247+
return k_args + k_kwargs
248+
249+
@cachier(backend='memory', hash_params=_hash_params)
250+
def _params_with_dataframe(*args, **kwargs):
251+
"""Some function."""
252+
return random()
253+
254+
_params_with_dataframe.clear_cache()
255+
256+
df_a = pd.DataFrame.from_dict(dict(a=[0], b=[2], c=[3]))
257+
df_b = pd.DataFrame.from_dict(dict(a=[0], b=[2], c=[3]))
258+
value_a = _params_with_dataframe(df_a, 1)
259+
value_b = _params_with_dataframe(df_b, 1)
260+
261+
assert value_a == value_b # same content --> same key
262+
263+
value_a = _params_with_dataframe(1, df=df_a)
264+
value_b = _params_with_dataframe(1, df=df_b)
265+
266+
assert value_a == value_b # same content --> same key
267+
268+
269+
if __name__ == '__main__':
270+
test_memory_being_calculated()

0 commit comments

Comments
 (0)