diff options
Diffstat (limited to 'appl/cmd/itreplay.b')
| -rw-r--r-- | appl/cmd/itreplay.b | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/appl/cmd/itreplay.b b/appl/cmd/itreplay.b new file mode 100644 index 00000000..bba2f591 --- /dev/null +++ b/appl/cmd/itreplay.b @@ -0,0 +1,230 @@ +implement Itreplay; + +include "sys.m"; + sys: Sys; +include "string.m"; + str: String; +include "draw.m"; +include "daytime.m"; + daytime: Daytime; +include "bufio.m"; + bufio: Bufio; + Iobuf: import bufio; +include "readdir.m"; + readdir: Readdir; +include "arg.m"; +include "itslib.m"; + S_INFO, S_WARN, S_ERROR, S_FATAL, S_STIME, S_ETIME: import Itslib; + +SUMFILE: con "summary"; +MSGFILE: con "msgs"; + +verbosity := 3; +display_stderr := 0; +display_stdout := 0; + +stderr: ref Sys->FD; + + +Itreplay: module +{ + init: fn(ctxt: ref Draw->Context, argv: list of string); +}; + + + +init(nil: ref Draw->Context, args: list of string) +{ + sys = load Sys Sys->PATH; + stderr = sys->fildes(2); + arg := load Arg Arg->PATH; + if(arg == nil) + nomod(Arg->PATH); + daytime = load Daytime Daytime->PATH; + if(daytime == nil) + nomod(Daytime->PATH); + str = load String String->PATH; + bufio = load Bufio Bufio->PATH; + if(bufio == nil) + nomod(Bufio->PATH); + if(str == nil) + nomod(String->PATH); + readdir = load Readdir Readdir->PATH; + if(readdir == nil) + nomod(Readdir->PATH); + arg->init(args); + while((o := arg->opt()) != 0) + case o { + 'e' => display_stderr++; + 'o' => display_stdout++; + 'v' => verbosity = toint("v", arg->arg(), 0, 9); + * => usage(); + } + recdirl := arg->argv(); + arg = nil; + if (recdirl == nil) + usage(); + while (recdirl != nil) { + dir := hd recdirl; + recdirl = tl recdirl; + replay(dir); + } +} + +usage() +{ + sys->fprint(stderr, "Usage: itreplay [-eo] [-v verbosity] recorddir ...\n"); + raise "fail: usage"; + exit; +} + +fatal(s: string) +{ + sys->fprint(stderr, "%s\n", s); + raise "fail: error"; + exit; +} + +nomod(mod: string) +{ + sys->fprint(stderr, "Failed to load %s\n", mod); + raise "fail: module"; + exit; +} + +toint(opt, s: string, min, max: int): int +{ + if (len s == 0 || str->take(s, "[0-9]+-") != s) + fatal(sys->sprint("no value specified for option %s", opt)); + v := int s; + if (v < min) + fatal(sys->sprint("option %s value is less than minimum of %d: %d", opt, v, min)); + if (max != -1 && v > max) + fatal(sys->sprint("option %s value is greater than maximum of %d: %d", opt, v, max)); + return v; +} + +replay(dir: string) +{ + sl := linelist(dir+"/"+SUMFILE); + if (sl == nil) { + sys->fprint(stderr, "No summary file in %s\n", dir); + return; + } + sline := hd sl; + (n, toks) := sys->tokenize(sline, " "); + if (n < 4) { + sys->fprint(stderr, "Bad summary file in %s\n", dir); + return; + } + when := int hd toks; + toks = tl toks; + elapsed := int hd toks; + toks = tl toks; + cflag := int hd toks; + toks = tl toks; + testspec := hd toks; + mreport(1, when, 0, 2, sys->sprint("Processing %s: test %s ran in %dms with cflag=%d\n", dir, testspec, elapsed, cflag)); + replay_msgs(dir+"/"+MSGFILE, testspec, cflag); + if (display_stdout) { + mreport(2, 0, 0, 0, "Stdout from test:"); + display_file(dir+"/stdout"); + } + if (display_stderr) { + mreport(2, 0, 0, 0, "Stderr from test:"); + display_file(dir+"/stderr"); + } +} + + +replay_msgs(mfile: string, tspec: string, cflag: int) +{ + mf := bufio->open(mfile, Bufio->OREAD); + if (mf == nil) + return; + (nwarns, nerrors, nfatals) := (0, 0, 0); + stime := 0; + etime := 0; + while ((line := mf.gets('\n')) != nil) { + (whens, rest) := str->splitl(line, ":"); + when := int whens; + msg := rest[1:]; + sev := int msg[0:1]; + verb := int msg[1:2]; + body := msg[2:]; + if (sev == S_STIME) { + stime = int body; + mreport(2, when, 0, 3, sys->sprint("Starting test %s cflag=%d", tspec, cflag)); + } + else if (sev == S_ETIME) { + uetime := int body; + elapsed := uetime-stime; + errsum := sys->sprint("WRN:%d ERR:%d FTL:%d", nwarns, nerrors, nfatals); + mreport(2, when+(int body-stime)/1000, 0, 3, sys->sprint("Finished test %s after %dms - %s", tspec, elapsed, errsum)); + } + else { + if (sev == S_WARN) { + nwarns++; + } + else if (sev == S_ERROR) { + nerrors++; + } + else if (sev == S_FATAL) { + nfatals++; + } + mreport(3, when, sev, verb, sys->sprint("%s: %s", severs(sev), body)); + } + } +} + +linelist(file: string): list of string +{ + bf := bufio->open(file, Bufio->OREAD); + if (bf == nil) + return nil; + cl : list of string; + while ((line := bf.gets('\n')) != nil) { + if (line[len line -1] == '\n') + line = line[:len line - 1]; + cl = line :: cl; + } + bf = nil; + return cl; +} + +display_file(file: string) +{ + bf := bufio->open(file, Bufio->OREAD); + if (bf == nil) + return; + while ((line := bf.gets('\n')) != nil) { + sys->print(" %s", line); + } +} + + +severs(sevs: int): string +{ + SEVMAP := array[] of {"INF", "WRN", "ERR", "FTL"}; + if (sevs >= len SEVMAP) + sstr := "UNK"; + else + sstr = SEVMAP[sevs]; + return sstr; +} + + +mreport(indent: int, when: int, sev: int, verb: int, msg: string) +{ + time := ""; + if (when) { + tm := daytime->local(when); + time = sys->sprint("%4d%02d%02d %02d:%02d:%02d", tm.year+1900, tm.mon-1, tm.mday, tm.hour, tm.min, tm.sec); + } + pad := "---"[:indent]; + term := ""; + if (len msg && msg[len msg-1] != '\n') + term = "\n"; + if (sev || verb <= verbosity) + sys->print("%-17s %s%s%s", time, pad, msg, term); +} |
