-
Notifications
You must be signed in to change notification settings - Fork 72
Expand file tree
/
Copy pathtest_recursion_depth.py
More file actions
147 lines (121 loc) · 4.16 KB
/
test_recursion_depth.py
File metadata and controls
147 lines (121 loc) · 4.16 KB
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
"""Tests for recursion depth protection in hash function."""
from datetime import timedelta
import pytest
from cachier import cachier
@pytest.mark.parametrize(
"backend",
[
pytest.param("memory", marks=pytest.mark.memory),
pytest.param("pickle", marks=pytest.mark.pickle),
],
)
def test_moderately_nested_structures_work(backend, tmp_path):
"""Verify that moderately nested structures (< 100 levels) work fine."""
call_count = 0
decorator_kwargs = {"backend": backend, "stale_after": timedelta(seconds=120)}
if backend == "pickle":
decorator_kwargs["cache_dir"] = tmp_path
@cachier(**decorator_kwargs)
def process_nested(data):
nonlocal call_count
call_count += 1
return "processed"
# Create a nested structure with 50 levels (well below the 100 limit)
nested_list = []
current = nested_list
for _ in range(50):
inner = []
current.append(inner)
current = inner
current.append("leaf")
# Should work without issues
result1 = process_nested(nested_list)
assert result1 == "processed"
assert call_count == 1
# Second call should hit cache
result2 = process_nested(nested_list)
assert result2 == "processed"
assert call_count == 1
process_nested.clear_cache()
@pytest.mark.parametrize(
"backend",
[
pytest.param("memory", marks=pytest.mark.memory),
pytest.param("pickle", marks=pytest.mark.pickle),
],
)
def test_deeply_nested_structures_raise_error(backend, tmp_path):
"""Verify that deeply nested structures (> 100 levels) raise RecursionError."""
decorator_kwargs = {"backend": backend, "stale_after": timedelta(seconds=120)}
if backend == "pickle":
decorator_kwargs["cache_dir"] = tmp_path
@cachier(**decorator_kwargs)
def process_nested(data):
return "processed"
# Create a nested structure with 150 levels (exceeds the 100 limit)
nested_list = []
current = nested_list
for _ in range(150):
inner = []
current.append(inner)
current = inner
current.append("leaf")
# Should raise RecursionError with a clear message
with pytest.raises(
RecursionError,
match=r"Maximum recursion depth \(100\) exceeded while hashing nested",
):
process_nested(nested_list)
@pytest.mark.parametrize(
"backend",
[
pytest.param("memory", marks=pytest.mark.memory),
pytest.param("pickle", marks=pytest.mark.pickle),
],
)
def test_nested_dicts_respect_depth_limit(backend, tmp_path):
"""Verify that nested dictionaries also respect the depth limit."""
decorator_kwargs = {"backend": backend, "stale_after": timedelta(seconds=120)}
if backend == "pickle":
decorator_kwargs["cache_dir"] = tmp_path
@cachier(**decorator_kwargs)
def process_dict(data):
return "processed"
# Create nested dictionaries beyond the limit
nested_dict = {}
current = nested_dict
for i in range(150):
current[f"level_{i}"] = {}
current = current[f"level_{i}"]
current["leaf"] = "value"
# Should raise RecursionError
with pytest.raises(
RecursionError,
match=r"Maximum recursion depth \(100\) exceeded while hashing nested",
):
process_dict(nested_dict)
@pytest.mark.parametrize(
"backend",
[
pytest.param("memory", marks=pytest.mark.memory),
pytest.param("pickle", marks=pytest.mark.pickle),
],
)
def test_nested_tuples_respect_depth_limit(backend, tmp_path):
"""Verify that nested tuples also respect the depth limit."""
decorator_kwargs = {"backend": backend, "stale_after": timedelta(seconds=120)}
if backend == "pickle":
decorator_kwargs["cache_dir"] = tmp_path
@cachier(**decorator_kwargs)
def process_tuple(data):
return "processed"
# Create nested tuples beyond the limit
nested_tuple = ("leaf",)
for _ in range(150):
nested_tuple = (nested_tuple,)
# Should raise RecursionError
with pytest.raises(
RecursionError,
match=r"Maximum recursion depth \(100\) exceeded while hashing nested",
):
process_tuple(nested_tuple)