1111use plib:: { run_test, TestPlan } ;
1212use rand:: { seq:: SliceRandom , thread_rng} ;
1313
14- fn generate_valid_arguments ( n : Option < & str > , c : Option < & str > ) -> Vec < Vec < String > > {
15- let mut argument_forms = Vec :: < Vec < ( String , String ) > > :: new ( ) ;
14+ /* #region Normal tests */
15+ fn head_test ( n : Option < & str > , c : Option < & str > , test_data : & str , expected_output : & str ) {
16+ fn generate_valid_arguments ( n : Option < & str > , c : Option < & str > ) -> Vec < Vec < String > > {
17+ let mut argument_forms = Vec :: < Vec < ( String , String ) > > :: new ( ) ;
1618
17- let mut args_outer = Vec :: < ( String , String ) > :: new ( ) ;
19+ let mut args_outer = Vec :: < ( String , String ) > :: new ( ) ;
1820
19- for n_form in [ "-n" , "--lines" ] {
20- args_outer. clear ( ) ;
21+ for n_form in [ "-n" , "--lines" ] {
22+ args_outer. clear ( ) ;
2123
22- if let Some ( n_str) = n {
23- args_outer. push ( ( n_form. to_owned ( ) , n_str. to_owned ( ) ) ) ;
24- } ;
24+ if let Some ( n_str) = n {
25+ args_outer. push ( ( n_form. to_owned ( ) , n_str. to_owned ( ) ) ) ;
26+ } ;
2527
26- for c_form in [ "-c" , "--bytes" ] {
27- let mut args_inner = args_outer. clone ( ) ;
28+ for c_form in [ "-c" , "--bytes" ] {
29+ let mut args_inner = args_outer. clone ( ) ;
2830
29- if let Some ( c_str) = c {
30- args_inner. push ( ( c_form. to_owned ( ) , c_str. to_owned ( ) ) ) ;
31- } ;
31+ if let Some ( c_str) = c {
32+ args_inner. push ( ( c_form. to_owned ( ) , c_str. to_owned ( ) ) ) ;
33+ } ;
3234
33- argument_forms. push ( args_inner) ;
35+ argument_forms. push ( args_inner) ;
36+ }
3437 }
35- }
3638
37- argument_forms. shuffle ( & mut thread_rng ( ) ) ;
39+ argument_forms. shuffle ( & mut thread_rng ( ) ) ;
40+
41+ let mut flattened = Vec :: < Vec < String > > :: with_capacity ( argument_forms. len ( ) ) ;
3842
39- let mut flattened = Vec :: < Vec < String > > :: with_capacity ( argument_forms. len ( ) ) ;
43+ for ve in argument_forms {
44+ let mut vec = Vec :: < String > :: new ( ) ;
4045
41- for ve in argument_forms {
42- let mut vec = Vec :: < String > :: new ( ) ;
46+ for ( st, str) in ve {
47+ vec. push ( st) ;
48+ vec. push ( str) ;
49+ }
4350
44- for ( st, str) in ve {
45- vec. push ( st) ;
46- vec. push ( str) ;
51+ flattened. push ( vec) ;
4752 }
4853
49- flattened. push ( vec ) ;
54+ flattened
5055 }
5156
52- flattened
53- }
54-
55- /* #region Normal tests */
56- fn head_test ( n : Option < & str > , c : Option < & str > , test_data : & str , expected_output : & str ) {
5757 for ve in generate_valid_arguments ( n, c) {
5858 run_test ( TestPlan {
5959 cmd : "head" . to_owned ( ) ,
@@ -123,6 +123,11 @@ fn test_head_c() {
123123mod property_tests {
124124 use plib:: run_test_base;
125125 use proptest:: { prelude:: TestCaseError , prop_assert, test_runner:: TestRunner } ;
126+ use std:: {
127+ sync:: mpsc:: { self , RecvTimeoutError } ,
128+ thread:: { self } ,
129+ time:: Duration ,
130+ } ;
126131
127132 fn get_test_runner ( cases : u32 ) -> TestRunner {
128133 TestRunner :: new ( proptest:: test_runner:: Config {
@@ -134,7 +139,7 @@ mod property_tests {
134139 }
135140
136141 fn run_head_and_verify_output (
137- input : Vec < u8 > ,
142+ input : & [ u8 ] ,
138143 true_if_lines_false_if_bytes : bool ,
139144 count : usize ,
140145 ) -> Result < ( ) , TestCaseError > {
@@ -144,11 +149,7 @@ mod property_tests {
144149 "-c"
145150 } ;
146151
147- let output = run_test_base (
148- "head" ,
149- & vec ! [ n_or_c. to_owned( ) , count. to_string( ) ] ,
150- input. as_slice ( ) ,
151- ) ;
152+ let output = run_test_base ( "head" , & vec ! [ n_or_c. to_owned( ) , count. to_string( ) ] , input) ;
152153
153154 let stdout = & output. stdout ;
154155
@@ -167,8 +168,46 @@ mod property_tests {
167168 Ok ( ( ) )
168169 }
169170
171+ fn run_head_and_verify_output_with_timeout (
172+ true_if_lines_false_if_bytes : bool ,
173+ count : usize ,
174+ input : Vec < u8 > ,
175+ ) -> Result < ( ) , TestCaseError > {
176+ let ( sender, receiver) = mpsc:: channel :: < Result < ( ) , TestCaseError > > ( ) ;
177+
178+ let input_len = input. len ( ) ;
179+
180+ thread:: spawn ( move || {
181+ sender. send ( run_head_and_verify_output (
182+ input. as_slice ( ) ,
183+ true_if_lines_false_if_bytes,
184+ count,
185+ ) )
186+ } ) ;
187+
188+ match receiver. recv_timeout ( Duration :: from_secs ( 60_u64 ) ) {
189+ Ok ( result) => result,
190+ Err ( RecvTimeoutError :: Timeout ) => {
191+ eprint ! (
192+ "\
193+ head property test has been running for more than a minute. The spawned process will have to be killed manually.
194+
195+ true_if_lines_false_if_bytes: {true_if_lines_false_if_bytes}
196+ count: {count}
197+ input_len: {input_len}
198+ "
199+ ) ;
200+
201+ Err ( TestCaseError :: fail ( "Spawned process did not terminate" ) )
202+ }
203+ Err ( RecvTimeoutError :: Disconnected ) => {
204+ unreachable ! ( ) ;
205+ }
206+ }
207+ }
208+
170209 #[ test]
171- fn property_test_random ( ) {
210+ fn test_head_property_test_small_or_large ( ) {
172211 get_test_runner ( 16_u32 )
173212 . run (
174213 & (
@@ -177,14 +216,18 @@ mod property_tests {
177216 proptest:: collection:: vec ( proptest:: num:: u8:: ANY , 0_usize ..65_536_usize ) ,
178217 ) ,
179218 |( true_if_lines_false_if_bytes, count, input) | {
180- run_head_and_verify_output ( input, true_if_lines_false_if_bytes, count)
219+ run_head_and_verify_output_with_timeout (
220+ true_if_lines_false_if_bytes,
221+ count,
222+ input,
223+ )
181224 } ,
182225 )
183226 . unwrap ( ) ;
184227 }
185228
186229 #[ test]
187- fn property_test_small ( ) {
230+ fn test_head_property_test_small ( ) {
188231 get_test_runner ( 128_u32 )
189232 . run (
190233 & (
@@ -193,7 +236,31 @@ mod property_tests {
193236 proptest:: collection:: vec ( proptest:: num:: u8:: ANY , 0_usize ..16_384_usize ) ,
194237 ) ,
195238 |( true_if_lines_false_if_bytes, count, input) | {
196- run_head_and_verify_output ( input, true_if_lines_false_if_bytes, count)
239+ run_head_and_verify_output_with_timeout (
240+ true_if_lines_false_if_bytes,
241+ count,
242+ input,
243+ )
244+ } ,
245+ )
246+ . unwrap ( ) ;
247+ }
248+
249+ #[ test]
250+ fn test_head_property_test_very_small ( ) {
251+ get_test_runner ( 128_u32 )
252+ . run (
253+ & (
254+ proptest:: bool:: ANY ,
255+ ( 0_usize ..512_usize ) ,
256+ proptest:: collection:: vec ( proptest:: num:: u8:: ANY , 0_usize ..512_usize ) ,
257+ ) ,
258+ |( true_if_lines_false_if_bytes, count, input) | {
259+ run_head_and_verify_output_with_timeout (
260+ true_if_lines_false_if_bytes,
261+ count,
262+ input,
263+ )
197264 } ,
198265 )
199266 . unwrap ( ) ;
0 commit comments