123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370open!ImportopenQuickcheck_intfopenBase_quickcheckmoduleFloat=Base.FloatmoduleInt=Base.IntmoduleList=Base.ListmoduleOption=Base.OptionmoduleSet=Base.SetmoduleSexp=Base.SexpmodulePolymorphic_types=structtype('a,'b)variant2=[`Aof'a|`Bof'b][@@derivingquickcheck]type('a,'b,'c)variant3=[`Aof'a|`Bof'b|`Cof'c][@@derivingquickcheck]type('a,'b,'c,'d)variant4=[`Aof'a|`Bof'b|`Cof'c|`Dof'd][@@derivingquickcheck]type('a,'b,'c,'d,'e)variant5=[`Aof'a|`Bof'b|`Cof'c|`Dof'd|`Eof'e][@@derivingquickcheck]type('a,'b,'c,'d,'e,'f)variant6=[`Aof'a|`Bof'b|`Cof'c|`Dof'd|`Eof'e|`Fof'f][@@derivingquickcheck]type('a,'b)tuple2='a*'b[@@derivingquickcheck]type('a,'b,'c)tuple3='a*'b*'c[@@derivingquickcheck]type('a,'b,'c,'d)tuple4='a*'b*'c*'d[@@derivingquickcheck]type('a,'b,'c,'d,'e)tuple5='a*'b*'c*'d*'e[@@derivingquickcheck]type('a,'b,'c,'d,'e,'f)tuple6='a*'b*'c*'d*'e*'f[@@derivingquickcheck]type(-'a,-'b,'r)fn2='a->'b->'r[@@derivingquickcheck]type(-'a,-'b,-'c,'r)fn3='a->'b->'c->'r[@@derivingquickcheck]type(-'a,-'b,-'c,-'d,'r)fn4='a->'b->'c->'d->'r[@@derivingquickcheck]type(-'a,-'b,-'c,-'d,-'e,'r)fn5='a->'b->'c->'d->'e->'r[@@derivingquickcheck]type(-'a,-'b,-'c,-'d,-'e,-'f,'r)fn6='a->'b->'c->'d->'e->'f->'r[@@derivingquickcheck]endmoduleObserver=structincludeObserverletof_hash(typea)(moduleM:Deriving_hashwithtypet=a)=of_hash_foldM.hash_fold_t;;letvariant2=Polymorphic_types.quickcheck_observer_variant2letvariant3=Polymorphic_types.quickcheck_observer_variant3letvariant4=Polymorphic_types.quickcheck_observer_variant4letvariant5=Polymorphic_types.quickcheck_observer_variant5letvariant6=Polymorphic_types.quickcheck_observer_variant6lettuple2=Polymorphic_types.quickcheck_observer_tuple2lettuple3=Polymorphic_types.quickcheck_observer_tuple3lettuple4=Polymorphic_types.quickcheck_observer_tuple4lettuple5=Polymorphic_types.quickcheck_observer_tuple5lettuple6=Polymorphic_types.quickcheck_observer_tuple6letof_predicateab~f=unmap(variant2ab)~f:(funx->iffxthen`Axelse`Bx)letsingleton()=opaqueletdoubletonf=of_predicate(singleton())(singleton())~fletenum_~f=unmapint~fletof_listlist~equal=letfx=matchList.findilist~f:(fun_y->equalxy)with|None->failwith"Quickcheck.Observer.of_list: value not found"|Some(i,_)->iinenum(List.lengthlist)~f;;letof_funf=create(funx~size~hash->observe(f())x~size~hash)letcomparison~compare~eq~lt~gt=unmap(variant3lt(singleton())gt)~f:(funx->letc=comparexeqinifc<0then`Axelseifc>0then`Cxelse`Bx);;endmoduleGenerator=structincludeGeneratoropenLet_syntaxletsingleton=returnletdoubletonxy=create(fun~size:_~random->ifSplittable_random.boolrandomthenxelsey);;letof_funf=create(fun~size~random->generate(f())~size~random)letof_sequence~pseq=ifFloat.(<=)p0.||Float.(>)p1.thenfailwith(Printf.sprintf"Generator.of_sequence: probability [%f] out of bounds"p);Sequence.delayed_foldseq~init:()~finish:(fun()->failwith"Generator.of_sequence: ran out of values")~f:(fun()x~k->weighted_union[p,singletonx;1.-.p,of_funk]);;letgeometric=Generator.int_geometricletsmall_non_negative_int=small_positive_or_zero_intletsmall_positive_int=small_strictly_positive_intletlist_with_lengthlengtht=list_with_lengtht~lengthletvariant2=Polymorphic_types.quickcheck_generator_variant2letvariant3=Polymorphic_types.quickcheck_generator_variant3letvariant4=Polymorphic_types.quickcheck_generator_variant4letvariant5=Polymorphic_types.quickcheck_generator_variant5letvariant6=Polymorphic_types.quickcheck_generator_variant6lettuple2=Polymorphic_types.quickcheck_generator_tuple2lettuple3=Polymorphic_types.quickcheck_generator_tuple3lettuple4=Polymorphic_types.quickcheck_generator_tuple4lettuple5=Polymorphic_types.quickcheck_generator_tuple5lettuple6=Polymorphic_types.quickcheck_generator_tuple6letfn2=Polymorphic_types.quickcheck_generator_fn2letfn3=Polymorphic_types.quickcheck_generator_fn3letfn4=Polymorphic_types.quickcheck_generator_fn4letfn5=Polymorphic_types.quickcheck_generator_fn5letfn6=Polymorphic_types.quickcheck_generator_fn6letcompare_fndom=fndomint>>|funget_indexxy->[%compare:int](get_indexx)(get_indexy);;letequal_fndom=compare_fndom>>|funcmpxy->Int.(=)(cmpxy)0endmoduleShrinker=structincludeShrinkerletempty()=atomicletvariant2=Polymorphic_types.quickcheck_shrinker_variant2letvariant3=Polymorphic_types.quickcheck_shrinker_variant3letvariant4=Polymorphic_types.quickcheck_shrinker_variant4letvariant5=Polymorphic_types.quickcheck_shrinker_variant5letvariant6=Polymorphic_types.quickcheck_shrinker_variant6lettuple2=Polymorphic_types.quickcheck_shrinker_tuple2lettuple3=Polymorphic_types.quickcheck_shrinker_tuple3lettuple4=Polymorphic_types.quickcheck_shrinker_tuple4lettuple5=Polymorphic_types.quickcheck_shrinker_tuple5lettuple6=Polymorphic_types.quickcheck_shrinker_tuple6endmoduleLet_syntax=structmoduleLet_syntax=structincludeGeneratormoduleOpen_on_rhs=GeneratorendincludeGenerator.Monad_infixletreturn=Generator.returnendmoduleConfigure(Config:Quickcheck_config)=structincludeConfigletnondeterministic_state=lazy(Random.State.make_self_init())letrandom_state_of_seedseed=matchseedwith|`Nondeterministic->Splittable_random.create(forcenondeterministic_state)|`Deterministicstr->Splittable_random.of_int([%hash:string]str);;letmake_seedseed:Test.Config.Seed.t=matchseedwith|`Nondeterministic->Nondeterministic|`Deterministicstring->Deterministicstring;;letmake_shrink_count=function|`Exhaustive->Int.max_value|`Limitn->n;;letmake_config~seed~sizes~trials~shrink_attempts:Test.Config.t={seed=make_seed(Option.valueseed~default:default_seed);sizes=Option.valuesizes~default:default_sizes;test_count=Option.valuetrials~default:default_trial_count;shrink_count=make_shrink_count(Option.valueshrink_attempts~default:default_shrink_attempts)};;letmake_test_m(typea)~gen~shrinker~sexp_of:(moduleTest.Swithtypet=a)=letmoduleM=structtypet=aletquickcheck_generator=genletquickcheck_shrinker=Option.valueshrinker~default:Shrinker.atomicletsexp_of_t=Option.valuesexp_of~default:[%sexp_of:_]endin(moduleM);;letrandom_value?(seed=default_seed)?(size=30)gen=letrandom=random_state_of_seedseedinGenerator.generategen~size~random;;letrandom_sequence?seed?sizesgen=letconfig=make_config~seed~sizes~trials:(SomeInt.max_value)~shrink_attempts:Noneinletreturn=refSequence.emptyinTest.with_sample_exn~configgen~f:(funsequence->return:=sequence);!return;;letiter?seed?sizes?trialsgen~f=letconfig=make_config~seed~sizes~trials~shrink_attempts:NoneinTest.with_sample_exn~configgen~f:(funsequence->Sequence.itersequence~f);;lettest?seed?sizes?trials?shrinker?shrink_attempts?sexp_of?examplesgen~f=letconfig=make_config~seed~sizes~trials~shrink_attemptsinlettest_m=make_test_m~gen~shrinker~sexp_ofinTest.run_exn~config?examples~ftest_m;;lettest_or_error?seed?sizes?trials?shrinker?shrink_attempts?sexp_of?examplesgen~f=letconfig=make_config~seed~sizes~trials~shrink_attemptsinlettest_m=make_test_m~gen~shrinker~sexp_ofinTest.run~config?examples~ftest_m;;lettest_distinct_values(typekey)?seed?sizes?sexp_ofgen~trials~distinct_values~compare=letmoduleM=structtypet=keylet(compare:t->t->int)=compareletsexp_of_t=matchsexp_ofwith|Somesexp_of->sexp_of|None->sexp_of_opaque;;include(valComparator.make~compare~sexp_of_t)endinletfailset=letexpect_count=distinct_valuesinletactual_count=Set.lengthsetinletvalues=matchsexp_ofwith|None->None|Somesexp_of_elt->Some[%sexp(Set.to_listset:eltlist)]inraise_s[%message"insufficient distinct values"(trials:int)(expect_count:int)(actual_count:int)(values:(Sexp.toption[@sexp.option]))]inwith_return(funr->letset=ref(Set.empty(moduleM))initer?seed?sizes~trialsgen~f:(funelt->set:=Set.add!setelt;ifSet.length!set>=distinct_valuesthenr.return());fail!set);;lettest_can_generate?seed?sizes?(trials=default_can_generate_trial_count)?sexp_ofgen~f=letr=ref[]inletf_and_enqueuereturnx=iffxthenreturn`Can_generateelser:=x::!rinmatchWith_return.with_return(funreturn->iter?seed?sizes~trialsgen~f:(f_and_enqueuereturn.return);`Cannot_generate)with|`Can_generate->()|`Cannot_generate->(matchsexp_ofwith|None->failwith"cannot generate"|Somesexp_of_value->Error.raise_s[%message"cannot generate"~attempts:(!r:valuelist)]);;endincludeConfigure(structletdefault_seed=`Deterministic"an arbitrary but deterministic string"letdefault_trial_count=matchWord_size.word_sizewith|W64->10_000|W32->1_000;;letdefault_can_generate_trial_count=10_000letdefault_shrink_attempts=`Limit1000letdefault_sizes=Sequence.cycle_list_exn(List.range030~stop:`inclusive)end)moduletypeS=SmoduletypeS1=S1moduletypeS2=S2moduletypeS_int=S_intmoduletypeS_range=S_rangetypenonrecseed=seedtypenonrecshrink_attempts=shrink_attemptsmoduletypeQuickcheck_config=Quickcheck_configmoduletypeQuickcheck_configured=Quickcheck_configured