@@ -35,41 +35,208 @@ def test_lock_no_renew(self):
35
35
self .fail ("should not raise an exception" )
36
36
37
37
self .mock .lock .assert_not_called ()
38
- self .mock .unlock .assert_called_once ()
39
38
self .mock .lock_renew .assert_called_once ()
39
+ self .mock .unlock .assert_called_once ()
40
40
41
41
42
42
def test_lock_with_renew (self ):
43
43
try :
44
44
with self .testEvaWithLocker :
45
- time .sleep (0.02 )
45
+ time .sleep (0.015 )
46
46
except Exception :
47
47
self .fail ("should not raise an exception" )
48
48
49
49
self .mock .lock .assert_not_called ()
50
+ self .assertEqual (self .mock .lock_renew .call_count , 2 )
50
51
self .mock .unlock .assert_called_once ()
51
- assert self .mock .lock_renew .call_count == 2
52
52
53
53
54
- def test_double_lock_should_raise (self ):
54
+ def test_not_locked_should_raise (self ):
55
+ self .mock .lock_renew .side_effect = Exception ("can't renew an unlocked eva" )
56
+
57
+ with self .assertRaises (Exception ):
58
+ with self .testEvaWithLocker :
59
+ self .fail ("did not raise exception when renewing a not locked Eva" )
60
+
61
+ self .mock .lock .assert_not_called ()
62
+ self .mock .lock_renew .assert_called_once ()
63
+ self .mock .unlock .assert_not_called ()
64
+
65
+
66
+ def test_nested_locker_same_period_should_raise (self ):
55
67
with self .assertRaises (Exception ):
56
68
with self .testEvaWithLocker :
57
69
with self .testEvaWithLocker :
58
70
self .fail ("did not raise exception when locking an already locked Eva" )
71
+
59
72
self .mock .lock .assert_not_called ()
60
- self .mock .unlock .assert_called_once ()
61
73
self .mock .lock_renew .assert_called_once ()
74
+ self .mock .unlock .assert_called_once ()
62
75
63
76
64
- def test_not_locked_should_raise (self ):
65
- self .mock .lock_renew .side_effect = Exception ("can't renew a unlocked eva" )
77
+ def test_nested_locker_entry_and_exit_renews_lock (self ):
78
+ try :
79
+ with self .testEvaWithLocker :
80
+ with self .testEvaWithLocker .set_renew_period (1 ):
81
+ pass
82
+ except Exception :
83
+ self .fail ("should not raise an exception" )
84
+
85
+ self .mock .lock .assert_not_called ()
86
+ self .assertEqual (self .mock .lock_renew .call_count , 3 )
87
+ self .mock .unlock .assert_called_once ()
88
+
89
+
90
+ def test_nested_locker_different_period_with_inner_renew (self ):
91
+ try :
92
+ with self .testEvaWithLocker :
93
+ time .sleep (0.005 )
94
+ with self .testEvaWithLocker .set_renew_period (0.05 ):
95
+ time .sleep (0.09 )
96
+ except Exception :
97
+ self .fail ("should not raise an exception" )
98
+
99
+ self .mock .lock .assert_not_called ()
100
+ self .assertEqual (self .mock .lock_renew .call_count , 4 )
101
+ self .mock .unlock .assert_called_once ()
102
+
103
+
104
+ def test_nested_locker_different_period_with_outer_renew (self ):
105
+ try :
106
+ with self .testEvaWithLocker :
107
+ with self .testEvaWithLocker .set_renew_period (0.1 ):
108
+ time .sleep (0.01 )
109
+ time .sleep (0.015 )
110
+ except Exception :
111
+ self .fail ("should not raise an exception" )
112
+
113
+ self .mock .lock .assert_not_called ()
114
+ self .assertEqual (self .mock .lock_renew .call_count , 4 )
115
+ self .mock .unlock .assert_called_once ()
116
+
117
+
118
+ def test_nested_locker_reset_on_outer_exit (self ):
119
+ try :
120
+ # 3 renews from this context
121
+ with self .testEvaWithLocker :
122
+ with self .testEvaWithLocker .set_renew_period (0.1 ):
123
+ pass
124
+
125
+ with self .testEvaWithLocker :
126
+ # Sleep duration < 0.1s should still cause a renew
127
+ time .sleep (0.015 )
128
+ except Exception :
129
+ self .fail ("should not raise an exception" )
130
+
131
+ self .mock .lock .assert_not_called ()
132
+ self .assertEqual (self .mock .lock_renew .call_count , 5 )
133
+ self .assertEqual (self .mock .unlock .call_count , 2 )
134
+
135
+
136
+ def test_deeply_nested_contexts (self ):
137
+ try :
138
+ with self .testEvaWithLocker :
139
+ with self .testEvaWithLocker .set_renew_period (0.3 ):
140
+ with self .testEvaWithLocker .set_renew_period (0.45 ):
141
+ with self .testEvaWithLocker .set_renew_period (0.075 ):
142
+ # Sleep duration should cause a renew here
143
+ time .sleep (0.078 )
144
+ except Exception :
145
+ self .fail ("should not raise an exception" )
146
+
147
+ self .mock .lock .assert_not_called ()
148
+ self .assertEqual (self .mock .lock_renew .call_count , 8 )
149
+ self .mock .unlock .assert_called_once ()
150
+
151
+
152
+ def test_locker_has_default_period (self ):
153
+ self .testEvaWithLocker = EvaWithLocker (self .mock )
154
+
155
+ try :
156
+ with self .testEvaWithLocker :
157
+ # To avoid long tests: Sleep duration shorter than
158
+ # the relatively long default should not cause a renew here
159
+ time .sleep (0.5 )
160
+ except Exception :
161
+ self .fail ("should not raise an exception" )
162
+
163
+ self .mock .lock .assert_not_called ()
164
+ self .assertEqual (self .mock .lock_renew .call_count , 1 )
165
+ self .mock .unlock .assert_called_once ()
166
+
167
+
168
+ def test_can_set_period_to_default (self ):
169
+ try :
170
+ with self .testEvaWithLocker :
171
+ with self .testEvaWithLocker .set_renew_period (1 ):
172
+ with self .testEvaWithLocker .set_renew_period ():
173
+ # Sleep duration should cause a renew here
174
+ time .sleep (0.011 )
175
+ except Exception :
176
+ self .fail ("should not raise an exception" )
177
+
178
+ self .mock .lock .assert_not_called ()
179
+ self .assertEqual (self .mock .lock_renew .call_count , 6 )
180
+ self .mock .unlock .assert_called_once ()
181
+
182
+
183
+ def test_nested_locker_uses_last_set_period (self ):
184
+ try :
185
+ with self .testEvaWithLocker :
186
+ self .testEvaWithLocker .set_renew_period (0.02 )
187
+ with self .testEvaWithLocker .set_renew_period (0.1 ):
188
+ # Sleep duration should not cause a renew here
189
+ time .sleep (0.05 )
190
+ except Exception :
191
+ self .fail ("should not raise an exception" )
192
+
193
+ self .mock .lock .assert_not_called ()
194
+ self .assertEqual (self .mock .lock_renew .call_count , 3 )
195
+ self .mock .unlock .assert_called_once ()
196
+
197
+
198
+ def test_nested_locker_returns_to_parent_period (self ):
199
+ try :
200
+ with self .testEvaWithLocker :
201
+ # Each sleep duration should cause a single renew here
202
+ with self .testEvaWithLocker .set_renew_period (0.1 ):
203
+ time .sleep (0.11 )
204
+ time .sleep (0.011 )
205
+ except Exception :
206
+ self .fail ("should not raise an exception" )
207
+
208
+ self .mock .lock .assert_not_called ()
209
+ self .assertEqual (self .mock .lock_renew .call_count , 5 )
210
+ self .mock .unlock .assert_called_once ()
211
+
212
+
213
+ def test_handles_nested_renew_failure_on_enter (self ):
214
+ self .mock .lock_renew .side_effect = [None , Exception ("Lock could not be renewed" )]
215
+
216
+ with self .assertRaises (Exception ):
217
+ with self .testEvaWithLocker :
218
+ with self .testEvaWithLocker .set_renew_period (0.1 ):
219
+ self .fail ("did not raise exception when renewing a not locked Eva" )
220
+
221
+ self .mock .lock .assert_not_called ()
222
+ self .assertEqual (self .mock .lock_renew .call_count , 2 )
223
+ # Should have final unlock
224
+ self .mock .unlock .assert_called_once ()
225
+
226
+
227
+ def test_handles_nested_renew_failure_on_exit (self ):
228
+ self .mock .lock_renew .side_effect = [None , None , Exception ("Lock could not be renewed" )]
66
229
67
230
with self .assertRaises (Exception ):
68
231
with self .testEvaWithLocker :
232
+ with self .testEvaWithLocker .set_renew_period (0.1 ):
233
+ pass
69
234
self .fail ("did not raise exception when renewing a not locked Eva" )
235
+
70
236
self .mock .lock .assert_not_called ()
71
- self .mock .unlock .assert_not_called ()
72
- self .mock .lock_renew .assert_called_once ()
237
+ self .assertEqual (self .mock .lock_renew .call_count , 3 )
238
+ # Should have final unlock
239
+ self .mock .unlock .assert_called_once ()
73
240
74
241
75
242
if __name__ == '__main__' :
0 commit comments