123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250(**************************************************************************)(* The OUnit library *)(* *)(* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *)(* Copyright (C) 2010 OCamlCore SARL *)(* Copyright (C) 2013 Sylvain Le Gall *)(* *)(* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *)(* and Sylvain Le Gall. *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining *)(* a copy of this document and the OUnit software ("the Software"), to *)(* deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, *)(* sublicense, and/or sell copies of the Software, and to permit persons *)(* to whom the Software is furnished to do so, subject to the following *)(* conditions: *)(* *)(* The above copyright notice and this permission notice shall be *)(* included in all copies or substantial portions of the Software. *)(* *)(* The Software is provided ``as is'', without warranty of any kind, *)(* express or implied, including but not limited to the warranties of *)(* merchantability, fitness for a particular purpose and noninfringement. *)(* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *)(* or other liability, whether in an action of contract, tort or *)(* otherwise, arising from, out of or in connection with the Software or *)(* the use or other dealings in the software. *)(* *)(* See LICENSE.txt for details. *)(**************************************************************************)(**
Utilities for OUnit
@author Sylvain Le Gall
*)letis_blank=function|' '|'\012'|'\n'|'\r'|'\t'->true|_->falseletrectrims=letstrlen=String.lengthsinifstrlen=0then""elseifis_blanks.[0]thentrim(String.subs1(strlen-1))elseifis_blanks.[strlen-1]thentrim(String.subs0(strlen-1))elseslettrim_comments=letbuff=Buffer.create(String.lengths)inletidx=ref0inwhile!idx<String.lengths&&s.[!idx]!='#'doBuffer.add_charbuffs.[!idx];incridxdone;Buffer.contentsbuffletsplit_liness=letrev_lst=ref[]inletbuff=Buffer.create13inletflush()=rev_lst:=Buffer.contentsbuff::!rev_lst;Buffer.clearbuffinifString.lengths>0thenbeginString.iter(function|'\n'->flush()|c->Buffer.add_charbuffc)s;flush();List.rev!rev_lstendelse[]letstarts_with~prefixs=ifString.lengths>=String.lengthprefixthenString.subs0(String.lengthprefix)=prefixelsefalseletstart_substr~prefixs=ifstarts_with~prefixsthenbeginletprefix_len=String.lengthprefixintrue,String.subsprefix_len(String.lengths-prefix_len)endelsebeginfalse,sendletextract_backtrace_positionstr=letprefixes=["Raised at ";"Re-raised at ";"Raised by primitive operation at ";"Called from ";]inletrecextract_one_linesprefixes=matchprefixeswith|[]->None|prefix::tl->letreally_starts,eol=start_substr~prefixsinifreally_startsthenbeginifeol="unknown location"thenNoneelsetryScanf.sscanfeol"%_s@\"%s@\", line %d, characters %d-%d"(funfnline__->Some(fn,line))withScanf.Scan_failure_->Noneendelsebeginextract_one_linestlendinList.map(funs->extract_one_linesprefixes)(split_linesstr)letcmp_float?(epsilon=0.00001)ab=matchclassify_floata,classify_floatbwith|FP_infinite,FP_infinite->a=b|FP_infinite,_|_,FP_infinite|FP_nan,_|_,FP_nan->false|_,_->abs_float(a-.b)<=epsilon*.(abs_floata)||abs_float(a-.b)<=epsilon*.(abs_floatb)letbuff_format_printff=letbuff=Buffer.create13inletfmt=Format.formatter_of_bufferbuffinffmt;Format.pp_print_flushfmt();Buffer.contentsbuff(* Applies function f in turn to each element in list. Function f takes
one element, and integer indicating its location in the list *)letmapifl=letrecrmapicntl=matchlwith|[]->[]|h::t->(fhcnt)::(rmapi(cnt+1)t)inrmapi0lletfold_leftifaccul=letrecrfold_lefticntaccupl=matchlwith|[]->accup|h::t->rfold_lefti(cnt+1)(faccuphcnt)tinrfold_lefti0acculletnow()=Unix.gettimeofday()(* Function which runs the given function and returns the running time
of the function, and the original result in a tuple *)lettime_funfx=letbegin_time=now()inletres=fxin(now()-.begin_time,res)letdate_iso8601?(tz=true)timestamp=lettm=Unix.gmtimetimestampinletres=Printf.sprintf"%04d-%02d-%02dT%02d:%02d:%02d"(1900+tm.Unix.tm_year)(1+tm.Unix.tm_mon)tm.Unix.tm_mdaytm.Unix.tm_hourtm.Unix.tm_mintm.Unix.tm_seciniftzthenres^"+00:00"elseresletbuildir=(* Detect a location where we can store semi-temporary data:
- it must survive a compilation
- it must be removed with 'make clean'
*)letpwd=Sys.getcwd()inletdir_existsfn=Sys.file_existsfn&&Sys.is_directoryfninletconcat,dirname=Filename.concat,Filename.dirnameinList.finddir_exists[concatpwd"_build";concat(dirnamepwd)"_build";concat(dirname(dirnamepwd))"_build";pwd]letfailwithffmt=Printf.ksprintffailwithfmtletoptf=functionSomev->fv|None->()letfqdn()=try(Unix.gethostbyname(Unix.gethostname())).Unix.h_namewithNot_found->"localhost"letshardf=Printf.sprintf"%s#%02d"(Unix.gethostname())letstring_of_process_status=function|Unix.WEXITEDn->Printf.sprintf"Exited with code %d"n|Unix.WSIGNALEDn->Printf.sprintf"Killed by signal %d"n|Unix.WSTOPPEDn->Printf.sprintf"Stopped by signal %d"nletmake_counter()=letdata=Hashtbl.create13inletall()=Hashtbl.fold(funkvlst->(k,v)::lst)data[]inletincrk=letv=tryHashtbl.finddatakwithNot_found->0inHashtbl.replacedatak(v+1)inall,incr