results-to-xml.cpp   [plain text]


#include <string>
#include <sstream>
#include <iostream>

using namespace std;

#define	NELEMENTS(a)	(sizeof (a)/sizeof *(a))

#define	NO_RESULT	(-1)
#define	PASS		1
#define	FAIL		0

#define	DBG	bhole

void
bhole(...)
{
}

class line_category
{
public:
	const char *key;
	char line[99999];
	void (*test)(line_category &);
	int test_result;
} lc;

void
deft(line_category &l)
{
	l.test_result = PASS;
}

void
pass_fail(line_category &l)
{
	if(FAIL!=l.test_result)
		l.test_result = strnstr(l.line, "FAIL", 4)? FAIL: PASS;
}

void
stderr_output(line_category &l)
{
	if(FAIL==l.test_result)
		return;

	if(l.line[0])
		l.test_result = FAIL;
}

void
exit_test(line_category &l)
{
	if(!atoi(l.line)) {
		DBG("exit_test(%s)==%d\n", l.line, atoi(l.line));
		l.test_result = PASS;
	}
}

#define	STDOUT	"stdout: "
#define	STDERR	"stderr: "
#define	CWD	"cwd: "
#define	CMD	"cmd: "
#define	SEXIT	"exit: "
line_category line_categories[] = {
	{ CWD, "" , deft, NO_RESULT},	/* must be first */
	{ CMD, "", deft, NO_RESULT},
	{ STDOUT, "", pass_fail, NO_RESULT},
	{ STDERR, "", stderr_output, NO_RESULT },
	{ SEXIT, "", exit_test, NO_RESULT },
};

static line_category no_line_category = { "none", "no test", deft, NO_RESULT };

line_category &
retrieve(line_category &l, const char *s)
{
	unsigned j;
	line_category *lp = &l;
	//int final_result = PASS;

	for(j=0; j<NELEMENTS(line_categories); ++j,++lp) {//TODO: remove NELEMENTS
		if(!strcmp(lp->key, s)) {
			char *p;

			for(p=(char *)lp->line; *p; ++p) {
				switch(*p) {
				case '\0':
					break;
				case '"':
				case '<':
					*p = ' ';
					// fall thru
				default:
					continue;
				}
			}
DBG("FOUND line_categories[j].line==%s\n", lp->line);
			return line_categories[j];
		}
	}

	return no_line_category;
}

void
xml_string_print(FILE *strm, const char *s)
{
	fputc('"', strm);
	for( ; ; ++s) {
		switch(*s) {
		case '\0':
			break;
		case '&':
			fputs("&amp;", strm);
			continue;
		default:
			fputc(*s, strm);
			continue;
		}
		break;
	}
	fputc('"', strm);
}

//	
//	FAIL if stderr non-zero
//	FAIL if stdout=="FAIL"
//	UNRESOLVED if make exit non-zero
//	PASS otherwise
//	

static int cnt;
void
dump_test(void)
{
	unsigned j;
	int final_result = PASS;

	for(j=0; j<NELEMENTS(line_categories); ++j) {
		if(line_categories[j].line[0]) {
			line_categories[j].line[strlen(line_categories[j].line)-1] = '\0';
			DBG("%s%s RESULT %d\n"
				, line_categories[j].key
				, line_categories[j].line
				, line_categories[j].test_result
				);

			if(PASS==final_result) {
				final_result = line_categories[j].test_result;
				if(NO_RESULT==line_categories[j].test_result) {
					final_result = NO_RESULT;
				} else if(FAIL==line_categories[j].test_result) {
					final_result = FAIL;
				}
			}
		}
	}

	printf("<test name=");
	xml_string_print(stdout, retrieve(line_categories[0], CMD).line);
	printf(" result=\"");
	if(NO_RESULT==final_result) {
		printf("UNRESOLVED");
	} else if(FAIL==final_result) {
		printf("FAIL");
	} else {
		printf("PASS");
	}
	printf("\" ");

	char *s = retrieve(line_categories[0], CWD).line;
	if(*s) {
		char detail[9999];
		char fn[9999];
		FILE *strm;

		strncpy(fn, s, sizeof fn);
		strncat(fn, "/comment.txt", sizeof fn);
		strm = fopen(fn, "r");
		if(strm) {
			if(fgets(detail, -1+sizeof detail, strm)) {
				detail[strlen(detail)-1] = '\0';
				printf("detail=");
				xml_string_print(stdout, detail);
			}
		}
	}
	printf(">\n");

	printf("    <diagnostics>\n");
	s = retrieve(line_categories[0], STDERR).line;
	if(*s) {
		printf("      <diagnostic line=\"%d\" message=", ++cnt);
		xml_string_print(stdout, s);
		printf(" severity=\"ERROR\"/>\n");
	}
#if 1
	s = retrieve(line_categories[0], STDOUT).line;
	if(*s) {
		printf("      <diagnostic line=\"%d\" message=", ++cnt);
		xml_string_print(stdout, s);
		printf(" severity=\"note\"/>\n");
	}
#endif
	printf("    </diagnostics>\n");
	printf("</test>\n\n");

	for(j=0; j<NELEMENTS(line_categories); ++j) {
		line_categories[j].line[0] = '\0';
		line_categories[j].test_result = NO_RESULT;
	}
}

int
main(int argc, char **argv)
{
	int firsttime = 1;


	if(argc>1)
		cnt = atoi(argv[1]);

	for(;;) {
		char line[99999];
		int i;

		line[0] = '\0';
		fgets(line, sizeof line, stdin);
		if(feof(stdin)) {
			dump_test();
			break;
		}

		for(i=0; ; ++i) {
			size_t len = strlen(line_categories[i].key);

			//DBG("strnstr(%s, %s, %u)\n", line, line_categories[i].key, len);
			if(strnstr(line, line_categories[i].key, len)) {
				if(firsttime)
					firsttime = 0;
				else if(0==i)
					dump_test();

				char *lp = &line[len];
				//DBG("%s%s", line_categories[i].key, lp);
				strncpy(line_categories[i].line, lp, sizeof line_categories[i].line);
				line_categories[i].test(line_categories[i]);
				break;
			}

			if(i==NELEMENTS(line_categories)-1) {
				DBG("BADLINE:%s", line);
				break;
			}
		}
	}
	return 0;
}