test: add RETURN_SKIP and RETURN_TODO macros

Added two new flags to identify tests that are intentionally ignored
(usually because we don't want to implement the tested functionality
on current platform) and test serving as TODO list (usually indicating
that the tested functionality should be implemented on current plaform
in the near future.)
This commit is contained in:
Miroslav Bajtoš 2013-04-20 06:43:31 +02:00 committed by Ben Noordhuis
parent 9b801d551b
commit 2c21050956
5 changed files with 174 additions and 17 deletions

View File

@ -286,6 +286,34 @@ int process_copy_output(process_info_t *p, int fd) {
}
/* Copy the last line of the stdio output buffer to `buffer` */
int process_read_last_line(process_info_t *p,
char* buffer,
size_t buffer_len) {
char* ptr;
int r = fseek(p->stdout_file, 0, SEEK_SET);
if (r < 0) {
perror("fseek");
return -1;
}
buffer[0] = '\0';
while (fgets(buffer, buffer_len, p->stdout_file) != NULL) {
for (ptr = buffer; *ptr && *ptr != '\r' && *ptr != '\n'; ptr++);
*ptr = '\0';
}
if (ferror(p->stdout_file)) {
perror("read");
buffer[0] = '\0';
return -1;
}
return 0;
}
/* Return the name that was specified when `p` was started by process_start */
char* process_get_name(process_info_t *p) {
return p->name;

View File

@ -248,6 +248,46 @@ int process_copy_output(process_info_t *p, int fd) {
}
int process_read_last_line(process_info_t *p,
char * buffer,
size_t buffer_len) {
DWORD size;
DWORD read;
DWORD start;
OVERLAPPED overlapped;
ASSERT(buffer_len > 0);
size = GetFileSize(p->stdio_out, NULL);
if (size == INVALID_FILE_SIZE)
return -1;
if (size == 0) {
buffer[0] = '\0';
return 1;
}
memset(&overlapped, 0, sizeof overlapped);
if (size >= buffer_len)
overlapped.Offset = size - buffer_len - 1;
if (!ReadFile(p->stdio_out, buffer, buffer_len - 1, &read, &overlapped))
return -1;
for (start = read - 1; start >= 0; start--) {
if (buffer[start] == '\n' || buffer[start] == '\r')
break;
}
if (start > 0)
memmove(buffer, buffer + start, read - start);
buffer[read - start] = '\0';
return 0;
}
char* process_get_name(process_info_t *p) {
return p->name;
}

View File

@ -31,12 +31,25 @@ char executable_path[PATHMAX] = { '\0' };
int tap_output = 0;
static void log_progress(int total, int passed, int failed, const char* name) {
static void log_progress(int total,
int passed,
int failed,
int todos,
int skipped,
const char* name) {
int progress;
if (total == 0)
total = 1;
LOGF("[%% %3d|+ %3d|- %3d]: %s", (int) ((passed + failed) / ((double) total) * 100.0),
passed, failed, name);
progress = 100 * (passed + failed + skipped + todos) / total;
LOGF("[%% %3d|+ %3d|- %3d|T %3d|S %3d]: %s",
progress,
passed,
failed,
todos,
skipped,
name);
}
@ -78,7 +91,13 @@ const char* fmt(double d) {
int run_tests(int timeout, int benchmark_output) {
int total, passed, failed, current;
int total;
int passed;
int failed;
int todos;
int skipped;
int current;
int test_result;
task_entry_t* task;
/* Count the number of tests. */
@ -96,6 +115,8 @@ int run_tests(int timeout, int benchmark_output) {
/* Run all tests. */
passed = 0;
failed = 0;
todos = 0;
skipped = 0;
current = 1;
for (task = TASKS; task->main; task++) {
if (task->is_helper) {
@ -106,13 +127,15 @@ int run_tests(int timeout, int benchmark_output) {
rewind_cursor();
if (!benchmark_output && !tap_output) {
log_progress(total, passed, failed, task->task_name);
log_progress(total, passed, failed, todos, skipped, task->task_name);
}
if (run_test(task->task_name, timeout, benchmark_output, current) == 0) {
passed++;
} else {
failed++;
test_result = run_test(task->task_name, timeout, benchmark_output, current);
switch (test_result) {
case TEST_OK: passed++; break;
case TEST_TODO: todos++; break;
case TEST_SKIP: skipped++; break;
default: failed++;
}
current++;
}
@ -121,13 +144,50 @@ int run_tests(int timeout, int benchmark_output) {
rewind_cursor();
if (!benchmark_output && !tap_output) {
log_progress(total, passed, failed, "Done.\n");
log_progress(total, passed, failed, todos, skipped, "Done.\n");
}
return failed;
}
void log_tap_result(int test_count,
const char* test,
int status,
process_info_t* process) {
const char* result;
const char* directive;
char reason[1024];
switch (status) {
case TEST_OK:
result = "ok";
directive = "";
break;
case TEST_TODO:
result = "not ok";
directive = " # TODO ";
break;
case TEST_SKIP:
result = "ok";
directive = " # SKIP ";
break;
default:
result = "not ok";
directive = "";
}
if ((status == TEST_SKIP || status == TEST_TODO) &&
process_output_size(process) > 0) {
process_read_last_line(process, reason, sizeof reason);
} else {
reason[0] = '\0';
}
LOGF("%s %d - %s%s%s\n", result, test_count, test, directive, reason);
}
int run_test(const char* test,
int timeout,
int benchmark_output,
@ -231,7 +291,7 @@ int run_test(const char* test,
}
status = process_reap(main_proc);
if (status != 0) {
if (status != TEST_OK) {
snprintf(errmsg,
sizeof errmsg,
"exit code %d",
@ -255,17 +315,17 @@ out:
FATAL("process_wait failed");
}
if (tap_output) {
if (status == 0)
LOGF("ok %d - %s\n", test_count, test);
else
LOGF("not ok %d - %s\n", test_count, test);
}
if (tap_output)
log_tap_result(test_count, test, status, &processes[i]);
/* Show error and output from processes if the test failed. */
if (status != 0 || task->show_output) {
if (tap_output) {
LOGF("#");
} else if (status == TEST_TODO) {
LOGF("\n`%s` todo\n", test);
} else if (status == TEST_SKIP) {
LOGF("\n`%s` skipped\n", test);
} else if (status != 0) {
LOGF("\n`%s` failed: %s\n", test, errmsg);
} else {

View File

@ -143,6 +143,11 @@ long int process_output_size(process_info_t *p);
/* Copy the contents of the stdio output buffer to `fd`. */
int process_copy_output(process_info_t *p, int fd);
/* Copy the last line of the stdio output buffer to `buffer` */
int process_read_last_line(process_info_t *p,
char * buffer,
size_t buffer_len);
/* Return the name that was specified when `p` was started by process_start */
char* process_get_name(process_info_t *p);

View File

@ -119,4 +119,28 @@ void uv_sleep(int msec);
/* Format big numbers nicely. WARNING: leaks memory. */
const char* fmt(double d);
/* Reserved test exit codes. */
enum test_status {
TEST_OK = 0,
TEST_TODO,
TEST_SKIP
};
#define RETURN_OK() \
do { \
return TEST_OK; \
} while (0)
#define RETURN_TODO(explanation) \
do { \
LOGF("%s\n", explanation); \
return TEST_TODO; \
} while (0)
#define RETURN_SKIP(explanation) \
do { \
LOGF("%s\n", explanation); \
return TEST_SKIP; \
} while (0)
#endif /* TASK_H_ */