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; 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);}
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;
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);
}