77% % The while module is ifdef:ed, rebar should set PULSE
88-ifdef (PULSE ).
99
10- -compile (export_all ).
10+ -compile ([ export_all , nowarn_export_all ] ).
1111
1212-include_lib (" eqc/include/eqc.hrl" ).
1313-include_lib (" eqc/include/eqc_statem.hrl" ).
1414
1515-include (" ../include/bitcask.hrl" ).
1616
17- -include_lib (" eunit/include/eunit.hrl" ).
18-
1917-compile ({parse_transform , pulse_instrument }).
2018-include_lib (" pulse_otp/include/pulse_otp.hrl" ).
2119% % The following functions contains side_effects but are run outside
2220% % PULSE, i.e. PULSE needs to leave them alone
23- -compile ({pulse_skip ,[{prop_pulse_test_ , 0 },
24- {really_delete_bitcask , 0 },
21+ -compile ({pulse_skip ,[{really_delete_bitcask , 0 },
2522 {copy_bitcask_app , 0 },
2623 {get_errors , 0 }]}).
2724-compile ({pulse_no_side_effect ,[{file ,'_' ,'_' }, {erlang , now , 0 }]}).
2825
29- % % The token module keeps track of the currently used directory for
30- % % bitcask. Each test uses a fresh directory!
26+ % % Each test uses a fresh directory!
3127-define (BITCASK , token :get_name ()).
28+ % % -define(BITCASK, filename:join(?TEST_FILEPATH, "bitcask.qc." ++ os:getpid())).
29+ % % -define(BITCASK, "bitcask.qc." ++ os:getpid()).
30+
3231% % Number of keys used in the tests
3332-define (NUM_KEYS , 50 ).
3433% % max_file_size given to bitcask.
@@ -310,7 +309,7 @@ run_on_node(slave, Verbose, M, F, A) ->
310309
311310% % Muting the QuickCheck license printout from the slave node
312311mute (true , Fun ) -> Fun ();
313- mute (false , Fun ) -> mute :run (Fun ).
312+ mute (false , Fun ) -> Fun (). % mute:run(Fun).
314313
315314% %
316315% % The actual code of the property, run on remote node via rpc:call above
@@ -320,15 +319,15 @@ run_commands_on_node(LocalOrSlave, Cmds, Seed, Verbose, KeepFiles) ->
320319 AfterTime = if LocalOrSlave == local -> 50000 ;
321320 LocalOrSlave == slave -> 1000000
322321 end ,
323- event_logger :start_link (),
324322 pulse :start (),
325323 error_logger :tty (false ),
326324 error_logger :add_report_handler (handle_errors ),
327325 token :next_name (),
328- event_logger :start_logging (),
329326 X =
330327 try
331328 {H , S , Res , PidRs , Trace } = pulse :run (fun () ->
329+ event_logger :start_link (),
330+ event_logger :start_logging (),
332331 application_controller :start ({application , kernel , []}),
333332 application :start (bitcask ),
334333 bitcask_time :test__set_fudge (10 ),
@@ -341,6 +340,7 @@ run_commands_on_node(LocalOrSlave, Cmds, Seed, Verbose, KeepFiles) ->
341340 pulse :verbose (OldVerbose ),
342341 Trace = event_logger :get_events (),
343342 receive after AfterTime -> ok end ,
343+ application :stop (bitcask ),
344344 unlink (whereis (pulse_application_controller )),
345345 exit (pulse_application_controller , shutdown ),
346346 receive after AfterTime -> ok end ,
@@ -363,6 +363,19 @@ run_commands_on_node(LocalOrSlave, Cmds, Seed, Verbose, KeepFiles) ->
363363get_errors () ->
364364 gen_event :call (error_logger , handle_errors , get_errors , 60 * 1000 ).
365365
366+ run_tests (Args ) ->
367+ try list_to_integer (atom_to_list (hd (Args ))) of
368+ N ->
369+ case quickcheck (eqc :testing_time (N , prop_pulse ())) of
370+ true -> erlang :halt ();
371+ false -> erlang :halt (1 )
372+ end
373+ catch _ :_ ->
374+ io :format (" Bad arguments: ~p \n " , [Args ]),
375+ timer :sleep (10 ),
376+ erlang :halt (2 )
377+ end .
378+
366379prop_pulse () ->
367380 prop_pulse (local , false , false ).
368381
@@ -388,8 +401,10 @@ prop_pulse(LocalOrSlave, Verbose0, KeepFiles) ->
388401 io :format (user , " GOT ~p , aborting. Stop PULSE and restart!\n " , [Bad ]),
389402 exit ({stopping , Bad });
390403 {H , S , Res , PidRs , Trace , Schedule , Errors0 } ->
391- Errors = [E || E <- Errors0 ,
392- re :run (element (2 , E ), " Invalid merge input" ) == nomatch ],
404+ Errors = [E || is_list (Errors0 ),
405+ E <- Errors0 ,
406+ re :run (element (2 , E ), " Invalid merge input" ) == nomatch ] ++
407+ [Errors0 || not is_list (Errors0 )],
393408 ? WHENFAIL (
394409 ? QC_FMT (" \n State: ~p \n " , [S ]),
395410 aggregate (zipwith (fun command_data /2 , tl (Cmds ), H ),
@@ -414,56 +429,6 @@ prop_pulse(LocalOrSlave, Verbose0, KeepFiles) ->
414429 end
415430 end )))))).
416431
417- % % A EUnit wrapper for the QuickCheck property
418- prop_pulse_test_ () ->
419- Timeout = case os :getenv (" PULSE_TIME" ) of
420- false -> 60 ;
421- Val -> list_to_integer (Val )
422- end ,
423- ExtraTO = case os :getenv (" PULSE_SHRINK_TIME" ) of
424- false -> 0 ;
425- Val2 -> list_to_integer (Val2 )
426- end ,
427- % % eqc has the irritating behavior of not asking for a license for
428- % % its entire test time at the start of the test. the following
429- % % code calulates the amount of time remaining and then reserves
430- % % the license until then, so long running tests won't fail
431- % % because the license server becomes unreachable sometime in the
432- % % middle of the test.
433- {D , {H , M0 , S }} = calendar :time_difference (calendar :local_time (),
434- eqc :reserved_until ()),
435- % % any minutes or seconds at all and we should just bump up to the
436- % % next hour
437- M =
438- case (M0 + S ) of
439- 0 ->
440- 0 ;
441- _N ->
442- 1
443- end ,
444- HoursLeft = (D * 24 ) + H + M ,
445- HoursAsked = trunc ((Timeout + ExtraTO )/ 60 / 60 ),
446- case HoursLeft < HoursAsked of
447- true -> eqc :reserve ({HoursAsked , hours });
448- false -> ok
449- end ,
450- io :format (user , " prop_pulse_test time: ~p + ~p seconds\n " ,
451- [Timeout , ExtraTO ]),
452- {timeout , (Timeout + ExtraTO + 120 ), % 120 = a bit more fudge time
453- fun () ->
454- copy_bitcask_app (),
455- ? assert (eqc :quickcheck (eqc :testing_time (Timeout ,
456- ? QC_OUT (prop_pulse ()))))
457- end }.
458-
459- % % Needed since rebar fails miserably in setting up the .eunit test directory
460- copy_bitcask_app () ->
461- try
462- {ok , B } = file :read_file (" ../ebin/bitcask.app" ),
463- ok = file :write_file (" ./bitcask.app" , B )
464- catch _ :_ -> ok end ,
465- ok .
466-
467432% % Using eqc_temporal to keep track of possible values for keys.
468433% %
469434% % The Trace contains entries for start and finish of operations. For
@@ -1127,7 +1092,9 @@ really_delete_bitcask() ->
11271092 [file :delete (X ) || X <- filelib :wildcard (? BITCASK ++ " /*" )],
11281093 file :del_dir (? BITCASK ),
11291094 case file :read_file_info (? BITCASK ) of
1130- {error , enoent } -> ok ;
1095+ {error , enoent } ->
1096+ timer :sleep (10 ),
1097+ ok ;
11311098 {ok , _ } ->
11321099 timer :sleep (10 ),
11331100 really_delete_bitcask ()
0 commit comments