(* Copyright (C) 2004, HELM Team. * * This file is part of HELM, an Hypertextual, Electronic * Library of Mathematics, developed at the Computer Science * Department, University of Bologna, Italy. * * HELM is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * HELM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HELM; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * For details, see the HELM World-Wide-Web page, * http://helm.cs.unibo.it/ *) open Printf let argc = Array.length Sys.argv let usage () = prerr_endline "Usage: regtest ..."; prerr_endline " regtest (-gen|--gen) ..."; exit 2 let rawsep = "###" let sep = Pcre.regexp rawsep let msg_prefix = "*** REGTEST *** " let print_msg s = prerr_endline (msg_prefix ^ s) type state = Term | EMetasenv | ETerm | EType | EReduced (* regtest file format * < cic term in concrete syntax > * separator (* see sep above *) * < expected cic term after disambiguation as PPed by CicPp.ppterm > * separator (* see sep above *) * < expected cic type as per type_of as PPed by CicPp.ppterm > * separator (* see sep above *) * < expected reduced cic term as PPed by CicPp.ppterm > *) type regtest = { term: string; (* raw cic term *) emetasenv : string; (* expected metasenv *) eterm: string; (* expected term *) etype: string; (* expected type *) ereduced: string; (* expected reduced term *) } (* this should be the only function here printing on stdout *) let print_test test fname = let oc = open_out fname in output_string oc (String.concat "" [ test.term; rawsep ^ "\n"; test.emetasenv; rawsep ^ "\n"; test.eterm; rawsep ^ "\n"; test.etype; rawsep ^ "\n"; test.ereduced ]); close_out oc let parse_regtest = let term = Buffer.create 1024 in (* raw term *) let emetasenv = Buffer.create 1024 in (* expected metasenv *) let eterm = Buffer.create 1024 in (* raw expected term *) let etype = Buffer.create 1024 in (* raw expected type *) let ereduced = Buffer.create 1024 in (* raw expected reducted term *) let state = ref Term in let bump_state () = match !state with | Term -> state := EMetasenv | EMetasenv -> state := ETerm | ETerm -> state := EType | EType -> state := EReduced | EReduced -> assert false in let buffer_of_state = function | Term -> term | EMetasenv -> emetasenv | ETerm -> eterm | EType -> etype | EReduced -> ereduced in fun fname -> state := Term; Buffer.clear term; Buffer.clear emetasenv; Buffer.clear eterm; Buffer.clear etype; Buffer.clear ereduced; let ic = open_in fname in (try while true do let line = input_line ic in match line with | l when Pcre.pmatch ~rex:sep l -> bump_state () | l -> Buffer.add_string (buffer_of_state !state) (line ^ "\n") done with End_of_file -> ()); { term = Buffer.contents term; emetasenv = Buffer.contents emetasenv; eterm = Buffer.contents eterm; etype = Buffer.contents etype; ereduced = Buffer.contents ereduced } let as_expected expected found = (* ignores "term" field *) let outcome = ref true in if expected.emetasenv <> found.emetasenv then begin print_msg "Metasenv mismatch"; print_msg " expected:"; print_msg (" " ^ expected.emetasenv); print_msg " found:"; print_msg (" " ^ found.emetasenv); outcome := false; end; if expected.eterm <> found.eterm then begin print_msg "Term mismatch"; print_msg " expected:"; print_msg (" " ^ expected.eterm); print_msg " found:"; print_msg (" " ^ found.eterm); outcome := false; end; if expected.etype <> found.etype then begin print_msg "Type mismatch"; print_msg " expected:"; print_msg (" " ^ expected.etype); print_msg " found:"; print_msg (" " ^ found.etype); outcome := false; end; if expected.ereduced <> found.ereduced then begin print_msg "Reduced term mismatch"; print_msg " expected:"; print_msg (" " ^ expected.ereduced); print_msg " found:"; print_msg (" " ^ found.ereduced); outcome := false; end; !outcome let test_this raw_term = let empty_context = [] in let (metasenv, cic_term) = BatchParser.parse raw_term in let etype = try CicPp.ppterm (CicTypeChecker.type_of_aux' metasenv empty_context cic_term) with _ -> "MALFORMED" in let ereduced = try CicPp.ppterm (CicReduction.whd empty_context cic_term) with _ -> "MALFORMED" in { term = raw_term; (* useless *) emetasenv = CicMetaSubst.ppmetasenv metasenv [] ^ "\n"; eterm = CicPp.ppterm cic_term ^ "\n"; etype = etype ^ "\n"; ereduced = ereduced ^ "\n"; } let main () = if Sys.argv.(1) = "-gen" || Sys.argv.(1) = "--gen" then begin (* gen mode *) print_msg "[ Gen mode ]"; for i = 2 to argc - 1 do let fname = Sys.argv.(i) in let test_fname = fname ^ ".test" in print_msg (sprintf "Generating regtest %s -> %s\n ..." fname test_fname); let raw_term = (parse_regtest fname).term in let result = test_this raw_term in print_test result test_fname done end else begin (* regtest mode *) prerr_endline "[ Regtest mode ]"; let (ok, nok) = (ref 0, ref []) in for i = 1 to argc - 1 do let fname = Sys.argv.(i) in prerr_endline ("# " ^ fname); try let expected = parse_regtest fname in let actual = test_this expected.term in if as_expected expected actual then incr ok else nok := fname :: !nok; with e -> nok := fname :: !nok done; print_msg "Regtest completed:"; print_msg (sprintf "Succeeded: %d" !ok); print_msg (sprintf "Failed: %d" (List.length !nok)); List.iter (fun fname -> print_msg (sprintf " %s failed :-(" fname)) (List.rev !nok) end let _ = try main () with Invalid_argument _ -> usage ()