123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106openBasetype'atest_pred=?here:Lexing.positionlist->?message:string->('a->bool)->'a->unittype'atest_eq=?here:Lexing.positionlist->?message:string->?equal:('a->'a->bool)->'a->'a->unittype'atest_result=?here:Lexing.positionlist->?message:string->?equal:('a->'a->bool)->expect:'a->'a->unitexceptionEofstring*Sexp.t[@@derivingsexp]letexn_sexp_style~message~pos~here~tagbody=letmessage=matchmessagewith|None->tag|Somes->s^": "^taginletsexp=Sexp.List(body@[Sexp.List[Sexp.Atom"Loc";Sexp.Atompos]]@beginmatchherewith|[]->[]|_->[Sexp.List[Sexp.Atom"Stack";[%sexp_of:Source_code_position.tlist]here]]end)in(* Here and in other places we return exceptions, rather than directly raising, and
instead raise at the latest moment possible, so backtrace don't include noise from
these functions that construct exceptions. *)E(message,sexp)let[@cold]exn_test_pred~message~pos~here~sexpifiert=exn_sexp_style~message~pos~here~tag:"predicate failed"[Sexp.List[Sexp.Atom"Value";sexpifiert]]lettest_pred~pos~sexpifier~here?messagepredicatet=ifnot(predicatet)thenraise(exn_test_pred~message~pos~here~sexpifiert)letr_diff:(from_:string->to_:string->unit)optionref=refNoneletset_diff_functionf=r_diff:=flet[@cold]test_result_or_eq_failed~sexpifier~expect~got=letgot=sexpifiergotinletexpect=sexpifierexpectinbeginmatch!r_diffwith|None->()|Somediff->letfrom_=Sexp.to_string_humexpectinletto_=Sexp.to_string_humgotindiff~from_~to_end;`Fail(expect,got)lettest_result_or_eq~sexpifier~comparator~equal~expect~got=letpass=matchequalwith|None->comparatorgotexpect=0|Somef->fgotexpectinifpassthen`Passelsetest_result_or_eq_failed~sexpifier~expect~gotlet[@cold]exn_test_eq~message~pos~here~t1~t2=exn_sexp_style~message~pos~here~tag:"comparison failed"[t1;Sexp.Atom"vs";t2;]lettest_eq~pos~sexpifier~comparator~here?message?equalt1t2=matchtest_result_or_eq~sexpifier~comparator~equal~expect:t1~got:t2with|`Pass->()|`Fail(t1,t2)->raise(exn_test_eq~message~pos~here~t1~t2)let[@cold]exn_test_result~message~pos~here~expect~got=exn_sexp_style~message~pos~here~tag:"got unexpected result"[Sexp.List[Sexp.Atom"expected";expect];Sexp.List[Sexp.Atom"got";got];]let[@warning"-16"]test_result~pos~sexpifier~comparator~here?message?equal~expect~got=matchtest_result_or_eq~sexpifier~comparator~equal~expect~gotwith|`Pass->()|`Fail(expect,got)->raise(exn_test_result~message~pos~here~expect~got)