123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263openLinmoduleMake_internal(Spec:Internal.CmdSpec[@alert"-internal"])=structmoduleM=Internal.Make(Spec)[@alert"-internal"]includeMletalloc_callback_src=Thread.yield();Noneletyield_tracker=Gc.Memprof.{null_trackerwithalloc_minor=alloc_callback;alloc_major=alloc_callback;}(* Note: On purpose we use
- a non-tail-recursive function and
- an (explicit) allocation in the loop body
since both trigger statistically significant more thread issues/interleaving *)letrecinterp_threadsutcs=matchcswith|[]->[]|c::cs->Thread.yield();letres=Spec.runcsutin(c,res)::interp_threadsutcsletarb_cmds_triple=arb_cmds_triple(* Linearization property based on [Thread] *)letlin_prop(seq_pref,cmds1,cmds2)=letsut=Spec.init()inletobs1,obs2=ref(Ok[]),ref(Ok[])in(* Gc.Memprof.{start,stop} raises Failure on OCaml 5.0 and 5.1 *)(tryignore(Gc.Memprof.start~sampling_rate:1e-1~callstack_size:0yield_tracker)withFailure_->());letpref_obs=interp_plainsutseq_prefinletwait=reftrueinletth1=Thread.create(fun()->while!waitdoThread.yield()done;obs1:=tryOk(interp_threadsutcmds1)withexn->Errorexn)()inletth2=Thread.create(fun()->wait:=false;obs2:=tryOk(interp_threadsutcmds2)withexn->Errorexn)()inThread.jointh1;Thread.jointh2;(tryGc.Memprof.stop()withFailure_->());Spec.cleanupsut;letobs1=match!obs1withOkv->refv|Errorexn->raiseexninletobs2=match!obs2withOkv->refv|Errorexn->raiseexninletseq_sut=Spec.init()in(* we reuse [check_seq_cons] to linearize and interpret sequentially *)check_seq_conspref_obs!obs1!obs2seq_sut[]||QCheck.Test.fail_reportf" Results incompatible with sequential execution\n\n%s"@@Util.print_triple_vertical~fig_indent:5~res_width:35(fun(c,r)->Printf.sprintf"%s : %s"(Spec.show_cmdc)(Spec.show_resr))(pref_obs,!obs1,!obs2)(* Common magic constants *)letrep_count=3(* No. of repetitions of the non-deterministic property *)letretries=25(* Additional factor of repetition during shrinking *)letlin_test~count~name=lin_test~rep_count~count~retries~name~lin_propletneg_lin_test~count~name=neg_lin_test~rep_count~count~retries~name~lin_propendmoduleMake(Spec:Spec)=Make_internal(MakeCmd(Spec))