@@ -7,8 +7,51 @@ use std::*;
77
88use fail:: fail_point;
99
10+ #[ test]
11+ #[ cfg_attr( not( feature = "failpoints" ) , ignore) ]
12+ fn test_pause ( ) {
13+ let local_registry = fail:: new_fail_group ( ) ;
14+ local_registry. register_current ( ) ;
15+ let f = || {
16+ fail_point ! ( "pause" ) ;
17+ } ;
18+ f ( ) ;
19+
20+ fail:: cfg ( "pause" , "pause" ) . unwrap ( ) ;
21+ let ( tx, rx) = mpsc:: channel ( ) ;
22+ // control `f()` is executed before next failpoint config
23+ let ( tx_before, rx_before) = mpsc:: channel ( ) ;
24+ let thread_registry = local_registry. clone ( ) ;
25+ thread:: spawn ( move || {
26+ thread_registry. register_current ( ) ;
27+ // pause
28+ tx_before. send ( ( ) ) . unwrap ( ) ;
29+ tx. send ( f ( ) ) . unwrap ( ) ;
30+ // woken up by new order pause, and then pause again.
31+ tx_before. send ( ( ) ) . unwrap ( ) ;
32+ tx. send ( f ( ) ) . unwrap ( ) ;
33+ // woken up by remove, and then quit immediately.
34+ tx. send ( f ( ) ) . unwrap ( ) ;
35+ } ) ;
36+
37+ rx_before. recv ( ) . unwrap ( ) ;
38+ assert ! ( rx. recv_timeout( Duration :: from_millis( 2000 ) ) . is_err( ) ) ;
39+ fail:: cfg ( "pause" , "pause" ) . unwrap ( ) ;
40+ rx. recv_timeout ( Duration :: from_millis ( 500 ) ) . unwrap ( ) ;
41+
42+ rx_before. recv ( ) . unwrap ( ) ;
43+ assert ! ( rx. recv_timeout( Duration :: from_millis( 2000 ) ) . is_err( ) ) ;
44+ fail:: remove ( "pause" ) ;
45+
46+ rx. recv_timeout ( Duration :: from_millis ( 500 ) ) . unwrap ( ) ;
47+ rx. recv_timeout ( Duration :: from_millis ( 500 ) ) . unwrap ( ) ;
48+ }
49+
1050#[ test]
1151fn test_off ( ) {
52+ let local_registry = fail:: new_fail_group ( ) ;
53+ local_registry. register_current ( ) ;
54+
1255 let f = || {
1356 fail_point ! ( "off" , |_| 2 ) ;
1457 0
@@ -22,6 +65,9 @@ fn test_off() {
2265#[ test]
2366#[ cfg_attr( not( feature = "failpoints" ) , ignore) ]
2467fn test_return ( ) {
68+ let local_registry = fail:: new_fail_group ( ) ;
69+ local_registry. register_current ( ) ;
70+
2571 let f = || {
2672 fail_point ! ( "return" , |s: Option <String >| s
2773 . map_or( 2 , |s| s. parse( ) . unwrap( ) ) ) ;
@@ -39,6 +85,9 @@ fn test_return() {
3985#[ test]
4086#[ cfg_attr( not( feature = "failpoints" ) , ignore) ]
4187fn test_sleep ( ) {
88+ let local_registry = fail:: new_fail_group ( ) ;
89+ local_registry. register_current ( ) ;
90+
4291 let f = || {
4392 fail_point ! ( "sleep" ) ;
4493 } ;
@@ -56,6 +105,9 @@ fn test_sleep() {
56105#[ should_panic]
57106#[ cfg_attr( not( feature = "failpoints" ) , ignore) ]
58107fn test_panic ( ) {
108+ let local_registry = fail:: new_fail_group ( ) ;
109+ local_registry. register_current ( ) ;
110+
59111 let f = || {
60112 fail_point ! ( "panic" ) ;
61113 } ;
@@ -66,6 +118,9 @@ fn test_panic() {
66118#[ test]
67119#[ cfg_attr( not( feature = "failpoints" ) , ignore) ]
68120fn test_print ( ) {
121+ let local_registry = fail:: new_fail_group ( ) ;
122+ local_registry. register_current ( ) ;
123+
69124 struct LogCollector ( Arc < Mutex < Vec < String > > > ) ;
70125 impl log:: Log for LogCollector {
71126 fn enabled ( & self , _: & log:: Metadata ) -> bool {
@@ -97,38 +152,11 @@ fn test_print() {
97152 assert_eq ! ( msg, "failpoint print executed." ) ;
98153}
99154
100- #[ test]
101- #[ cfg_attr( not( feature = "failpoints" ) , ignore) ]
102- fn test_pause ( ) {
103- let f = || {
104- fail_point ! ( "pause" ) ;
105- } ;
106- f ( ) ;
107-
108- fail:: cfg ( "pause" , "pause" ) . unwrap ( ) ;
109- let ( tx, rx) = mpsc:: channel ( ) ;
110- thread:: spawn ( move || {
111- // pause
112- tx. send ( f ( ) ) . unwrap ( ) ;
113- // woken up by new order pause, and then pause again.
114- tx. send ( f ( ) ) . unwrap ( ) ;
115- // woken up by remove, and then quit immediately.
116- tx. send ( f ( ) ) . unwrap ( ) ;
117- } ) ;
118-
119- assert ! ( rx. recv_timeout( Duration :: from_millis( 500 ) ) . is_err( ) ) ;
120- fail:: cfg ( "pause" , "pause" ) . unwrap ( ) ;
121- rx. recv_timeout ( Duration :: from_millis ( 500 ) ) . unwrap ( ) ;
122-
123- assert ! ( rx. recv_timeout( Duration :: from_millis( 500 ) ) . is_err( ) ) ;
124- fail:: remove ( "pause" ) ;
125- rx. recv_timeout ( Duration :: from_millis ( 500 ) ) . unwrap ( ) ;
126-
127- rx. recv_timeout ( Duration :: from_millis ( 500 ) ) . unwrap ( ) ;
128- }
129-
130155#[ test]
131156fn test_yield ( ) {
157+ let local_registry = fail:: new_fail_group ( ) ;
158+ local_registry. register_current ( ) ;
159+
132160 let f = || {
133161 fail_point ! ( "yield" ) ;
134162 } ;
@@ -139,6 +167,9 @@ fn test_yield() {
139167#[ test]
140168#[ cfg_attr( not( feature = "failpoints" ) , ignore) ]
141169fn test_callback ( ) {
170+ let local_registry = fail:: new_fail_group ( ) ;
171+ local_registry. register_current ( ) ;
172+
142173 let f1 = || {
143174 fail_point ! ( "cb" ) ;
144175 } ;
@@ -160,6 +191,9 @@ fn test_callback() {
160191#[ test]
161192#[ cfg_attr( not( feature = "failpoints" ) , ignore) ]
162193fn test_delay ( ) {
194+ let local_registry = fail:: new_fail_group ( ) ;
195+ local_registry. register_current ( ) ;
196+
163197 let f = || fail_point ! ( "delay" ) ;
164198 let timer = Instant :: now ( ) ;
165199 fail:: cfg ( "delay" , "delay(1000)" ) . unwrap ( ) ;
@@ -170,6 +204,9 @@ fn test_delay() {
170204#[ test]
171205#[ cfg_attr( not( feature = "failpoints" ) , ignore) ]
172206fn test_freq_and_count ( ) {
207+ let local_registry = fail:: new_fail_group ( ) ;
208+ local_registry. register_current ( ) ;
209+
173210 let f = || {
174211 fail_point ! ( "freq_and_count" , |s: Option <String >| s
175212 . map_or( 2 , |s| s. parse( ) . unwrap( ) ) ) ;
@@ -191,6 +228,9 @@ fn test_freq_and_count() {
191228#[ test]
192229#[ cfg_attr( not( feature = "failpoints" ) , ignore) ]
193230fn test_condition ( ) {
231+ let local_registry = fail:: new_fail_group ( ) ;
232+ local_registry. register_current ( ) ;
233+
194234 let f = |_enabled| {
195235 fail_point ! ( "condition" , _enabled, |_| 2 ) ;
196236 0
@@ -205,9 +245,61 @@ fn test_condition() {
205245
206246#[ test]
207247fn test_list ( ) {
248+ let local_registry = fail:: new_fail_group ( ) ;
249+ local_registry. register_current ( ) ;
250+
208251 assert ! ( !fail:: list( ) . contains( & ( "list" . to_string( ) , "off" . to_string( ) ) ) ) ;
209252 fail:: cfg ( "list" , "off" ) . unwrap ( ) ;
210253 assert ! ( fail:: list( ) . contains( & ( "list" . to_string( ) , "off" . to_string( ) ) ) ) ;
211254 fail:: cfg ( "list" , "return" ) . unwrap ( ) ;
212255 assert ! ( fail:: list( ) . contains( & ( "list" . to_string( ) , "return" . to_string( ) ) ) ) ;
213256}
257+
258+ #[ test]
259+ fn test_multiple_threads_cleanup ( ) {
260+ let local_registry = fail:: new_fail_group ( ) ;
261+ local_registry. register_current ( ) ;
262+
263+ let ( tx, rx) = mpsc:: channel ( ) ;
264+ thread:: spawn ( move || {
265+ local_registry. register_current ( ) ;
266+ fail:: cfg ( "thread_point" , "sleep(10)" ) . unwrap ( ) ;
267+ tx. send ( ( ) ) . unwrap ( ) ;
268+ } ) ;
269+ rx. recv ( ) . unwrap ( ) ;
270+ let l = fail:: list ( ) ;
271+ assert ! (
272+ l. iter( )
273+ . find( |& x| x == & ( "thread_point" . to_owned( ) , "sleep(10)" . to_owned( ) ) )
274+ . is_some( )
275+ && l. len( ) == 1
276+ ) ;
277+
278+ let ( tx, rx) = mpsc:: channel ( ) ;
279+ let t = thread:: spawn ( move || {
280+ let local_registry = fail:: new_fail_group ( ) ;
281+ local_registry. register_current ( ) ;
282+ fail:: cfg ( "thread_point" , "panic" ) . unwrap ( ) ;
283+ let l = fail:: list ( ) ;
284+ assert ! (
285+ l. iter( )
286+ . find( |& x| x == & ( "thread_point" . to_owned( ) , "panic" . to_owned( ) ) )
287+ . is_some( )
288+ && l. len( ) == 1
289+ ) ;
290+ rx. recv ( ) . unwrap ( ) ;
291+ local_registry. cleanup ( ) ;
292+ let l = fail:: list ( ) ;
293+ assert ! ( l. is_empty( ) ) ;
294+ } ) ;
295+
296+ tx. send ( ( ) ) . unwrap ( ) ;
297+ let l = fail:: list ( ) ;
298+ assert ! (
299+ l. iter( )
300+ . find( |& x| x == & ( "thread_point" . to_owned( ) , "sleep(10)" . to_owned( ) ) )
301+ . is_some( )
302+ && l. len( ) == 1
303+ ) ;
304+ t. join ( ) . unwrap ( ) ;
305+ }
0 commit comments