summaryrefslogtreecommitdiff
path: root/runner
diff options
context:
space:
mode:
Diffstat (limited to 'runner')
-rw-r--r--runner/resultgen.c261
1 files changed, 135 insertions, 126 deletions
diff --git a/runner/resultgen.c b/runner/resultgen.c
index 5faa8555..0adcc872 100644
--- a/runner/resultgen.c
+++ b/runner/resultgen.c
@@ -10,6 +10,7 @@
#include <json.h>
+#include "igt_aux.h"
#include "igt_core.h"
#include "resultgen.h"
#include "settings.h"
@@ -59,28 +60,7 @@ static char *find_line_starting_with(char *haystack, const char *needle, char *e
return NULL;
}
-static char *find_line_starting_with_either(char *haystack,
- const char *needle1,
- const char *needle2,
- char *end)
-{
- while (haystack < end) {
- char *line_end = memchr(haystack, '\n', end - haystack);
- size_t linelen = line_end != NULL ? line_end - haystack : end - haystack;
- if ((linelen >= strlen(needle1) && !memcmp(haystack, needle1, strlen(needle1))) ||
- (linelen >= strlen(needle2) && !memcmp(haystack, needle2, strlen(needle2))))
- return haystack;
-
- if (line_end == NULL)
- return NULL;
-
- haystack = line_end + 1;
- }
-
- return NULL;
-}
-
-static char *next_line(char *line, char *bufend)
+static const char *next_line(const char *line, const char *bufend)
{
char *ret;
@@ -97,45 +77,6 @@ static char *next_line(char *line, char *bufend)
return NULL;
}
-static char *find_line_after_last(char *begin,
- const char *needle1,
- const char *needle2,
- char *end)
-{
- char *one, *two;
- char *current_pos = begin;
- char *needle1_newline = malloc(strlen(needle1) + 2);
- char *needle2_newline = malloc(strlen(needle2) + 2);
-
- needle1_newline[0] = needle2_newline[0] = '\n';
- strcpy(needle1_newline + 1, needle1);
- strcpy(needle2_newline + 1, needle2);
-
- while (true) {
- one = memmem(current_pos, end - current_pos, needle1_newline, strlen(needle1_newline));
- two = memmem(current_pos, end - current_pos, needle2_newline, strlen(needle2_newline));
- if (one == NULL && two == NULL)
- break;
-
- if (one != NULL && current_pos < one)
- current_pos = one;
- if (two != NULL && current_pos < two)
- current_pos = two;
-
- one = next_line(current_pos, end);
- if (one != NULL)
- current_pos = one;
- }
- free(needle1_newline);
- free(needle2_newline);
-
- one = memchr(current_pos, '\n', end - current_pos);
- if (one != NULL)
- return ++one;
-
- return current_pos;
-}
-
static size_t count_lines(const char *buf, const char *bufend)
{
size_t ret = 0;
@@ -166,7 +107,7 @@ static const struct {
{ "CRASH", "crash" },
{ "TIMEOUT", "timeout" },
};
-static void parse_result_string(char *resultstring, size_t len, const char **result, double *time)
+static void parse_result_string(const char *resultstring, size_t len, const char **result, double *time)
{
size_t i;
size_t wordlen = 0;
@@ -206,19 +147,20 @@ static void parse_result_string(char *resultstring, size_t len, const char **res
}
}
-static void parse_subtest_result(char *subtest, const char **result, double *time, char *buf, char *bufend)
+static void parse_subtest_result(const char *subtest,
+ const char **result,
+ double *time,
+ const char *line,
+ const char *bufend)
{
- char *line;
- char *line_end;
- char *resultstring;
- size_t linelen;
+ const char *resultstring;
size_t subtestlen = strlen(subtest);
+ const char *line_end;
+ size_t linelen;
- *result = NULL;
+ *result = "incomplete";
*time = 0.0;
- if (!buf) return;
-
/*
* The result line structure is:
*
@@ -235,18 +177,17 @@ static void parse_subtest_result(char *subtest, const char **result, double *tim
* Subtest subtestname: PASS (0.003s)
*/
- line = find_line_starting_with(buf, SUBTEST_RESULT, bufend);
- if (!line) {
- *result = "incomplete";
+ if (!line)
return;
- }
line_end = memchr(line, '\n', bufend - line);
linelen = line_end != NULL ? line_end - line : bufend - line;
if (strlen(SUBTEST_RESULT) + subtestlen + strlen(": ") > linelen ||
- strncmp(line + strlen(SUBTEST_RESULT), subtest, subtestlen))
- return parse_subtest_result(subtest, result, time, line + linelen, bufend);
+ strncmp(line + strlen(SUBTEST_RESULT), subtest, subtestlen)) {
+ /* This is not the correct result line */
+ return;
+ }
resultstring = line + strlen(SUBTEST_RESULT) + subtestlen + strlen(": ");
parse_result_string(resultstring, linelen - (resultstring - line), result, time);
@@ -309,6 +250,59 @@ static void set_runtime(struct json_object *obj, double time)
json_object_new_double(time));
}
+struct match_item
+{
+ const char *where;
+ const char *what;
+};
+
+struct matches
+{
+ struct match_item *items;
+ size_t size;
+};
+
+static void match_add(struct matches *matches, const char *where, const char *what)
+{
+ struct match_item newitem = { where, what };
+
+ matches->size++;
+ matches->items = realloc(matches->items, matches->size * sizeof(*matches->items));
+ matches->items[matches->size - 1] = newitem;
+}
+
+static struct matches find_matches(const char *buf, const char *bufend,
+ const char **needles)
+{
+ struct matches ret = {};
+
+ while (buf < bufend) {
+ const char **needle;
+
+ for (needle = needles; *needle; needle++) {
+ if (bufend - buf < strlen(*needle))
+ continue;
+
+ if (!memcmp(buf, *needle, strlen(*needle))) {
+ match_add(&ret, buf, *needle);
+ goto end_find;
+ }
+ }
+
+ end_find:
+ buf = next_line(buf, bufend);
+ if (!buf)
+ break;
+ }
+
+ return ret;
+}
+
+static void free_matches(struct matches *matches)
+{
+ free(matches->items);
+}
+
static bool fill_from_output(int fd, const char *binary, const char *key,
struct subtests *subtests,
struct json_object *tests)
@@ -319,7 +313,13 @@ static bool fill_from_output(int fd, const char *binary, const char *key,
char *igt_version = NULL;
size_t igt_version_len = 0;
struct json_object *current_test = NULL;
- size_t i;
+ const char *needles[] = {
+ STARTING_SUBTEST,
+ SUBTEST_RESULT,
+ NULL
+ };
+ struct matches matches = {};
+ size_t i, k;
if (fstat(fd, &statbuf))
return false;
@@ -364,10 +364,13 @@ static bool fill_from_output(int fd, const char *binary, const char *key,
return true;
}
+ matches = find_matches(buf, bufend, needles);
+
for (i = 0; i < subtests->size; i++) {
char *this_sub_begin, *this_sub_result;
+ int begin_idx = -1, result_idx = -1;
const char *resulttext;
- char *beg, *end, *startline;
+ const char *beg, *end;
double time;
int begin_len;
int result_len;
@@ -383,66 +386,68 @@ static bool fill_from_output(int fd, const char *binary, const char *key,
return false;
}
- beg = find_line_starting_with(buf, this_sub_begin, bufend);
- end = find_line_starting_with(buf, this_sub_result, bufend);
- startline = beg;
+ for (k = 0; k < matches.size; k++) {
+ if (matches.items[k].what == STARTING_SUBTEST &&
+ !memcmp(matches.items[k].where,
+ this_sub_begin,
+ min(begin_len, bufend - matches.items[k].where))) {
+ beg = matches.items[k].where;
+ begin_idx = k;
+ }
+ if (matches.items[k].what == SUBTEST_RESULT &&
+ !memcmp(matches.items[k].where,
+ this_sub_result,
+ min(result_len, bufend - matches.items[k].where))) {
+ end = matches.items[k].where;
+ result_idx = k;
+ }
+ }
free(this_sub_begin);
free(this_sub_result);
- if (beg == NULL && end == NULL) {
+ if (begin_idx < 0 && result_idx < 0) {
/* No output at all */
- beg = bufend;
+ beg = buf;
end = bufend;
- }
-
- if (beg == NULL) {
+ } else if (begin_idx < 0) {
/*
- * Subtest didn't start, probably skipped from
- * fixture already. Start from the result
- * line, it gets adjusted below.
+ * Subtest didn't start, but we have the
+ * result. Probably because an igt_fixture
+ * made it fail/skip.
+ *
+ * Start the output right after the previous
+ * subtest result/start.
*/
- beg = end;
+ if (result_idx > 0)
+ beg = next_line(matches.items[result_idx - 1].where, bufend);
+ else
+ beg = buf;
+ } else {
+ /* Stretch output beginning backwards */
+ if (begin_idx == 0)
+ beg = buf;
+ else
+ beg = next_line(matches.items[begin_idx - 1].where, bufend);
}
- /* Include the output after the previous subtest output */
- beg = find_line_after_last(buf,
- STARTING_SUBTEST,
- SUBTEST_RESULT,
- beg);
-
- if (end == NULL) {
- /* Incomplete result. Find the next starting subtest or result. */
- end = next_line(startline, bufend);
- if (end != NULL) {
- end = find_line_starting_with_either(end,
- STARTING_SUBTEST,
- SUBTEST_RESULT,
- bufend);
- }
- if (end == NULL) {
- end = bufend;
- }
- } else {
+ if (result_idx < 0 && begin_idx < 0) {
+ /* No output at all: Already handled above */
+ } else if (result_idx < 0) {
/*
- * Now pointing to the line where this sub's
- * result is. We need to include that of
- * course.
+ * Incomplete result. Include output up to the
+ * next starting subtest or result.
*/
- char *nexttest = next_line(end, bufend);
-
- /* Stretch onwards until the next subtest begins or ends */
- if (nexttest != NULL) {
- nexttest = find_line_starting_with_either(nexttest,
- STARTING_SUBTEST,
- SUBTEST_RESULT,
- bufend);
- }
- if (nexttest != NULL) {
- end = nexttest;
- } else {
+ if (begin_idx < matches.size - 1)
+ end = matches.items[begin_idx + 1].where;
+ else
+ end = bufend;
+ } else {
+ /* Stretch output to the next starting subtest or result. */
+ if (result_idx < matches.size - 1)
+ end = matches.items[result_idx + 1].where;
+ else
end = bufend;
- }
}
json_object_object_add(current_test, key,
@@ -455,12 +460,16 @@ static bool fill_from_output(int fd, const char *binary, const char *key,
}
if (!json_object_object_get_ex(current_test, "result", NULL)) {
- parse_subtest_result(subtests->names[i], &resulttext, &time, beg, end);
+ parse_subtest_result(subtests->names[i],
+ &resulttext, &time,
+ result_idx < 0 ? NULL : matches.items[result_idx].where,
+ end);
set_result(current_test, resulttext);
set_runtime(current_test, time);
}
}
+ free_matches(&matches);
return true;
}