Files
pretty-test-matrix/main.c

204 lines
4.5 KiB
C

#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define lenof(x) (sizeof((x)) / sizeof(*(x)))
#define MAX_LINE_LEN 256
#define MAX_RCOL 32
#define RCOL_LEN 64
#define RED "\033[0;31m"
#define GREEN "\033[0;32m"
#define YELLOW "\033[0;33m"
#define HRED "\033[0;91m"
#define HGREEN "\033[0;92m"
#define HYELLOW "\033[0;93m"
#define RESET "\033[0m"
unsigned hash(char const *buf) {
unsigned res = 5381;
for (; *buf; buf++) {
res = (res << 5) + res + *buf;
}
return res;
}
void err_misfmt_input(char const *reason) {
fprintf(stderr, "error: misformatted input: %s\n", reason);
exit(1);
}
char buf[MAX_LINE_LEN];
struct counters {
unsigned char pfs[3];
};
unsigned num_rcol = 0;
unsigned rcol_hashes[MAX_RCOL] = {0};
char rcol_values[MAX_RCOL][RCOL_LEN];
struct counters rcol_ctr[MAX_RCOL] = {0};
unsigned rcol_lut(unsigned hash) {
unsigned *p;
for (p = rcol_hashes; *p; p++)
if (*p == hash)
return p - rcol_hashes + 1;
return 0;
}
void rstrip(char *buf) {
char *sub;
for (; *buf; buf++) {
if (isspace(*buf)) {
for (sub = buf + 1; *sub && isspace(*sub); sub++)
;
if (!*sub) {
*buf = 0;
break;
}
}
}
}
void put(int pfs_mode) {
if (pfs_mode == 0)
printf(HGREEN "* " RESET);
else if (pfs_mode == 1)
printf(HRED "X " RESET);
else
printf(HYELLOW "- " RESET);
}
void finish(int last_lc, unsigned last_rcol_idx) {
if (last_lc == 0)
return;
for (; last_rcol_idx < num_rcol; last_rcol_idx++) {
put(2);
rcol_ctr[last_rcol_idx].pfs[2] += 1;
}
}
int main(int argc, char **argv) {
int lcol_width;
unsigned last_lc = 0;
char *p, *lcol, *rcol;
unsigned lcol_hash, rcol_hash, rcol_idx, last_rcol_idx = 0,
actual_last_rcol_idx, i, j, pfs_mode;
struct counters sum = {0};
if (argc != 2 || !((lcol_width = atoi(argv[1])))) {
fprintf(stderr, "usage: %s <left column width>\n", *argv);
return 1;
}
while (buf == fgets(buf, lenof(buf), stdin)) {
p = buf;
for (; isspace(*p); p++)
;
if (*p == '#' || !*p)
continue;
lcol = strtok(p, " \t");
rcol = strtok(0, " \t");
p = strtok(0, " \t");
rstrip(p);
if (!p || p[1])
err_misfmt_input("3rd column invalid");
if (*p == '0')
pfs_mode = 1;
else if (*p == '1')
pfs_mode = 0;
else if (*p == '-')
pfs_mode = 2;
else
err_misfmt_input("3rd column invalid");
lcol_hash = hash(lcol);
rcol_hash = hash(rcol);
actual_last_rcol_idx = last_rcol_idx;
if (lcol_hash != last_lc) {
last_rcol_idx = 0;
}
rcol_idx = rcol_lut(rcol_hash);
if (rcol_idx == 0) {
rcol_idx = ++num_rcol;
/* TODO: validate length */
rcol_hashes[rcol_idx - 1] = rcol_hash;
/* TODO: validate length */
strcpy(rcol_values[rcol_idx - 1], rcol);
} else if (rcol_idx <= last_rcol_idx && last_rcol_idx != 0) {
err_misfmt_input("ordering different from last time");
}
rcol_ctr[rcol_idx - 1].pfs[pfs_mode] += 1;
if (lcol[0] == '-' && lcol[1] == 0)
continue;
if (lcol_hash != last_lc) {
finish(last_lc, actual_last_rcol_idx);
if (last_lc != 0)
putchar('\n');
last_lc = lcol_hash;
last_rcol_idx = 0;
printf("%*s ", lcol_width, lcol);
}
for (i = last_rcol_idx + 1; i < rcol_idx; i++) {
put(2);
rcol_ctr[i - 1].pfs[2]++;
}
put(pfs_mode);
last_rcol_idx = rcol_idx;
fflush(stdout);
}
finish(last_lc, last_rcol_idx);
if (last_lc != 0)
putchar('\n');
for (i = 0; i <= num_rcol; i++) {
for (j = 0; j < lcol_width + (num_rcol - i) * 2; j++)
putchar(' ');
if (i != num_rcol) {
putchar('^');
sum.pfs[0] += rcol_ctr[i].pfs[0];
sum.pfs[1] += rcol_ctr[i].pfs[1];
sum.pfs[2] += rcol_ctr[i].pfs[2];
} else
putchar(' ');
if (i != 0) {
printf(" %s \t(%u/%u passed", rcol_values[num_rcol - i],
rcol_ctr[num_rcol - i].pfs[0],
rcol_ctr[num_rcol - i].pfs[0] + rcol_ctr[num_rcol - i].pfs[1]);
if (rcol_ctr[num_rcol - i].pfs[2])
printf(", %u skipped", rcol_ctr[num_rcol - i].pfs[2]);
printf(")");
}
putchar('\n');
}
printf("\nSummary:\n");
if (sum.pfs[0])
printf(HGREEN " %u passed" RESET "\n", sum.pfs[0]);
if (sum.pfs[1])
printf(HRED " %u failed" RESET "\n", sum.pfs[1]);
if (sum.pfs[2])
printf(HYELLOW " %u skipped" RESET "\n", sum.pfs[2]);
return 0;
}