1*d83cc019SAndroid Build Coastguard Worker #include <assert.h>
2*d83cc019SAndroid Build Coastguard Worker #include <ctype.h>
3*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
4*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
5*d83cc019SAndroid Build Coastguard Worker #include <string.h>
6*d83cc019SAndroid Build Coastguard Worker #include <sys/mman.h>
7*d83cc019SAndroid Build Coastguard Worker #include <sys/stat.h>
8*d83cc019SAndroid Build Coastguard Worker #include <sys/types.h>
9*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
10*d83cc019SAndroid Build Coastguard Worker
11*d83cc019SAndroid Build Coastguard Worker #include <json.h>
12*d83cc019SAndroid Build Coastguard Worker
13*d83cc019SAndroid Build Coastguard Worker #include "igt_core.h"
14*d83cc019SAndroid Build Coastguard Worker #include "resultgen.h"
15*d83cc019SAndroid Build Coastguard Worker #include "settings.h"
16*d83cc019SAndroid Build Coastguard Worker #include "executor.h"
17*d83cc019SAndroid Build Coastguard Worker #include "output_strings.h"
18*d83cc019SAndroid Build Coastguard Worker
19*d83cc019SAndroid Build Coastguard Worker #define INCOMPLETE_EXITCODE -1
20*d83cc019SAndroid Build Coastguard Worker
21*d83cc019SAndroid Build Coastguard Worker _Static_assert(INCOMPLETE_EXITCODE != IGT_EXIT_SKIP, "exit code clash");
22*d83cc019SAndroid Build Coastguard Worker _Static_assert(INCOMPLETE_EXITCODE != IGT_EXIT_SUCCESS, "exit code clash");
23*d83cc019SAndroid Build Coastguard Worker _Static_assert(INCOMPLETE_EXITCODE != IGT_EXIT_INVALID, "exit code clash");
24*d83cc019SAndroid Build Coastguard Worker
25*d83cc019SAndroid Build Coastguard Worker struct subtests
26*d83cc019SAndroid Build Coastguard Worker {
27*d83cc019SAndroid Build Coastguard Worker char **names;
28*d83cc019SAndroid Build Coastguard Worker size_t size;
29*d83cc019SAndroid Build Coastguard Worker };
30*d83cc019SAndroid Build Coastguard Worker
31*d83cc019SAndroid Build Coastguard Worker struct results
32*d83cc019SAndroid Build Coastguard Worker {
33*d83cc019SAndroid Build Coastguard Worker struct json_object *tests;
34*d83cc019SAndroid Build Coastguard Worker struct json_object *totals;
35*d83cc019SAndroid Build Coastguard Worker struct json_object *runtimes;
36*d83cc019SAndroid Build Coastguard Worker };
37*d83cc019SAndroid Build Coastguard Worker
38*d83cc019SAndroid Build Coastguard Worker /*
39*d83cc019SAndroid Build Coastguard Worker * A lot of string handling here operates on an mmapped buffer, and
40*d83cc019SAndroid Build Coastguard Worker * thus we can't assume null-terminated strings. Buffers will be
41*d83cc019SAndroid Build Coastguard Worker * passed around as pointer+size, or pointer+pointer-past-the-end, the
42*d83cc019SAndroid Build Coastguard Worker * mem*() family of functions is used instead of str*().
43*d83cc019SAndroid Build Coastguard Worker */
44*d83cc019SAndroid Build Coastguard Worker
find_line_starting_with(char * haystack,const char * needle,char * end)45*d83cc019SAndroid Build Coastguard Worker static char *find_line_starting_with(char *haystack, const char *needle, char *end)
46*d83cc019SAndroid Build Coastguard Worker {
47*d83cc019SAndroid Build Coastguard Worker while (haystack < end) {
48*d83cc019SAndroid Build Coastguard Worker char *line_end = memchr(haystack, '\n', end - haystack);
49*d83cc019SAndroid Build Coastguard Worker
50*d83cc019SAndroid Build Coastguard Worker if (end - haystack < strlen(needle))
51*d83cc019SAndroid Build Coastguard Worker return NULL;
52*d83cc019SAndroid Build Coastguard Worker if (!memcmp(haystack, needle, strlen(needle)))
53*d83cc019SAndroid Build Coastguard Worker return haystack;
54*d83cc019SAndroid Build Coastguard Worker if (line_end == NULL)
55*d83cc019SAndroid Build Coastguard Worker return NULL;
56*d83cc019SAndroid Build Coastguard Worker haystack = line_end + 1;
57*d83cc019SAndroid Build Coastguard Worker }
58*d83cc019SAndroid Build Coastguard Worker
59*d83cc019SAndroid Build Coastguard Worker return NULL;
60*d83cc019SAndroid Build Coastguard Worker }
61*d83cc019SAndroid Build Coastguard Worker
find_line_starting_with_either(char * haystack,const char * needle1,const char * needle2,char * end)62*d83cc019SAndroid Build Coastguard Worker static char *find_line_starting_with_either(char *haystack,
63*d83cc019SAndroid Build Coastguard Worker const char *needle1,
64*d83cc019SAndroid Build Coastguard Worker const char *needle2,
65*d83cc019SAndroid Build Coastguard Worker char *end)
66*d83cc019SAndroid Build Coastguard Worker {
67*d83cc019SAndroid Build Coastguard Worker while (haystack < end) {
68*d83cc019SAndroid Build Coastguard Worker char *line_end = memchr(haystack, '\n', end - haystack);
69*d83cc019SAndroid Build Coastguard Worker size_t linelen = line_end != NULL ? line_end - haystack : end - haystack;
70*d83cc019SAndroid Build Coastguard Worker if ((linelen >= strlen(needle1) && !memcmp(haystack, needle1, strlen(needle1))) ||
71*d83cc019SAndroid Build Coastguard Worker (linelen >= strlen(needle2) && !memcmp(haystack, needle2, strlen(needle2))))
72*d83cc019SAndroid Build Coastguard Worker return haystack;
73*d83cc019SAndroid Build Coastguard Worker
74*d83cc019SAndroid Build Coastguard Worker if (line_end == NULL)
75*d83cc019SAndroid Build Coastguard Worker return NULL;
76*d83cc019SAndroid Build Coastguard Worker
77*d83cc019SAndroid Build Coastguard Worker haystack = line_end + 1;
78*d83cc019SAndroid Build Coastguard Worker }
79*d83cc019SAndroid Build Coastguard Worker
80*d83cc019SAndroid Build Coastguard Worker return NULL;
81*d83cc019SAndroid Build Coastguard Worker }
82*d83cc019SAndroid Build Coastguard Worker
next_line(char * line,char * bufend)83*d83cc019SAndroid Build Coastguard Worker static char *next_line(char *line, char *bufend)
84*d83cc019SAndroid Build Coastguard Worker {
85*d83cc019SAndroid Build Coastguard Worker char *ret;
86*d83cc019SAndroid Build Coastguard Worker
87*d83cc019SAndroid Build Coastguard Worker if (!line)
88*d83cc019SAndroid Build Coastguard Worker return NULL;
89*d83cc019SAndroid Build Coastguard Worker
90*d83cc019SAndroid Build Coastguard Worker ret = memchr(line, '\n', bufend - line);
91*d83cc019SAndroid Build Coastguard Worker if (ret)
92*d83cc019SAndroid Build Coastguard Worker ret++;
93*d83cc019SAndroid Build Coastguard Worker
94*d83cc019SAndroid Build Coastguard Worker if (ret < bufend)
95*d83cc019SAndroid Build Coastguard Worker return ret;
96*d83cc019SAndroid Build Coastguard Worker else
97*d83cc019SAndroid Build Coastguard Worker return NULL;
98*d83cc019SAndroid Build Coastguard Worker }
99*d83cc019SAndroid Build Coastguard Worker
find_line_after_last(char * begin,const char * needle1,const char * needle2,char * end)100*d83cc019SAndroid Build Coastguard Worker static char *find_line_after_last(char *begin,
101*d83cc019SAndroid Build Coastguard Worker const char *needle1,
102*d83cc019SAndroid Build Coastguard Worker const char *needle2,
103*d83cc019SAndroid Build Coastguard Worker char *end)
104*d83cc019SAndroid Build Coastguard Worker {
105*d83cc019SAndroid Build Coastguard Worker char *one, *two;
106*d83cc019SAndroid Build Coastguard Worker char *current_pos = begin;
107*d83cc019SAndroid Build Coastguard Worker char *needle1_newline = malloc(strlen(needle1) + 2);
108*d83cc019SAndroid Build Coastguard Worker char *needle2_newline = malloc(strlen(needle2) + 2);
109*d83cc019SAndroid Build Coastguard Worker
110*d83cc019SAndroid Build Coastguard Worker needle1_newline[0] = needle2_newline[0] = '\n';
111*d83cc019SAndroid Build Coastguard Worker strcpy(needle1_newline + 1, needle1);
112*d83cc019SAndroid Build Coastguard Worker strcpy(needle2_newline + 1, needle2);
113*d83cc019SAndroid Build Coastguard Worker
114*d83cc019SAndroid Build Coastguard Worker while (true) {
115*d83cc019SAndroid Build Coastguard Worker one = memmem(current_pos, end - current_pos, needle1_newline, strlen(needle1_newline));
116*d83cc019SAndroid Build Coastguard Worker two = memmem(current_pos, end - current_pos, needle2_newline, strlen(needle2_newline));
117*d83cc019SAndroid Build Coastguard Worker if (one == NULL && two == NULL)
118*d83cc019SAndroid Build Coastguard Worker break;
119*d83cc019SAndroid Build Coastguard Worker
120*d83cc019SAndroid Build Coastguard Worker if (one != NULL && current_pos < one)
121*d83cc019SAndroid Build Coastguard Worker current_pos = one;
122*d83cc019SAndroid Build Coastguard Worker if (two != NULL && current_pos < two)
123*d83cc019SAndroid Build Coastguard Worker current_pos = two;
124*d83cc019SAndroid Build Coastguard Worker
125*d83cc019SAndroid Build Coastguard Worker one = next_line(current_pos, end);
126*d83cc019SAndroid Build Coastguard Worker if (one != NULL)
127*d83cc019SAndroid Build Coastguard Worker current_pos = one;
128*d83cc019SAndroid Build Coastguard Worker }
129*d83cc019SAndroid Build Coastguard Worker free(needle1_newline);
130*d83cc019SAndroid Build Coastguard Worker free(needle2_newline);
131*d83cc019SAndroid Build Coastguard Worker
132*d83cc019SAndroid Build Coastguard Worker one = memchr(current_pos, '\n', end - current_pos);
133*d83cc019SAndroid Build Coastguard Worker if (one != NULL)
134*d83cc019SAndroid Build Coastguard Worker return ++one;
135*d83cc019SAndroid Build Coastguard Worker
136*d83cc019SAndroid Build Coastguard Worker return current_pos;
137*d83cc019SAndroid Build Coastguard Worker }
138*d83cc019SAndroid Build Coastguard Worker
count_lines(const char * buf,const char * bufend)139*d83cc019SAndroid Build Coastguard Worker static size_t count_lines(const char *buf, const char *bufend)
140*d83cc019SAndroid Build Coastguard Worker {
141*d83cc019SAndroid Build Coastguard Worker size_t ret = 0;
142*d83cc019SAndroid Build Coastguard Worker while (buf < bufend && (buf = memchr(buf, '\n', bufend - buf)) != NULL) {
143*d83cc019SAndroid Build Coastguard Worker ret++;
144*d83cc019SAndroid Build Coastguard Worker buf++;
145*d83cc019SAndroid Build Coastguard Worker }
146*d83cc019SAndroid Build Coastguard Worker
147*d83cc019SAndroid Build Coastguard Worker return ret;
148*d83cc019SAndroid Build Coastguard Worker }
149*d83cc019SAndroid Build Coastguard Worker
append_line(char ** buf,size_t * buflen,char * line)150*d83cc019SAndroid Build Coastguard Worker static void append_line(char **buf, size_t *buflen, char *line)
151*d83cc019SAndroid Build Coastguard Worker {
152*d83cc019SAndroid Build Coastguard Worker size_t linelen = strlen(line);
153*d83cc019SAndroid Build Coastguard Worker
154*d83cc019SAndroid Build Coastguard Worker *buf = realloc(*buf, *buflen + linelen + 1);
155*d83cc019SAndroid Build Coastguard Worker strcpy(*buf + *buflen, line);
156*d83cc019SAndroid Build Coastguard Worker *buflen += linelen;
157*d83cc019SAndroid Build Coastguard Worker }
158*d83cc019SAndroid Build Coastguard Worker
159*d83cc019SAndroid Build Coastguard Worker static const struct {
160*d83cc019SAndroid Build Coastguard Worker const char *output_str;
161*d83cc019SAndroid Build Coastguard Worker const char *result_str;
162*d83cc019SAndroid Build Coastguard Worker } resultmap[] = {
163*d83cc019SAndroid Build Coastguard Worker { "SUCCESS", "pass" },
164*d83cc019SAndroid Build Coastguard Worker { "SKIP", "skip" },
165*d83cc019SAndroid Build Coastguard Worker { "FAIL", "fail" },
166*d83cc019SAndroid Build Coastguard Worker { "CRASH", "crash" },
167*d83cc019SAndroid Build Coastguard Worker { "TIMEOUT", "timeout" },
168*d83cc019SAndroid Build Coastguard Worker };
parse_result_string(char * resultstring,size_t len,const char ** result,double * time)169*d83cc019SAndroid Build Coastguard Worker static void parse_result_string(char *resultstring, size_t len, const char **result, double *time)
170*d83cc019SAndroid Build Coastguard Worker {
171*d83cc019SAndroid Build Coastguard Worker size_t i;
172*d83cc019SAndroid Build Coastguard Worker size_t wordlen = 0;
173*d83cc019SAndroid Build Coastguard Worker
174*d83cc019SAndroid Build Coastguard Worker while (wordlen < len && !isspace(resultstring[wordlen])) {
175*d83cc019SAndroid Build Coastguard Worker wordlen++;
176*d83cc019SAndroid Build Coastguard Worker }
177*d83cc019SAndroid Build Coastguard Worker
178*d83cc019SAndroid Build Coastguard Worker *result = NULL;
179*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < (sizeof(resultmap) / sizeof(resultmap[0])); i++) {
180*d83cc019SAndroid Build Coastguard Worker if (!strncmp(resultstring, resultmap[i].output_str, wordlen)) {
181*d83cc019SAndroid Build Coastguard Worker *result = resultmap[i].result_str;
182*d83cc019SAndroid Build Coastguard Worker break;
183*d83cc019SAndroid Build Coastguard Worker }
184*d83cc019SAndroid Build Coastguard Worker }
185*d83cc019SAndroid Build Coastguard Worker
186*d83cc019SAndroid Build Coastguard Worker /* If the result string is unknown, use incomplete */
187*d83cc019SAndroid Build Coastguard Worker if (!*result)
188*d83cc019SAndroid Build Coastguard Worker *result = "incomplete";
189*d83cc019SAndroid Build Coastguard Worker
190*d83cc019SAndroid Build Coastguard Worker /*
191*d83cc019SAndroid Build Coastguard Worker * Check for subtest runtime after the result. The string is
192*d83cc019SAndroid Build Coastguard Worker * '(' followed by the runtime in seconds as floating point,
193*d83cc019SAndroid Build Coastguard Worker * followed by 's)'.
194*d83cc019SAndroid Build Coastguard Worker */
195*d83cc019SAndroid Build Coastguard Worker wordlen++;
196*d83cc019SAndroid Build Coastguard Worker if (wordlen < len && resultstring[wordlen] == '(') {
197*d83cc019SAndroid Build Coastguard Worker char *dup;
198*d83cc019SAndroid Build Coastguard Worker
199*d83cc019SAndroid Build Coastguard Worker wordlen++;
200*d83cc019SAndroid Build Coastguard Worker dup = malloc(len - wordlen + 1);
201*d83cc019SAndroid Build Coastguard Worker memcpy(dup, resultstring + wordlen, len - wordlen);
202*d83cc019SAndroid Build Coastguard Worker dup[len - wordlen] = '\0';
203*d83cc019SAndroid Build Coastguard Worker *time = strtod(dup, NULL);
204*d83cc019SAndroid Build Coastguard Worker
205*d83cc019SAndroid Build Coastguard Worker free(dup);
206*d83cc019SAndroid Build Coastguard Worker }
207*d83cc019SAndroid Build Coastguard Worker }
208*d83cc019SAndroid Build Coastguard Worker
parse_subtest_result(char * subtest,const char ** result,double * time,char * buf,char * bufend)209*d83cc019SAndroid Build Coastguard Worker static void parse_subtest_result(char *subtest, const char **result, double *time, char *buf, char *bufend)
210*d83cc019SAndroid Build Coastguard Worker {
211*d83cc019SAndroid Build Coastguard Worker char *line;
212*d83cc019SAndroid Build Coastguard Worker char *line_end;
213*d83cc019SAndroid Build Coastguard Worker char *resultstring;
214*d83cc019SAndroid Build Coastguard Worker size_t linelen;
215*d83cc019SAndroid Build Coastguard Worker size_t subtestlen = strlen(subtest);
216*d83cc019SAndroid Build Coastguard Worker
217*d83cc019SAndroid Build Coastguard Worker *result = NULL;
218*d83cc019SAndroid Build Coastguard Worker *time = 0.0;
219*d83cc019SAndroid Build Coastguard Worker
220*d83cc019SAndroid Build Coastguard Worker if (!buf) return;
221*d83cc019SAndroid Build Coastguard Worker
222*d83cc019SAndroid Build Coastguard Worker /*
223*d83cc019SAndroid Build Coastguard Worker * The result line structure is:
224*d83cc019SAndroid Build Coastguard Worker *
225*d83cc019SAndroid Build Coastguard Worker * - The string "Subtest " (`SUBTEST_RESULT` from output_strings.h)
226*d83cc019SAndroid Build Coastguard Worker * - The subtest name
227*d83cc019SAndroid Build Coastguard Worker * - The characters ':' and ' '
228*d83cc019SAndroid Build Coastguard Worker * - Subtest result string
229*d83cc019SAndroid Build Coastguard Worker * - Optional:
230*d83cc019SAndroid Build Coastguard Worker * -- The characters ' ' and '('
231*d83cc019SAndroid Build Coastguard Worker * -- Subtest runtime in seconds as floating point
232*d83cc019SAndroid Build Coastguard Worker * -- The characters 's' and ')'
233*d83cc019SAndroid Build Coastguard Worker *
234*d83cc019SAndroid Build Coastguard Worker * Example:
235*d83cc019SAndroid Build Coastguard Worker * Subtest subtestname: PASS (0.003s)
236*d83cc019SAndroid Build Coastguard Worker */
237*d83cc019SAndroid Build Coastguard Worker
238*d83cc019SAndroid Build Coastguard Worker line = find_line_starting_with(buf, SUBTEST_RESULT, bufend);
239*d83cc019SAndroid Build Coastguard Worker if (!line) {
240*d83cc019SAndroid Build Coastguard Worker *result = "incomplete";
241*d83cc019SAndroid Build Coastguard Worker return;
242*d83cc019SAndroid Build Coastguard Worker }
243*d83cc019SAndroid Build Coastguard Worker
244*d83cc019SAndroid Build Coastguard Worker line_end = memchr(line, '\n', bufend - line);
245*d83cc019SAndroid Build Coastguard Worker linelen = line_end != NULL ? line_end - line : bufend - line;
246*d83cc019SAndroid Build Coastguard Worker
247*d83cc019SAndroid Build Coastguard Worker if (strlen(SUBTEST_RESULT) + subtestlen + strlen(": ") > linelen ||
248*d83cc019SAndroid Build Coastguard Worker strncmp(line + strlen(SUBTEST_RESULT), subtest, subtestlen))
249*d83cc019SAndroid Build Coastguard Worker return parse_subtest_result(subtest, result, time, line + linelen, bufend);
250*d83cc019SAndroid Build Coastguard Worker
251*d83cc019SAndroid Build Coastguard Worker resultstring = line + strlen(SUBTEST_RESULT) + subtestlen + strlen(": ");
252*d83cc019SAndroid Build Coastguard Worker parse_result_string(resultstring, linelen - (resultstring - line), result, time);
253*d83cc019SAndroid Build Coastguard Worker }
254*d83cc019SAndroid Build Coastguard Worker
get_or_create_json_object(struct json_object * base,const char * key)255*d83cc019SAndroid Build Coastguard Worker static struct json_object *get_or_create_json_object(struct json_object *base,
256*d83cc019SAndroid Build Coastguard Worker const char *key)
257*d83cc019SAndroid Build Coastguard Worker {
258*d83cc019SAndroid Build Coastguard Worker struct json_object *ret;
259*d83cc019SAndroid Build Coastguard Worker
260*d83cc019SAndroid Build Coastguard Worker if (json_object_object_get_ex(base, key, &ret))
261*d83cc019SAndroid Build Coastguard Worker return ret;
262*d83cc019SAndroid Build Coastguard Worker
263*d83cc019SAndroid Build Coastguard Worker ret = json_object_new_object();
264*d83cc019SAndroid Build Coastguard Worker json_object_object_add(base, key, ret);
265*d83cc019SAndroid Build Coastguard Worker
266*d83cc019SAndroid Build Coastguard Worker return ret;
267*d83cc019SAndroid Build Coastguard Worker }
268*d83cc019SAndroid Build Coastguard Worker
set_result(struct json_object * obj,const char * result)269*d83cc019SAndroid Build Coastguard Worker static void set_result(struct json_object *obj, const char *result)
270*d83cc019SAndroid Build Coastguard Worker {
271*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "result",
272*d83cc019SAndroid Build Coastguard Worker json_object_new_string(result));
273*d83cc019SAndroid Build Coastguard Worker }
274*d83cc019SAndroid Build Coastguard Worker
add_runtime(struct json_object * obj,double time)275*d83cc019SAndroid Build Coastguard Worker static void add_runtime(struct json_object *obj, double time)
276*d83cc019SAndroid Build Coastguard Worker {
277*d83cc019SAndroid Build Coastguard Worker double oldtime;
278*d83cc019SAndroid Build Coastguard Worker struct json_object *timeobj = get_or_create_json_object(obj, "time");
279*d83cc019SAndroid Build Coastguard Worker struct json_object *oldend;
280*d83cc019SAndroid Build Coastguard Worker
281*d83cc019SAndroid Build Coastguard Worker json_object_object_add(timeobj, "__type__",
282*d83cc019SAndroid Build Coastguard Worker json_object_new_string("TimeAttribute"));
283*d83cc019SAndroid Build Coastguard Worker json_object_object_add(timeobj, "start",
284*d83cc019SAndroid Build Coastguard Worker json_object_new_double(0.0));
285*d83cc019SAndroid Build Coastguard Worker
286*d83cc019SAndroid Build Coastguard Worker if (!json_object_object_get_ex(timeobj, "end", &oldend)) {
287*d83cc019SAndroid Build Coastguard Worker json_object_object_add(timeobj, "end",
288*d83cc019SAndroid Build Coastguard Worker json_object_new_double(time));
289*d83cc019SAndroid Build Coastguard Worker return;
290*d83cc019SAndroid Build Coastguard Worker }
291*d83cc019SAndroid Build Coastguard Worker
292*d83cc019SAndroid Build Coastguard Worker /* Add the runtime to the existing runtime. */
293*d83cc019SAndroid Build Coastguard Worker oldtime = json_object_get_double(oldend);
294*d83cc019SAndroid Build Coastguard Worker time += oldtime;
295*d83cc019SAndroid Build Coastguard Worker json_object_object_add(timeobj, "end",
296*d83cc019SAndroid Build Coastguard Worker json_object_new_double(time));
297*d83cc019SAndroid Build Coastguard Worker }
298*d83cc019SAndroid Build Coastguard Worker
set_runtime(struct json_object * obj,double time)299*d83cc019SAndroid Build Coastguard Worker static void set_runtime(struct json_object *obj, double time)
300*d83cc019SAndroid Build Coastguard Worker {
301*d83cc019SAndroid Build Coastguard Worker struct json_object *timeobj = get_or_create_json_object(obj, "time");
302*d83cc019SAndroid Build Coastguard Worker
303*d83cc019SAndroid Build Coastguard Worker json_object_object_add(timeobj, "__type__",
304*d83cc019SAndroid Build Coastguard Worker json_object_new_string("TimeAttribute"));
305*d83cc019SAndroid Build Coastguard Worker json_object_object_add(timeobj, "start",
306*d83cc019SAndroid Build Coastguard Worker json_object_new_double(0.0));
307*d83cc019SAndroid Build Coastguard Worker json_object_object_add(timeobj, "end",
308*d83cc019SAndroid Build Coastguard Worker json_object_new_double(time));
309*d83cc019SAndroid Build Coastguard Worker }
310*d83cc019SAndroid Build Coastguard Worker
fill_from_output(int fd,const char * binary,const char * key,struct subtests * subtests,struct json_object * tests)311*d83cc019SAndroid Build Coastguard Worker static bool fill_from_output(int fd, const char *binary, const char *key,
312*d83cc019SAndroid Build Coastguard Worker struct subtests *subtests,
313*d83cc019SAndroid Build Coastguard Worker struct json_object *tests)
314*d83cc019SAndroid Build Coastguard Worker {
315*d83cc019SAndroid Build Coastguard Worker char *buf, *bufend, *nullchr;
316*d83cc019SAndroid Build Coastguard Worker struct stat statbuf;
317*d83cc019SAndroid Build Coastguard Worker char piglit_name[256];
318*d83cc019SAndroid Build Coastguard Worker char *igt_version = NULL;
319*d83cc019SAndroid Build Coastguard Worker size_t igt_version_len = 0;
320*d83cc019SAndroid Build Coastguard Worker struct json_object *current_test = NULL;
321*d83cc019SAndroid Build Coastguard Worker size_t i;
322*d83cc019SAndroid Build Coastguard Worker
323*d83cc019SAndroid Build Coastguard Worker if (fstat(fd, &statbuf))
324*d83cc019SAndroid Build Coastguard Worker return false;
325*d83cc019SAndroid Build Coastguard Worker
326*d83cc019SAndroid Build Coastguard Worker if (statbuf.st_size != 0) {
327*d83cc019SAndroid Build Coastguard Worker buf = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
328*d83cc019SAndroid Build Coastguard Worker if (buf == MAP_FAILED)
329*d83cc019SAndroid Build Coastguard Worker return false;
330*d83cc019SAndroid Build Coastguard Worker } else {
331*d83cc019SAndroid Build Coastguard Worker buf = NULL;
332*d83cc019SAndroid Build Coastguard Worker }
333*d83cc019SAndroid Build Coastguard Worker
334*d83cc019SAndroid Build Coastguard Worker /*
335*d83cc019SAndroid Build Coastguard Worker * Avoid null characters: Just pretend the output stops at the
336*d83cc019SAndroid Build Coastguard Worker * first such character, if any.
337*d83cc019SAndroid Build Coastguard Worker */
338*d83cc019SAndroid Build Coastguard Worker if ((nullchr = memchr(buf, '\0', statbuf.st_size)) != NULL) {
339*d83cc019SAndroid Build Coastguard Worker statbuf.st_size = nullchr - buf;
340*d83cc019SAndroid Build Coastguard Worker }
341*d83cc019SAndroid Build Coastguard Worker
342*d83cc019SAndroid Build Coastguard Worker bufend = buf + statbuf.st_size;
343*d83cc019SAndroid Build Coastguard Worker
344*d83cc019SAndroid Build Coastguard Worker igt_version = find_line_starting_with(buf, IGT_VERSIONSTRING, bufend);
345*d83cc019SAndroid Build Coastguard Worker if (igt_version) {
346*d83cc019SAndroid Build Coastguard Worker char *newline = memchr(igt_version, '\n', bufend - igt_version);
347*d83cc019SAndroid Build Coastguard Worker igt_version_len = newline - igt_version;
348*d83cc019SAndroid Build Coastguard Worker }
349*d83cc019SAndroid Build Coastguard Worker
350*d83cc019SAndroid Build Coastguard Worker /* TODO: Refactor to helper functions */
351*d83cc019SAndroid Build Coastguard Worker if (subtests->size == 0) {
352*d83cc019SAndroid Build Coastguard Worker /* No subtests */
353*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(binary, NULL, piglit_name, sizeof(piglit_name));
354*d83cc019SAndroid Build Coastguard Worker current_test = get_or_create_json_object(tests, piglit_name);
355*d83cc019SAndroid Build Coastguard Worker
356*d83cc019SAndroid Build Coastguard Worker json_object_object_add(current_test, key,
357*d83cc019SAndroid Build Coastguard Worker json_object_new_string_len(buf, statbuf.st_size));
358*d83cc019SAndroid Build Coastguard Worker if (igt_version)
359*d83cc019SAndroid Build Coastguard Worker json_object_object_add(current_test, "igt-version",
360*d83cc019SAndroid Build Coastguard Worker json_object_new_string_len(igt_version,
361*d83cc019SAndroid Build Coastguard Worker igt_version_len));
362*d83cc019SAndroid Build Coastguard Worker
363*d83cc019SAndroid Build Coastguard Worker return true;
364*d83cc019SAndroid Build Coastguard Worker }
365*d83cc019SAndroid Build Coastguard Worker
366*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < subtests->size; i++) {
367*d83cc019SAndroid Build Coastguard Worker char *this_sub_begin, *this_sub_result;
368*d83cc019SAndroid Build Coastguard Worker const char *resulttext;
369*d83cc019SAndroid Build Coastguard Worker char *beg, *end, *startline;
370*d83cc019SAndroid Build Coastguard Worker double time;
371*d83cc019SAndroid Build Coastguard Worker int begin_len;
372*d83cc019SAndroid Build Coastguard Worker int result_len;
373*d83cc019SAndroid Build Coastguard Worker
374*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(binary, subtests->names[i], piglit_name, sizeof(piglit_name));
375*d83cc019SAndroid Build Coastguard Worker current_test = get_or_create_json_object(tests, piglit_name);
376*d83cc019SAndroid Build Coastguard Worker
377*d83cc019SAndroid Build Coastguard Worker begin_len = asprintf(&this_sub_begin, "%s%s\n", STARTING_SUBTEST, subtests->names[i]);
378*d83cc019SAndroid Build Coastguard Worker result_len = asprintf(&this_sub_result, "%s%s: ", SUBTEST_RESULT, subtests->names[i]);
379*d83cc019SAndroid Build Coastguard Worker
380*d83cc019SAndroid Build Coastguard Worker if (begin_len < 0 || result_len < 0) {
381*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Failure generating strings\n");
382*d83cc019SAndroid Build Coastguard Worker return false;
383*d83cc019SAndroid Build Coastguard Worker }
384*d83cc019SAndroid Build Coastguard Worker
385*d83cc019SAndroid Build Coastguard Worker beg = find_line_starting_with(buf, this_sub_begin, bufend);
386*d83cc019SAndroid Build Coastguard Worker end = find_line_starting_with(buf, this_sub_result, bufend);
387*d83cc019SAndroid Build Coastguard Worker startline = beg;
388*d83cc019SAndroid Build Coastguard Worker
389*d83cc019SAndroid Build Coastguard Worker free(this_sub_begin);
390*d83cc019SAndroid Build Coastguard Worker free(this_sub_result);
391*d83cc019SAndroid Build Coastguard Worker
392*d83cc019SAndroid Build Coastguard Worker if (beg == NULL && end == NULL) {
393*d83cc019SAndroid Build Coastguard Worker /* No output at all */
394*d83cc019SAndroid Build Coastguard Worker beg = bufend;
395*d83cc019SAndroid Build Coastguard Worker end = bufend;
396*d83cc019SAndroid Build Coastguard Worker }
397*d83cc019SAndroid Build Coastguard Worker
398*d83cc019SAndroid Build Coastguard Worker if (beg == NULL) {
399*d83cc019SAndroid Build Coastguard Worker /*
400*d83cc019SAndroid Build Coastguard Worker * Subtest didn't start, probably skipped from
401*d83cc019SAndroid Build Coastguard Worker * fixture already. Start from the result
402*d83cc019SAndroid Build Coastguard Worker * line, it gets adjusted below.
403*d83cc019SAndroid Build Coastguard Worker */
404*d83cc019SAndroid Build Coastguard Worker beg = end;
405*d83cc019SAndroid Build Coastguard Worker }
406*d83cc019SAndroid Build Coastguard Worker
407*d83cc019SAndroid Build Coastguard Worker /* Include the output after the previous subtest output */
408*d83cc019SAndroid Build Coastguard Worker beg = find_line_after_last(buf,
409*d83cc019SAndroid Build Coastguard Worker STARTING_SUBTEST,
410*d83cc019SAndroid Build Coastguard Worker SUBTEST_RESULT,
411*d83cc019SAndroid Build Coastguard Worker beg);
412*d83cc019SAndroid Build Coastguard Worker
413*d83cc019SAndroid Build Coastguard Worker if (end == NULL) {
414*d83cc019SAndroid Build Coastguard Worker /* Incomplete result. Find the next starting subtest or result. */
415*d83cc019SAndroid Build Coastguard Worker end = next_line(startline, bufend);
416*d83cc019SAndroid Build Coastguard Worker if (end != NULL) {
417*d83cc019SAndroid Build Coastguard Worker end = find_line_starting_with_either(end,
418*d83cc019SAndroid Build Coastguard Worker STARTING_SUBTEST,
419*d83cc019SAndroid Build Coastguard Worker SUBTEST_RESULT,
420*d83cc019SAndroid Build Coastguard Worker bufend);
421*d83cc019SAndroid Build Coastguard Worker }
422*d83cc019SAndroid Build Coastguard Worker if (end == NULL) {
423*d83cc019SAndroid Build Coastguard Worker end = bufend;
424*d83cc019SAndroid Build Coastguard Worker }
425*d83cc019SAndroid Build Coastguard Worker } else {
426*d83cc019SAndroid Build Coastguard Worker /*
427*d83cc019SAndroid Build Coastguard Worker * Now pointing to the line where this sub's
428*d83cc019SAndroid Build Coastguard Worker * result is. We need to include that of
429*d83cc019SAndroid Build Coastguard Worker * course.
430*d83cc019SAndroid Build Coastguard Worker */
431*d83cc019SAndroid Build Coastguard Worker char *nexttest = next_line(end, bufend);
432*d83cc019SAndroid Build Coastguard Worker
433*d83cc019SAndroid Build Coastguard Worker /* Stretch onwards until the next subtest begins or ends */
434*d83cc019SAndroid Build Coastguard Worker if (nexttest != NULL) {
435*d83cc019SAndroid Build Coastguard Worker nexttest = find_line_starting_with_either(nexttest,
436*d83cc019SAndroid Build Coastguard Worker STARTING_SUBTEST,
437*d83cc019SAndroid Build Coastguard Worker SUBTEST_RESULT,
438*d83cc019SAndroid Build Coastguard Worker bufend);
439*d83cc019SAndroid Build Coastguard Worker }
440*d83cc019SAndroid Build Coastguard Worker if (nexttest != NULL) {
441*d83cc019SAndroid Build Coastguard Worker end = nexttest;
442*d83cc019SAndroid Build Coastguard Worker } else {
443*d83cc019SAndroid Build Coastguard Worker end = bufend;
444*d83cc019SAndroid Build Coastguard Worker }
445*d83cc019SAndroid Build Coastguard Worker }
446*d83cc019SAndroid Build Coastguard Worker
447*d83cc019SAndroid Build Coastguard Worker json_object_object_add(current_test, key,
448*d83cc019SAndroid Build Coastguard Worker json_object_new_string_len(beg, end - beg));
449*d83cc019SAndroid Build Coastguard Worker
450*d83cc019SAndroid Build Coastguard Worker if (igt_version) {
451*d83cc019SAndroid Build Coastguard Worker json_object_object_add(current_test, "igt-version",
452*d83cc019SAndroid Build Coastguard Worker json_object_new_string_len(igt_version,
453*d83cc019SAndroid Build Coastguard Worker igt_version_len));
454*d83cc019SAndroid Build Coastguard Worker }
455*d83cc019SAndroid Build Coastguard Worker
456*d83cc019SAndroid Build Coastguard Worker if (!json_object_object_get_ex(current_test, "result", NULL)) {
457*d83cc019SAndroid Build Coastguard Worker parse_subtest_result(subtests->names[i], &resulttext, &time, beg, end);
458*d83cc019SAndroid Build Coastguard Worker set_result(current_test, resulttext);
459*d83cc019SAndroid Build Coastguard Worker set_runtime(current_test, time);
460*d83cc019SAndroid Build Coastguard Worker }
461*d83cc019SAndroid Build Coastguard Worker }
462*d83cc019SAndroid Build Coastguard Worker
463*d83cc019SAndroid Build Coastguard Worker return true;
464*d83cc019SAndroid Build Coastguard Worker }
465*d83cc019SAndroid Build Coastguard Worker
466*d83cc019SAndroid Build Coastguard Worker /*
467*d83cc019SAndroid Build Coastguard Worker * This regexp controls the kmsg handling. All kernel log records that
468*d83cc019SAndroid Build Coastguard Worker * have log level of warning or higher convert the result to
469*d83cc019SAndroid Build Coastguard Worker * dmesg-warn/dmesg-fail unless they match this regexp.
470*d83cc019SAndroid Build Coastguard Worker *
471*d83cc019SAndroid Build Coastguard Worker * TODO: Move this to external files, i915-suppressions.txt,
472*d83cc019SAndroid Build Coastguard Worker * general-suppressions.txt et al.
473*d83cc019SAndroid Build Coastguard Worker */
474*d83cc019SAndroid Build Coastguard Worker
475*d83cc019SAndroid Build Coastguard Worker #define _ "|"
476*d83cc019SAndroid Build Coastguard Worker static const char igt_dmesg_whitelist[] =
477*d83cc019SAndroid Build Coastguard Worker "ACPI: button: The lid device is not compliant to SW_LID" _
478*d83cc019SAndroid Build Coastguard Worker "ACPI: .*: Unable to dock!" _
479*d83cc019SAndroid Build Coastguard Worker "IRQ [0-9]+: no longer affine to CPU[0-9]+" _
480*d83cc019SAndroid Build Coastguard Worker "IRQ fixup: irq [0-9]+ move in progress, old vector [0-9]+" _
481*d83cc019SAndroid Build Coastguard Worker /* i915 tests set module options, expected message */
482*d83cc019SAndroid Build Coastguard Worker "Setting dangerous option [a-z_]+ - tainting kernel" _
483*d83cc019SAndroid Build Coastguard Worker /* Raw printk() call, uses default log level (warn) */
484*d83cc019SAndroid Build Coastguard Worker "Suspending console\\(s\\) \\(use no_console_suspend to debug\\)" _
485*d83cc019SAndroid Build Coastguard Worker "atkbd serio[0-9]+: Failed to (deactivate|enable) keyboard on isa[0-9]+/serio[0-9]+" _
486*d83cc019SAndroid Build Coastguard Worker "cache: parent cpu[0-9]+ should not be sleeping" _
487*d83cc019SAndroid Build Coastguard Worker "hpet[0-9]+: lost [0-9]+ rtc interrupts" _
488*d83cc019SAndroid Build Coastguard Worker /* i915 selftests terminate normally with ENODEV from the
489*d83cc019SAndroid Build Coastguard Worker * module load after the testing finishes, which produces this
490*d83cc019SAndroid Build Coastguard Worker * message.
491*d83cc019SAndroid Build Coastguard Worker */
492*d83cc019SAndroid Build Coastguard Worker "i915: probe of [0-9:.]+ failed with error -25" _
493*d83cc019SAndroid Build Coastguard Worker /* swiotbl warns even when asked not to */
494*d83cc019SAndroid Build Coastguard Worker "mock: DMA: Out of SW-IOMMU space for [0-9]+ bytes" _
495*d83cc019SAndroid Build Coastguard Worker "usb usb[0-9]+: root hub lost power or was reset"
496*d83cc019SAndroid Build Coastguard Worker ;
497*d83cc019SAndroid Build Coastguard Worker #undef _
498*d83cc019SAndroid Build Coastguard Worker
499*d83cc019SAndroid Build Coastguard Worker static const char igt_piglit_style_dmesg_blacklist[] =
500*d83cc019SAndroid Build Coastguard Worker "(\\[drm:|drm_|intel_|i915_)";
501*d83cc019SAndroid Build Coastguard Worker
init_regex_whitelist(struct settings * settings,GRegex ** re)502*d83cc019SAndroid Build Coastguard Worker static bool init_regex_whitelist(struct settings* settings, GRegex **re)
503*d83cc019SAndroid Build Coastguard Worker {
504*d83cc019SAndroid Build Coastguard Worker GError *err = NULL;
505*d83cc019SAndroid Build Coastguard Worker const char *regex = settings->piglit_style_dmesg ?
506*d83cc019SAndroid Build Coastguard Worker igt_piglit_style_dmesg_blacklist :
507*d83cc019SAndroid Build Coastguard Worker igt_dmesg_whitelist;
508*d83cc019SAndroid Build Coastguard Worker
509*d83cc019SAndroid Build Coastguard Worker *re = g_regex_new(regex, G_REGEX_OPTIMIZE, 0, &err);
510*d83cc019SAndroid Build Coastguard Worker if (err) {
511*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Cannot compile dmesg regexp\n");
512*d83cc019SAndroid Build Coastguard Worker g_error_free(err);
513*d83cc019SAndroid Build Coastguard Worker return false;
514*d83cc019SAndroid Build Coastguard Worker }
515*d83cc019SAndroid Build Coastguard Worker
516*d83cc019SAndroid Build Coastguard Worker return true;
517*d83cc019SAndroid Build Coastguard Worker }
518*d83cc019SAndroid Build Coastguard Worker
parse_dmesg_line(char * line,unsigned * flags,unsigned long long * ts_usec,char * continuation,char ** message)519*d83cc019SAndroid Build Coastguard Worker static bool parse_dmesg_line(char* line,
520*d83cc019SAndroid Build Coastguard Worker unsigned *flags, unsigned long long *ts_usec,
521*d83cc019SAndroid Build Coastguard Worker char *continuation, char **message)
522*d83cc019SAndroid Build Coastguard Worker {
523*d83cc019SAndroid Build Coastguard Worker unsigned long long seq;
524*d83cc019SAndroid Build Coastguard Worker int s;
525*d83cc019SAndroid Build Coastguard Worker
526*d83cc019SAndroid Build Coastguard Worker s = sscanf(line, "%u,%llu,%llu,%c;", flags, &seq, ts_usec, continuation);
527*d83cc019SAndroid Build Coastguard Worker if (s != 4) {
528*d83cc019SAndroid Build Coastguard Worker /*
529*d83cc019SAndroid Build Coastguard Worker * Machine readable key/value pairs begin with
530*d83cc019SAndroid Build Coastguard Worker * a space. We ignore them.
531*d83cc019SAndroid Build Coastguard Worker */
532*d83cc019SAndroid Build Coastguard Worker if (line[0] != ' ') {
533*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Cannot parse kmsg record: %s\n", line);
534*d83cc019SAndroid Build Coastguard Worker }
535*d83cc019SAndroid Build Coastguard Worker return false;
536*d83cc019SAndroid Build Coastguard Worker }
537*d83cc019SAndroid Build Coastguard Worker
538*d83cc019SAndroid Build Coastguard Worker *message = strchr(line, ';');
539*d83cc019SAndroid Build Coastguard Worker if (!message) {
540*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "No ; found in kmsg record, this shouldn't happen\n");
541*d83cc019SAndroid Build Coastguard Worker return false;
542*d83cc019SAndroid Build Coastguard Worker }
543*d83cc019SAndroid Build Coastguard Worker (*message)++;
544*d83cc019SAndroid Build Coastguard Worker
545*d83cc019SAndroid Build Coastguard Worker return true;
546*d83cc019SAndroid Build Coastguard Worker }
547*d83cc019SAndroid Build Coastguard Worker
generate_formatted_dmesg_line(char * message,unsigned flags,unsigned long long ts_usec,char ** formatted)548*d83cc019SAndroid Build Coastguard Worker static void generate_formatted_dmesg_line(char *message,
549*d83cc019SAndroid Build Coastguard Worker unsigned flags,
550*d83cc019SAndroid Build Coastguard Worker unsigned long long ts_usec,
551*d83cc019SAndroid Build Coastguard Worker char **formatted)
552*d83cc019SAndroid Build Coastguard Worker {
553*d83cc019SAndroid Build Coastguard Worker char prefix[512];
554*d83cc019SAndroid Build Coastguard Worker size_t messagelen;
555*d83cc019SAndroid Build Coastguard Worker size_t prefixlen;
556*d83cc019SAndroid Build Coastguard Worker char *p, *f;
557*d83cc019SAndroid Build Coastguard Worker
558*d83cc019SAndroid Build Coastguard Worker snprintf(prefix, sizeof(prefix),
559*d83cc019SAndroid Build Coastguard Worker "<%u> [%llu.%06llu] ",
560*d83cc019SAndroid Build Coastguard Worker flags & 0x07,
561*d83cc019SAndroid Build Coastguard Worker ts_usec / 1000000,
562*d83cc019SAndroid Build Coastguard Worker ts_usec % 1000000);
563*d83cc019SAndroid Build Coastguard Worker
564*d83cc019SAndroid Build Coastguard Worker messagelen = strlen(message);
565*d83cc019SAndroid Build Coastguard Worker prefixlen = strlen(prefix);
566*d83cc019SAndroid Build Coastguard Worker
567*d83cc019SAndroid Build Coastguard Worker /*
568*d83cc019SAndroid Build Coastguard Worker * Decoding the hex escapes only makes the string shorter, so
569*d83cc019SAndroid Build Coastguard Worker * we can use the original length
570*d83cc019SAndroid Build Coastguard Worker */
571*d83cc019SAndroid Build Coastguard Worker *formatted = malloc(strlen(prefix) + messagelen + 1);
572*d83cc019SAndroid Build Coastguard Worker strcpy(*formatted, prefix);
573*d83cc019SAndroid Build Coastguard Worker
574*d83cc019SAndroid Build Coastguard Worker f = *formatted + prefixlen;
575*d83cc019SAndroid Build Coastguard Worker for (p = message; *p; p++, f++) {
576*d83cc019SAndroid Build Coastguard Worker if (p - message + 4 < messagelen &&
577*d83cc019SAndroid Build Coastguard Worker p[0] == '\\' && p[1] == 'x') {
578*d83cc019SAndroid Build Coastguard Worker int c = 0;
579*d83cc019SAndroid Build Coastguard Worker /* newline and tab are not isprint(), but they are isspace() */
580*d83cc019SAndroid Build Coastguard Worker if (sscanf(p, "\\x%2x", &c) == 1 &&
581*d83cc019SAndroid Build Coastguard Worker (isprint(c) || isspace(c))) {
582*d83cc019SAndroid Build Coastguard Worker *f = c;
583*d83cc019SAndroid Build Coastguard Worker p += 3;
584*d83cc019SAndroid Build Coastguard Worker continue;
585*d83cc019SAndroid Build Coastguard Worker }
586*d83cc019SAndroid Build Coastguard Worker }
587*d83cc019SAndroid Build Coastguard Worker *f = *p;
588*d83cc019SAndroid Build Coastguard Worker }
589*d83cc019SAndroid Build Coastguard Worker *f = '\0';
590*d83cc019SAndroid Build Coastguard Worker }
591*d83cc019SAndroid Build Coastguard Worker
add_dmesg(struct json_object * obj,const char * dmesg,size_t dmesglen,const char * warnings,size_t warningslen)592*d83cc019SAndroid Build Coastguard Worker static void add_dmesg(struct json_object *obj,
593*d83cc019SAndroid Build Coastguard Worker const char *dmesg, size_t dmesglen,
594*d83cc019SAndroid Build Coastguard Worker const char *warnings, size_t warningslen)
595*d83cc019SAndroid Build Coastguard Worker {
596*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "dmesg",
597*d83cc019SAndroid Build Coastguard Worker json_object_new_string_len(dmesg, dmesglen));
598*d83cc019SAndroid Build Coastguard Worker
599*d83cc019SAndroid Build Coastguard Worker if (warnings) {
600*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "dmesg-warnings",
601*d83cc019SAndroid Build Coastguard Worker json_object_new_string_len(warnings, warningslen));
602*d83cc019SAndroid Build Coastguard Worker }
603*d83cc019SAndroid Build Coastguard Worker }
604*d83cc019SAndroid Build Coastguard Worker
add_empty_dmesgs_where_missing(struct json_object * tests,char * binary,struct subtests * subtests)605*d83cc019SAndroid Build Coastguard Worker static void add_empty_dmesgs_where_missing(struct json_object *tests,
606*d83cc019SAndroid Build Coastguard Worker char *binary,
607*d83cc019SAndroid Build Coastguard Worker struct subtests *subtests)
608*d83cc019SAndroid Build Coastguard Worker {
609*d83cc019SAndroid Build Coastguard Worker struct json_object *current_test;
610*d83cc019SAndroid Build Coastguard Worker char piglit_name[256];
611*d83cc019SAndroid Build Coastguard Worker size_t i;
612*d83cc019SAndroid Build Coastguard Worker
613*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < subtests->size; i++) {
614*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(binary, subtests->names[i], piglit_name, sizeof(piglit_name));
615*d83cc019SAndroid Build Coastguard Worker current_test = get_or_create_json_object(tests, piglit_name);
616*d83cc019SAndroid Build Coastguard Worker if (!json_object_object_get_ex(current_test, "dmesg", NULL)) {
617*d83cc019SAndroid Build Coastguard Worker add_dmesg(current_test, "", 0, NULL, 0);
618*d83cc019SAndroid Build Coastguard Worker }
619*d83cc019SAndroid Build Coastguard Worker }
620*d83cc019SAndroid Build Coastguard Worker
621*d83cc019SAndroid Build Coastguard Worker }
622*d83cc019SAndroid Build Coastguard Worker
fill_from_dmesg(int fd,struct settings * settings,char * binary,struct subtests * subtests,struct json_object * tests)623*d83cc019SAndroid Build Coastguard Worker static bool fill_from_dmesg(int fd,
624*d83cc019SAndroid Build Coastguard Worker struct settings *settings,
625*d83cc019SAndroid Build Coastguard Worker char *binary,
626*d83cc019SAndroid Build Coastguard Worker struct subtests *subtests,
627*d83cc019SAndroid Build Coastguard Worker struct json_object *tests)
628*d83cc019SAndroid Build Coastguard Worker {
629*d83cc019SAndroid Build Coastguard Worker char *line = NULL, *warnings = NULL, *dmesg = NULL;
630*d83cc019SAndroid Build Coastguard Worker size_t linelen = 0, warningslen = 0, dmesglen = 0;
631*d83cc019SAndroid Build Coastguard Worker struct json_object *current_test = NULL;
632*d83cc019SAndroid Build Coastguard Worker FILE *f = fdopen(fd, "r");
633*d83cc019SAndroid Build Coastguard Worker char piglit_name[256];
634*d83cc019SAndroid Build Coastguard Worker ssize_t read;
635*d83cc019SAndroid Build Coastguard Worker size_t i;
636*d83cc019SAndroid Build Coastguard Worker GRegex *re;
637*d83cc019SAndroid Build Coastguard Worker
638*d83cc019SAndroid Build Coastguard Worker if (!f) {
639*d83cc019SAndroid Build Coastguard Worker return false;
640*d83cc019SAndroid Build Coastguard Worker }
641*d83cc019SAndroid Build Coastguard Worker
642*d83cc019SAndroid Build Coastguard Worker if (!init_regex_whitelist(settings, &re)) {
643*d83cc019SAndroid Build Coastguard Worker fclose(f);
644*d83cc019SAndroid Build Coastguard Worker return false;
645*d83cc019SAndroid Build Coastguard Worker }
646*d83cc019SAndroid Build Coastguard Worker
647*d83cc019SAndroid Build Coastguard Worker while ((read = getline(&line, &linelen, f)) > 0) {
648*d83cc019SAndroid Build Coastguard Worker char *formatted;
649*d83cc019SAndroid Build Coastguard Worker unsigned flags;
650*d83cc019SAndroid Build Coastguard Worker unsigned long long ts_usec;
651*d83cc019SAndroid Build Coastguard Worker char continuation;
652*d83cc019SAndroid Build Coastguard Worker char *message, *subtest;
653*d83cc019SAndroid Build Coastguard Worker
654*d83cc019SAndroid Build Coastguard Worker if (!parse_dmesg_line(line, &flags, &ts_usec, &continuation, &message))
655*d83cc019SAndroid Build Coastguard Worker continue;
656*d83cc019SAndroid Build Coastguard Worker
657*d83cc019SAndroid Build Coastguard Worker generate_formatted_dmesg_line(message, flags, ts_usec, &formatted);
658*d83cc019SAndroid Build Coastguard Worker
659*d83cc019SAndroid Build Coastguard Worker if ((subtest = strstr(message, STARTING_SUBTEST_DMESG)) != NULL) {
660*d83cc019SAndroid Build Coastguard Worker if (current_test != NULL) {
661*d83cc019SAndroid Build Coastguard Worker /* Done with the previous subtest, file up */
662*d83cc019SAndroid Build Coastguard Worker add_dmesg(current_test, dmesg, dmesglen, warnings, warningslen);
663*d83cc019SAndroid Build Coastguard Worker
664*d83cc019SAndroid Build Coastguard Worker free(dmesg);
665*d83cc019SAndroid Build Coastguard Worker free(warnings);
666*d83cc019SAndroid Build Coastguard Worker dmesg = warnings = NULL;
667*d83cc019SAndroid Build Coastguard Worker dmesglen = warningslen = 0;
668*d83cc019SAndroid Build Coastguard Worker }
669*d83cc019SAndroid Build Coastguard Worker
670*d83cc019SAndroid Build Coastguard Worker subtest += strlen(STARTING_SUBTEST_DMESG);
671*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(binary, subtest, piglit_name, sizeof(piglit_name));
672*d83cc019SAndroid Build Coastguard Worker current_test = get_or_create_json_object(tests, piglit_name);
673*d83cc019SAndroid Build Coastguard Worker }
674*d83cc019SAndroid Build Coastguard Worker
675*d83cc019SAndroid Build Coastguard Worker if (settings->piglit_style_dmesg) {
676*d83cc019SAndroid Build Coastguard Worker if ((flags & 0x07) <= settings->dmesg_warn_level && continuation != 'c' &&
677*d83cc019SAndroid Build Coastguard Worker g_regex_match(re, message, 0, NULL)) {
678*d83cc019SAndroid Build Coastguard Worker append_line(&warnings, &warningslen, formatted);
679*d83cc019SAndroid Build Coastguard Worker }
680*d83cc019SAndroid Build Coastguard Worker } else {
681*d83cc019SAndroid Build Coastguard Worker if ((flags & 0x07) <= settings->dmesg_warn_level && continuation != 'c' &&
682*d83cc019SAndroid Build Coastguard Worker !g_regex_match(re, message, 0, NULL)) {
683*d83cc019SAndroid Build Coastguard Worker append_line(&warnings, &warningslen, formatted);
684*d83cc019SAndroid Build Coastguard Worker }
685*d83cc019SAndroid Build Coastguard Worker }
686*d83cc019SAndroid Build Coastguard Worker append_line(&dmesg, &dmesglen, formatted);
687*d83cc019SAndroid Build Coastguard Worker free(formatted);
688*d83cc019SAndroid Build Coastguard Worker }
689*d83cc019SAndroid Build Coastguard Worker free(line);
690*d83cc019SAndroid Build Coastguard Worker
691*d83cc019SAndroid Build Coastguard Worker if (current_test != NULL) {
692*d83cc019SAndroid Build Coastguard Worker add_dmesg(current_test, dmesg, dmesglen, warnings, warningslen);
693*d83cc019SAndroid Build Coastguard Worker } else {
694*d83cc019SAndroid Build Coastguard Worker /*
695*d83cc019SAndroid Build Coastguard Worker * Didn't get any subtest messages at all. If there
696*d83cc019SAndroid Build Coastguard Worker * are subtests, add all of the dmesg gotten to all of
697*d83cc019SAndroid Build Coastguard Worker * them.
698*d83cc019SAndroid Build Coastguard Worker */
699*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < subtests->size; i++) {
700*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(binary, subtests->names[i], piglit_name, sizeof(piglit_name));
701*d83cc019SAndroid Build Coastguard Worker current_test = get_or_create_json_object(tests, piglit_name);
702*d83cc019SAndroid Build Coastguard Worker /*
703*d83cc019SAndroid Build Coastguard Worker * Don't bother with warnings, any subtests
704*d83cc019SAndroid Build Coastguard Worker * there are would have skip as their result
705*d83cc019SAndroid Build Coastguard Worker * anyway.
706*d83cc019SAndroid Build Coastguard Worker */
707*d83cc019SAndroid Build Coastguard Worker add_dmesg(current_test, dmesg, dmesglen, NULL, 0);
708*d83cc019SAndroid Build Coastguard Worker }
709*d83cc019SAndroid Build Coastguard Worker
710*d83cc019SAndroid Build Coastguard Worker if (subtests->size == 0) {
711*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(binary, NULL, piglit_name, sizeof(piglit_name));
712*d83cc019SAndroid Build Coastguard Worker current_test = get_or_create_json_object(tests, piglit_name);
713*d83cc019SAndroid Build Coastguard Worker add_dmesg(current_test, dmesg, dmesglen, warnings, warningslen);
714*d83cc019SAndroid Build Coastguard Worker }
715*d83cc019SAndroid Build Coastguard Worker }
716*d83cc019SAndroid Build Coastguard Worker
717*d83cc019SAndroid Build Coastguard Worker add_empty_dmesgs_where_missing(tests, binary, subtests);
718*d83cc019SAndroid Build Coastguard Worker
719*d83cc019SAndroid Build Coastguard Worker free(dmesg);
720*d83cc019SAndroid Build Coastguard Worker free(warnings);
721*d83cc019SAndroid Build Coastguard Worker g_regex_unref(re);
722*d83cc019SAndroid Build Coastguard Worker fclose(f);
723*d83cc019SAndroid Build Coastguard Worker return true;
724*d83cc019SAndroid Build Coastguard Worker }
725*d83cc019SAndroid Build Coastguard Worker
result_from_exitcode(int exitcode)726*d83cc019SAndroid Build Coastguard Worker static const char *result_from_exitcode(int exitcode)
727*d83cc019SAndroid Build Coastguard Worker {
728*d83cc019SAndroid Build Coastguard Worker switch (exitcode) {
729*d83cc019SAndroid Build Coastguard Worker case IGT_EXIT_SKIP:
730*d83cc019SAndroid Build Coastguard Worker return "skip";
731*d83cc019SAndroid Build Coastguard Worker case IGT_EXIT_SUCCESS:
732*d83cc019SAndroid Build Coastguard Worker return "pass";
733*d83cc019SAndroid Build Coastguard Worker case IGT_EXIT_INVALID:
734*d83cc019SAndroid Build Coastguard Worker return "notrun";
735*d83cc019SAndroid Build Coastguard Worker case INCOMPLETE_EXITCODE:
736*d83cc019SAndroid Build Coastguard Worker return "incomplete";
737*d83cc019SAndroid Build Coastguard Worker default:
738*d83cc019SAndroid Build Coastguard Worker return "fail";
739*d83cc019SAndroid Build Coastguard Worker }
740*d83cc019SAndroid Build Coastguard Worker }
741*d83cc019SAndroid Build Coastguard Worker
add_subtest(struct subtests * subtests,char * subtest)742*d83cc019SAndroid Build Coastguard Worker static void add_subtest(struct subtests *subtests, char *subtest)
743*d83cc019SAndroid Build Coastguard Worker {
744*d83cc019SAndroid Build Coastguard Worker size_t len = strlen(subtest);
745*d83cc019SAndroid Build Coastguard Worker size_t i;
746*d83cc019SAndroid Build Coastguard Worker
747*d83cc019SAndroid Build Coastguard Worker if (len == 0)
748*d83cc019SAndroid Build Coastguard Worker return;
749*d83cc019SAndroid Build Coastguard Worker
750*d83cc019SAndroid Build Coastguard Worker if (subtest[len - 1] == '\n')
751*d83cc019SAndroid Build Coastguard Worker subtest[len - 1] = '\0';
752*d83cc019SAndroid Build Coastguard Worker
753*d83cc019SAndroid Build Coastguard Worker /* Don't add if we already have this subtest */
754*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < subtests->size; i++)
755*d83cc019SAndroid Build Coastguard Worker if (!strcmp(subtest, subtests->names[i]))
756*d83cc019SAndroid Build Coastguard Worker return;
757*d83cc019SAndroid Build Coastguard Worker
758*d83cc019SAndroid Build Coastguard Worker subtests->size++;
759*d83cc019SAndroid Build Coastguard Worker subtests->names = realloc(subtests->names, sizeof(*subtests->names) * subtests->size);
760*d83cc019SAndroid Build Coastguard Worker subtests->names[subtests->size - 1] = subtest;
761*d83cc019SAndroid Build Coastguard Worker }
762*d83cc019SAndroid Build Coastguard Worker
free_subtests(struct subtests * subtests)763*d83cc019SAndroid Build Coastguard Worker static void free_subtests(struct subtests *subtests)
764*d83cc019SAndroid Build Coastguard Worker {
765*d83cc019SAndroid Build Coastguard Worker size_t i;
766*d83cc019SAndroid Build Coastguard Worker
767*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < subtests->size; i++)
768*d83cc019SAndroid Build Coastguard Worker free(subtests->names[i]);
769*d83cc019SAndroid Build Coastguard Worker free(subtests->names);
770*d83cc019SAndroid Build Coastguard Worker }
771*d83cc019SAndroid Build Coastguard Worker
fill_from_journal(int fd,struct job_list_entry * entry,struct subtests * subtests,struct results * results)772*d83cc019SAndroid Build Coastguard Worker static void fill_from_journal(int fd,
773*d83cc019SAndroid Build Coastguard Worker struct job_list_entry *entry,
774*d83cc019SAndroid Build Coastguard Worker struct subtests *subtests,
775*d83cc019SAndroid Build Coastguard Worker struct results *results)
776*d83cc019SAndroid Build Coastguard Worker {
777*d83cc019SAndroid Build Coastguard Worker FILE *f = fdopen(fd, "r");
778*d83cc019SAndroid Build Coastguard Worker char *line = NULL;
779*d83cc019SAndroid Build Coastguard Worker size_t linelen = 0;
780*d83cc019SAndroid Build Coastguard Worker ssize_t read;
781*d83cc019SAndroid Build Coastguard Worker char exitline[] = "exit:";
782*d83cc019SAndroid Build Coastguard Worker char timeoutline[] = "timeout:";
783*d83cc019SAndroid Build Coastguard Worker int exitcode = INCOMPLETE_EXITCODE;
784*d83cc019SAndroid Build Coastguard Worker bool has_timeout = false;
785*d83cc019SAndroid Build Coastguard Worker struct json_object *tests = results->tests;
786*d83cc019SAndroid Build Coastguard Worker struct json_object *runtimes = results->runtimes;
787*d83cc019SAndroid Build Coastguard Worker
788*d83cc019SAndroid Build Coastguard Worker while ((read = getline(&line, &linelen, f)) > 0) {
789*d83cc019SAndroid Build Coastguard Worker if (read >= strlen(exitline) && !memcmp(line, exitline, strlen(exitline))) {
790*d83cc019SAndroid Build Coastguard Worker char *p = strchr(line, '(');
791*d83cc019SAndroid Build Coastguard Worker char piglit_name[256];
792*d83cc019SAndroid Build Coastguard Worker double time = 0.0;
793*d83cc019SAndroid Build Coastguard Worker struct json_object *obj;
794*d83cc019SAndroid Build Coastguard Worker
795*d83cc019SAndroid Build Coastguard Worker exitcode = atoi(line + strlen(exitline));
796*d83cc019SAndroid Build Coastguard Worker
797*d83cc019SAndroid Build Coastguard Worker if (p)
798*d83cc019SAndroid Build Coastguard Worker time = strtod(p + 1, NULL);
799*d83cc019SAndroid Build Coastguard Worker
800*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(entry->binary, NULL, piglit_name, sizeof(piglit_name));
801*d83cc019SAndroid Build Coastguard Worker obj = get_or_create_json_object(runtimes, piglit_name);
802*d83cc019SAndroid Build Coastguard Worker add_runtime(obj, time);
803*d83cc019SAndroid Build Coastguard Worker
804*d83cc019SAndroid Build Coastguard Worker /* If no subtests, the test result node also gets the runtime */
805*d83cc019SAndroid Build Coastguard Worker if (subtests->size == 0 && entry->subtest_count == 0) {
806*d83cc019SAndroid Build Coastguard Worker obj = get_or_create_json_object(tests, piglit_name);
807*d83cc019SAndroid Build Coastguard Worker add_runtime(obj, time);
808*d83cc019SAndroid Build Coastguard Worker }
809*d83cc019SAndroid Build Coastguard Worker } else if (read >= strlen(timeoutline) && !memcmp(line, timeoutline, strlen(timeoutline))) {
810*d83cc019SAndroid Build Coastguard Worker has_timeout = true;
811*d83cc019SAndroid Build Coastguard Worker
812*d83cc019SAndroid Build Coastguard Worker if (subtests->size) {
813*d83cc019SAndroid Build Coastguard Worker /* Assign the timeout to the previously appeared subtest */
814*d83cc019SAndroid Build Coastguard Worker char *last_subtest = subtests->names[subtests->size - 1];
815*d83cc019SAndroid Build Coastguard Worker char piglit_name[256];
816*d83cc019SAndroid Build Coastguard Worker char *p = strchr(line, '(');
817*d83cc019SAndroid Build Coastguard Worker double time = 0.0;
818*d83cc019SAndroid Build Coastguard Worker struct json_object *obj;
819*d83cc019SAndroid Build Coastguard Worker
820*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(entry->binary, last_subtest, piglit_name, sizeof(piglit_name));
821*d83cc019SAndroid Build Coastguard Worker obj = get_or_create_json_object(tests, piglit_name);
822*d83cc019SAndroid Build Coastguard Worker
823*d83cc019SAndroid Build Coastguard Worker set_result(obj, "timeout");
824*d83cc019SAndroid Build Coastguard Worker
825*d83cc019SAndroid Build Coastguard Worker if (p)
826*d83cc019SAndroid Build Coastguard Worker time = strtod(p + 1, NULL);
827*d83cc019SAndroid Build Coastguard Worker
828*d83cc019SAndroid Build Coastguard Worker /* Add runtime for the subtest... */
829*d83cc019SAndroid Build Coastguard Worker add_runtime(obj, time);
830*d83cc019SAndroid Build Coastguard Worker
831*d83cc019SAndroid Build Coastguard Worker /* ... and also for the binary */
832*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(entry->binary, NULL, piglit_name, sizeof(piglit_name));
833*d83cc019SAndroid Build Coastguard Worker obj = get_or_create_json_object(runtimes, piglit_name);
834*d83cc019SAndroid Build Coastguard Worker add_runtime(obj, time);
835*d83cc019SAndroid Build Coastguard Worker }
836*d83cc019SAndroid Build Coastguard Worker } else {
837*d83cc019SAndroid Build Coastguard Worker add_subtest(subtests, strdup(line));
838*d83cc019SAndroid Build Coastguard Worker }
839*d83cc019SAndroid Build Coastguard Worker }
840*d83cc019SAndroid Build Coastguard Worker
841*d83cc019SAndroid Build Coastguard Worker if (subtests->size == 0) {
842*d83cc019SAndroid Build Coastguard Worker char *subtestname = NULL;
843*d83cc019SAndroid Build Coastguard Worker char piglit_name[256];
844*d83cc019SAndroid Build Coastguard Worker struct json_object *obj;
845*d83cc019SAndroid Build Coastguard Worker const char *result = has_timeout ? "timeout" : result_from_exitcode(exitcode);
846*d83cc019SAndroid Build Coastguard Worker
847*d83cc019SAndroid Build Coastguard Worker /*
848*d83cc019SAndroid Build Coastguard Worker * If the test was killed before it printed that it's
849*d83cc019SAndroid Build Coastguard Worker * entering a subtest, we would incorrectly generate
850*d83cc019SAndroid Build Coastguard Worker * results as the binary had no subtests. If we know
851*d83cc019SAndroid Build Coastguard Worker * otherwise, do otherwise.
852*d83cc019SAndroid Build Coastguard Worker */
853*d83cc019SAndroid Build Coastguard Worker if (entry->subtest_count > 0) {
854*d83cc019SAndroid Build Coastguard Worker subtestname = entry->subtests[0];
855*d83cc019SAndroid Build Coastguard Worker add_subtest(subtests, strdup(subtestname));
856*d83cc019SAndroid Build Coastguard Worker }
857*d83cc019SAndroid Build Coastguard Worker
858*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(entry->binary, subtestname, piglit_name, sizeof(piglit_name));
859*d83cc019SAndroid Build Coastguard Worker obj = get_or_create_json_object(tests, piglit_name);
860*d83cc019SAndroid Build Coastguard Worker set_result(obj, result);
861*d83cc019SAndroid Build Coastguard Worker }
862*d83cc019SAndroid Build Coastguard Worker
863*d83cc019SAndroid Build Coastguard Worker free(line);
864*d83cc019SAndroid Build Coastguard Worker fclose(f);
865*d83cc019SAndroid Build Coastguard Worker }
866*d83cc019SAndroid Build Coastguard Worker
override_result_single(struct json_object * obj)867*d83cc019SAndroid Build Coastguard Worker static void override_result_single(struct json_object *obj)
868*d83cc019SAndroid Build Coastguard Worker {
869*d83cc019SAndroid Build Coastguard Worker const char *errtext = "", *result = "";
870*d83cc019SAndroid Build Coastguard Worker struct json_object *textobj;
871*d83cc019SAndroid Build Coastguard Worker bool dmesgwarns = false;
872*d83cc019SAndroid Build Coastguard Worker
873*d83cc019SAndroid Build Coastguard Worker if (json_object_object_get_ex(obj, "err", &textobj))
874*d83cc019SAndroid Build Coastguard Worker errtext = json_object_get_string(textobj);
875*d83cc019SAndroid Build Coastguard Worker if (json_object_object_get_ex(obj, "result", &textobj))
876*d83cc019SAndroid Build Coastguard Worker result = json_object_get_string(textobj);
877*d83cc019SAndroid Build Coastguard Worker if (json_object_object_get_ex(obj, "dmesg-warnings", &textobj))
878*d83cc019SAndroid Build Coastguard Worker dmesgwarns = true;
879*d83cc019SAndroid Build Coastguard Worker
880*d83cc019SAndroid Build Coastguard Worker if (!strcmp(result, "pass") &&
881*d83cc019SAndroid Build Coastguard Worker count_lines(errtext, errtext + strlen(errtext)) > 2) {
882*d83cc019SAndroid Build Coastguard Worker set_result(obj, "warn");
883*d83cc019SAndroid Build Coastguard Worker result = "warn";
884*d83cc019SAndroid Build Coastguard Worker }
885*d83cc019SAndroid Build Coastguard Worker
886*d83cc019SAndroid Build Coastguard Worker if (dmesgwarns) {
887*d83cc019SAndroid Build Coastguard Worker if (!strcmp(result, "pass") || !strcmp(result, "warn")) {
888*d83cc019SAndroid Build Coastguard Worker set_result(obj, "dmesg-warn");
889*d83cc019SAndroid Build Coastguard Worker } else if (!strcmp(result, "fail")) {
890*d83cc019SAndroid Build Coastguard Worker set_result(obj, "dmesg-fail");
891*d83cc019SAndroid Build Coastguard Worker }
892*d83cc019SAndroid Build Coastguard Worker }
893*d83cc019SAndroid Build Coastguard Worker }
894*d83cc019SAndroid Build Coastguard Worker
override_results(char * binary,struct subtests * subtests,struct json_object * tests)895*d83cc019SAndroid Build Coastguard Worker static void override_results(char *binary,
896*d83cc019SAndroid Build Coastguard Worker struct subtests *subtests,
897*d83cc019SAndroid Build Coastguard Worker struct json_object *tests)
898*d83cc019SAndroid Build Coastguard Worker {
899*d83cc019SAndroid Build Coastguard Worker struct json_object *obj;
900*d83cc019SAndroid Build Coastguard Worker char piglit_name[256];
901*d83cc019SAndroid Build Coastguard Worker size_t i;
902*d83cc019SAndroid Build Coastguard Worker
903*d83cc019SAndroid Build Coastguard Worker if (subtests->size == 0) {
904*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(binary, NULL, piglit_name, sizeof(piglit_name));
905*d83cc019SAndroid Build Coastguard Worker obj = get_or_create_json_object(tests, piglit_name);
906*d83cc019SAndroid Build Coastguard Worker override_result_single(obj);
907*d83cc019SAndroid Build Coastguard Worker return;
908*d83cc019SAndroid Build Coastguard Worker }
909*d83cc019SAndroid Build Coastguard Worker
910*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < subtests->size; i++) {
911*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(binary, subtests->names[i], piglit_name, sizeof(piglit_name));
912*d83cc019SAndroid Build Coastguard Worker obj = get_or_create_json_object(tests, piglit_name);
913*d83cc019SAndroid Build Coastguard Worker override_result_single(obj);
914*d83cc019SAndroid Build Coastguard Worker }
915*d83cc019SAndroid Build Coastguard Worker }
916*d83cc019SAndroid Build Coastguard Worker
get_totals_object(struct json_object * totals,const char * key)917*d83cc019SAndroid Build Coastguard Worker static struct json_object *get_totals_object(struct json_object *totals,
918*d83cc019SAndroid Build Coastguard Worker const char *key)
919*d83cc019SAndroid Build Coastguard Worker {
920*d83cc019SAndroid Build Coastguard Worker struct json_object *obj = NULL;
921*d83cc019SAndroid Build Coastguard Worker
922*d83cc019SAndroid Build Coastguard Worker if (json_object_object_get_ex(totals, key, &obj))
923*d83cc019SAndroid Build Coastguard Worker return obj;
924*d83cc019SAndroid Build Coastguard Worker
925*d83cc019SAndroid Build Coastguard Worker obj = json_object_new_object();
926*d83cc019SAndroid Build Coastguard Worker json_object_object_add(totals, key, obj);
927*d83cc019SAndroid Build Coastguard Worker
928*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "crash", json_object_new_int(0));
929*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "pass", json_object_new_int(0));
930*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "dmesg-fail", json_object_new_int(0));
931*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "dmesg-warn", json_object_new_int(0));
932*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "skip", json_object_new_int(0));
933*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "incomplete", json_object_new_int(0));
934*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "timeout", json_object_new_int(0));
935*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "notrun", json_object_new_int(0));
936*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "fail", json_object_new_int(0));
937*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "warn", json_object_new_int(0));
938*d83cc019SAndroid Build Coastguard Worker
939*d83cc019SAndroid Build Coastguard Worker return obj;
940*d83cc019SAndroid Build Coastguard Worker }
941*d83cc019SAndroid Build Coastguard Worker
add_result_to_totals(struct json_object * totals,const char * result)942*d83cc019SAndroid Build Coastguard Worker static void add_result_to_totals(struct json_object *totals,
943*d83cc019SAndroid Build Coastguard Worker const char *result)
944*d83cc019SAndroid Build Coastguard Worker {
945*d83cc019SAndroid Build Coastguard Worker json_object *numobj = NULL;
946*d83cc019SAndroid Build Coastguard Worker int old;
947*d83cc019SAndroid Build Coastguard Worker
948*d83cc019SAndroid Build Coastguard Worker if (!json_object_object_get_ex(totals, result, &numobj)) {
949*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Warning: Totals object without count for %s\n", result);
950*d83cc019SAndroid Build Coastguard Worker return;
951*d83cc019SAndroid Build Coastguard Worker }
952*d83cc019SAndroid Build Coastguard Worker
953*d83cc019SAndroid Build Coastguard Worker old = json_object_get_int(numobj);
954*d83cc019SAndroid Build Coastguard Worker json_object_object_add(totals, result, json_object_new_int(old + 1));
955*d83cc019SAndroid Build Coastguard Worker }
956*d83cc019SAndroid Build Coastguard Worker
add_to_totals(const char * binary,struct subtests * subtests,struct results * results)957*d83cc019SAndroid Build Coastguard Worker static void add_to_totals(const char *binary,
958*d83cc019SAndroid Build Coastguard Worker struct subtests *subtests,
959*d83cc019SAndroid Build Coastguard Worker struct results *results)
960*d83cc019SAndroid Build Coastguard Worker {
961*d83cc019SAndroid Build Coastguard Worker struct json_object *test, *resultobj, *emptystrtotal, *roottotal, *binarytotal;
962*d83cc019SAndroid Build Coastguard Worker char piglit_name[256];
963*d83cc019SAndroid Build Coastguard Worker const char *result;
964*d83cc019SAndroid Build Coastguard Worker size_t i;
965*d83cc019SAndroid Build Coastguard Worker
966*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(binary, NULL, piglit_name, sizeof(piglit_name));
967*d83cc019SAndroid Build Coastguard Worker emptystrtotal = get_totals_object(results->totals, "");
968*d83cc019SAndroid Build Coastguard Worker roottotal = get_totals_object(results->totals, "root");
969*d83cc019SAndroid Build Coastguard Worker binarytotal = get_totals_object(results->totals, piglit_name);
970*d83cc019SAndroid Build Coastguard Worker
971*d83cc019SAndroid Build Coastguard Worker if (subtests->size == 0) {
972*d83cc019SAndroid Build Coastguard Worker test = get_or_create_json_object(results->tests, piglit_name);
973*d83cc019SAndroid Build Coastguard Worker if (!json_object_object_get_ex(test, "result", &resultobj)) {
974*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Warning: No results set for %s\n", piglit_name);
975*d83cc019SAndroid Build Coastguard Worker return;
976*d83cc019SAndroid Build Coastguard Worker }
977*d83cc019SAndroid Build Coastguard Worker result = json_object_get_string(resultobj);
978*d83cc019SAndroid Build Coastguard Worker add_result_to_totals(emptystrtotal, result);
979*d83cc019SAndroid Build Coastguard Worker add_result_to_totals(roottotal, result);
980*d83cc019SAndroid Build Coastguard Worker add_result_to_totals(binarytotal, result);
981*d83cc019SAndroid Build Coastguard Worker return;
982*d83cc019SAndroid Build Coastguard Worker }
983*d83cc019SAndroid Build Coastguard Worker
984*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < subtests->size; i++) {
985*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(binary, subtests->names[i], piglit_name, sizeof(piglit_name));
986*d83cc019SAndroid Build Coastguard Worker test = get_or_create_json_object(results->tests, piglit_name);
987*d83cc019SAndroid Build Coastguard Worker if (!json_object_object_get_ex(test, "result", &resultobj)) {
988*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Warning: No results set for %s\n", piglit_name);
989*d83cc019SAndroid Build Coastguard Worker return;
990*d83cc019SAndroid Build Coastguard Worker }
991*d83cc019SAndroid Build Coastguard Worker result = json_object_get_string(resultobj);
992*d83cc019SAndroid Build Coastguard Worker add_result_to_totals(emptystrtotal, result);
993*d83cc019SAndroid Build Coastguard Worker add_result_to_totals(roottotal, result);
994*d83cc019SAndroid Build Coastguard Worker add_result_to_totals(binarytotal, result);
995*d83cc019SAndroid Build Coastguard Worker }
996*d83cc019SAndroid Build Coastguard Worker }
997*d83cc019SAndroid Build Coastguard Worker
parse_test_directory(int dirfd,struct job_list_entry * entry,struct settings * settings,struct results * results)998*d83cc019SAndroid Build Coastguard Worker static bool parse_test_directory(int dirfd,
999*d83cc019SAndroid Build Coastguard Worker struct job_list_entry *entry,
1000*d83cc019SAndroid Build Coastguard Worker struct settings *settings,
1001*d83cc019SAndroid Build Coastguard Worker struct results *results)
1002*d83cc019SAndroid Build Coastguard Worker {
1003*d83cc019SAndroid Build Coastguard Worker int fds[_F_LAST];
1004*d83cc019SAndroid Build Coastguard Worker struct subtests subtests = {};
1005*d83cc019SAndroid Build Coastguard Worker bool status = true;
1006*d83cc019SAndroid Build Coastguard Worker
1007*d83cc019SAndroid Build Coastguard Worker if (!open_output_files(dirfd, fds, false)) {
1008*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error opening output files\n");
1009*d83cc019SAndroid Build Coastguard Worker return false;
1010*d83cc019SAndroid Build Coastguard Worker }
1011*d83cc019SAndroid Build Coastguard Worker
1012*d83cc019SAndroid Build Coastguard Worker /*
1013*d83cc019SAndroid Build Coastguard Worker * fill_from_journal fills the subtests struct and adds
1014*d83cc019SAndroid Build Coastguard Worker * timeout results where applicable.
1015*d83cc019SAndroid Build Coastguard Worker */
1016*d83cc019SAndroid Build Coastguard Worker fill_from_journal(fds[_F_JOURNAL], entry, &subtests, results);
1017*d83cc019SAndroid Build Coastguard Worker
1018*d83cc019SAndroid Build Coastguard Worker if (!fill_from_output(fds[_F_OUT], entry->binary, "out", &subtests, results->tests) ||
1019*d83cc019SAndroid Build Coastguard Worker !fill_from_output(fds[_F_ERR], entry->binary, "err", &subtests, results->tests) ||
1020*d83cc019SAndroid Build Coastguard Worker !fill_from_dmesg(fds[_F_DMESG], settings, entry->binary, &subtests, results->tests)) {
1021*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error parsing output files\n");
1022*d83cc019SAndroid Build Coastguard Worker status = false;
1023*d83cc019SAndroid Build Coastguard Worker goto parse_output_end;
1024*d83cc019SAndroid Build Coastguard Worker }
1025*d83cc019SAndroid Build Coastguard Worker
1026*d83cc019SAndroid Build Coastguard Worker override_results(entry->binary, &subtests, results->tests);
1027*d83cc019SAndroid Build Coastguard Worker add_to_totals(entry->binary, &subtests, results);
1028*d83cc019SAndroid Build Coastguard Worker
1029*d83cc019SAndroid Build Coastguard Worker parse_output_end:
1030*d83cc019SAndroid Build Coastguard Worker close_outputs(fds);
1031*d83cc019SAndroid Build Coastguard Worker free_subtests(&subtests);
1032*d83cc019SAndroid Build Coastguard Worker
1033*d83cc019SAndroid Build Coastguard Worker return status;
1034*d83cc019SAndroid Build Coastguard Worker }
1035*d83cc019SAndroid Build Coastguard Worker
try_add_notrun_results(const struct job_list_entry * entry,const struct settings * settings,struct results * results)1036*d83cc019SAndroid Build Coastguard Worker static void try_add_notrun_results(const struct job_list_entry *entry,
1037*d83cc019SAndroid Build Coastguard Worker const struct settings *settings,
1038*d83cc019SAndroid Build Coastguard Worker struct results *results)
1039*d83cc019SAndroid Build Coastguard Worker {
1040*d83cc019SAndroid Build Coastguard Worker struct subtests subtests = {};
1041*d83cc019SAndroid Build Coastguard Worker struct json_object *current_test;
1042*d83cc019SAndroid Build Coastguard Worker size_t i;
1043*d83cc019SAndroid Build Coastguard Worker
1044*d83cc019SAndroid Build Coastguard Worker if (entry->subtest_count == 0) {
1045*d83cc019SAndroid Build Coastguard Worker char piglit_name[256];
1046*d83cc019SAndroid Build Coastguard Worker
1047*d83cc019SAndroid Build Coastguard Worker /* We cannot distinguish no-subtests from run-all-subtests in multiple-mode */
1048*d83cc019SAndroid Build Coastguard Worker if (settings->multiple_mode)
1049*d83cc019SAndroid Build Coastguard Worker return;
1050*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(entry->binary, NULL, piglit_name, sizeof(piglit_name));
1051*d83cc019SAndroid Build Coastguard Worker current_test = get_or_create_json_object(results->tests, piglit_name);
1052*d83cc019SAndroid Build Coastguard Worker json_object_object_add(current_test, "out", json_object_new_string(""));
1053*d83cc019SAndroid Build Coastguard Worker json_object_object_add(current_test, "err", json_object_new_string(""));
1054*d83cc019SAndroid Build Coastguard Worker json_object_object_add(current_test, "dmesg", json_object_new_string(""));
1055*d83cc019SAndroid Build Coastguard Worker json_object_object_add(current_test, "result", json_object_new_string("notrun"));
1056*d83cc019SAndroid Build Coastguard Worker }
1057*d83cc019SAndroid Build Coastguard Worker
1058*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < entry->subtest_count; i++) {
1059*d83cc019SAndroid Build Coastguard Worker char piglit_name[256];
1060*d83cc019SAndroid Build Coastguard Worker
1061*d83cc019SAndroid Build Coastguard Worker generate_piglit_name(entry->binary, entry->subtests[i], piglit_name, sizeof(piglit_name));
1062*d83cc019SAndroid Build Coastguard Worker current_test = get_or_create_json_object(results->tests, piglit_name);
1063*d83cc019SAndroid Build Coastguard Worker json_object_object_add(current_test, "out", json_object_new_string(""));
1064*d83cc019SAndroid Build Coastguard Worker json_object_object_add(current_test, "err", json_object_new_string(""));
1065*d83cc019SAndroid Build Coastguard Worker json_object_object_add(current_test, "dmesg", json_object_new_string(""));
1066*d83cc019SAndroid Build Coastguard Worker json_object_object_add(current_test, "result", json_object_new_string("notrun"));
1067*d83cc019SAndroid Build Coastguard Worker add_subtest(&subtests, strdup(entry->subtests[i]));
1068*d83cc019SAndroid Build Coastguard Worker }
1069*d83cc019SAndroid Build Coastguard Worker
1070*d83cc019SAndroid Build Coastguard Worker add_to_totals(entry->binary, &subtests, results);
1071*d83cc019SAndroid Build Coastguard Worker free_subtests(&subtests);
1072*d83cc019SAndroid Build Coastguard Worker }
1073*d83cc019SAndroid Build Coastguard Worker
create_result_root_nodes(struct json_object * root,struct results * results)1074*d83cc019SAndroid Build Coastguard Worker static void create_result_root_nodes(struct json_object *root,
1075*d83cc019SAndroid Build Coastguard Worker struct results *results)
1076*d83cc019SAndroid Build Coastguard Worker {
1077*d83cc019SAndroid Build Coastguard Worker results->tests = json_object_new_object();
1078*d83cc019SAndroid Build Coastguard Worker json_object_object_add(root, "tests", results->tests);
1079*d83cc019SAndroid Build Coastguard Worker results->totals = json_object_new_object();
1080*d83cc019SAndroid Build Coastguard Worker json_object_object_add(root, "totals", results->totals);
1081*d83cc019SAndroid Build Coastguard Worker results->runtimes = json_object_new_object();
1082*d83cc019SAndroid Build Coastguard Worker json_object_object_add(root, "runtimes", results->runtimes);
1083*d83cc019SAndroid Build Coastguard Worker }
1084*d83cc019SAndroid Build Coastguard Worker
generate_results_json(int dirfd)1085*d83cc019SAndroid Build Coastguard Worker struct json_object *generate_results_json(int dirfd)
1086*d83cc019SAndroid Build Coastguard Worker {
1087*d83cc019SAndroid Build Coastguard Worker struct settings settings;
1088*d83cc019SAndroid Build Coastguard Worker struct job_list job_list;
1089*d83cc019SAndroid Build Coastguard Worker struct json_object *obj, *elapsed;
1090*d83cc019SAndroid Build Coastguard Worker struct results results;
1091*d83cc019SAndroid Build Coastguard Worker int testdirfd, fd;
1092*d83cc019SAndroid Build Coastguard Worker size_t i;
1093*d83cc019SAndroid Build Coastguard Worker
1094*d83cc019SAndroid Build Coastguard Worker init_settings(&settings);
1095*d83cc019SAndroid Build Coastguard Worker init_job_list(&job_list);
1096*d83cc019SAndroid Build Coastguard Worker
1097*d83cc019SAndroid Build Coastguard Worker if (!read_settings_from_dir(&settings, dirfd)) {
1098*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "resultgen: Cannot parse settings\n");
1099*d83cc019SAndroid Build Coastguard Worker return NULL;
1100*d83cc019SAndroid Build Coastguard Worker }
1101*d83cc019SAndroid Build Coastguard Worker
1102*d83cc019SAndroid Build Coastguard Worker if (!read_job_list(&job_list, dirfd)) {
1103*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "resultgen: Cannot parse job list\n");
1104*d83cc019SAndroid Build Coastguard Worker return NULL;
1105*d83cc019SAndroid Build Coastguard Worker }
1106*d83cc019SAndroid Build Coastguard Worker
1107*d83cc019SAndroid Build Coastguard Worker obj = json_object_new_object();
1108*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "__type__", json_object_new_string("TestrunResult"));
1109*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "results_version", json_object_new_int(10));
1110*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "name",
1111*d83cc019SAndroid Build Coastguard Worker settings.name ?
1112*d83cc019SAndroid Build Coastguard Worker json_object_new_string(settings.name) :
1113*d83cc019SAndroid Build Coastguard Worker json_object_new_string(""));
1114*d83cc019SAndroid Build Coastguard Worker
1115*d83cc019SAndroid Build Coastguard Worker if ((fd = openat(dirfd, "uname.txt", O_RDONLY)) >= 0) {
1116*d83cc019SAndroid Build Coastguard Worker char buf[128];
1117*d83cc019SAndroid Build Coastguard Worker ssize_t r = read(fd, buf, sizeof(buf));
1118*d83cc019SAndroid Build Coastguard Worker
1119*d83cc019SAndroid Build Coastguard Worker if (r > 0 && buf[r - 1] == '\n')
1120*d83cc019SAndroid Build Coastguard Worker r--;
1121*d83cc019SAndroid Build Coastguard Worker
1122*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "uname",
1123*d83cc019SAndroid Build Coastguard Worker json_object_new_string_len(buf, r));
1124*d83cc019SAndroid Build Coastguard Worker close(fd);
1125*d83cc019SAndroid Build Coastguard Worker }
1126*d83cc019SAndroid Build Coastguard Worker
1127*d83cc019SAndroid Build Coastguard Worker elapsed = json_object_new_object();
1128*d83cc019SAndroid Build Coastguard Worker json_object_object_add(elapsed, "__type__", json_object_new_string("TimeAttribute"));
1129*d83cc019SAndroid Build Coastguard Worker if ((fd = openat(dirfd, "starttime.txt", O_RDONLY)) >= 0) {
1130*d83cc019SAndroid Build Coastguard Worker char buf[128] = {};
1131*d83cc019SAndroid Build Coastguard Worker read(fd, buf, sizeof(buf));
1132*d83cc019SAndroid Build Coastguard Worker json_object_object_add(elapsed, "start", json_object_new_double(atof(buf)));
1133*d83cc019SAndroid Build Coastguard Worker close(fd);
1134*d83cc019SAndroid Build Coastguard Worker }
1135*d83cc019SAndroid Build Coastguard Worker if ((fd = openat(dirfd, "endtime.txt", O_RDONLY)) >= 0) {
1136*d83cc019SAndroid Build Coastguard Worker char buf[128] = {};
1137*d83cc019SAndroid Build Coastguard Worker read(fd, buf, sizeof(buf));
1138*d83cc019SAndroid Build Coastguard Worker json_object_object_add(elapsed, "end", json_object_new_double(atof(buf)));
1139*d83cc019SAndroid Build Coastguard Worker close(fd);
1140*d83cc019SAndroid Build Coastguard Worker }
1141*d83cc019SAndroid Build Coastguard Worker json_object_object_add(obj, "time_elapsed", elapsed);
1142*d83cc019SAndroid Build Coastguard Worker
1143*d83cc019SAndroid Build Coastguard Worker create_result_root_nodes(obj, &results);
1144*d83cc019SAndroid Build Coastguard Worker
1145*d83cc019SAndroid Build Coastguard Worker /*
1146*d83cc019SAndroid Build Coastguard Worker * Result fields that won't be added:
1147*d83cc019SAndroid Build Coastguard Worker *
1148*d83cc019SAndroid Build Coastguard Worker * - glxinfo
1149*d83cc019SAndroid Build Coastguard Worker * - wglinfo
1150*d83cc019SAndroid Build Coastguard Worker * - clinfo
1151*d83cc019SAndroid Build Coastguard Worker *
1152*d83cc019SAndroid Build Coastguard Worker * Result fields that are TODO:
1153*d83cc019SAndroid Build Coastguard Worker *
1154*d83cc019SAndroid Build Coastguard Worker * - lspci
1155*d83cc019SAndroid Build Coastguard Worker * - options
1156*d83cc019SAndroid Build Coastguard Worker */
1157*d83cc019SAndroid Build Coastguard Worker
1158*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < job_list.size; i++) {
1159*d83cc019SAndroid Build Coastguard Worker char name[16];
1160*d83cc019SAndroid Build Coastguard Worker
1161*d83cc019SAndroid Build Coastguard Worker snprintf(name, 16, "%zd", i);
1162*d83cc019SAndroid Build Coastguard Worker if ((testdirfd = openat(dirfd, name, O_DIRECTORY | O_RDONLY)) < 0) {
1163*d83cc019SAndroid Build Coastguard Worker try_add_notrun_results(&job_list.entries[i], &settings, &results);
1164*d83cc019SAndroid Build Coastguard Worker continue;
1165*d83cc019SAndroid Build Coastguard Worker }
1166*d83cc019SAndroid Build Coastguard Worker
1167*d83cc019SAndroid Build Coastguard Worker if (!parse_test_directory(testdirfd, &job_list.entries[i], &settings, &results)) {
1168*d83cc019SAndroid Build Coastguard Worker close(testdirfd);
1169*d83cc019SAndroid Build Coastguard Worker return NULL;
1170*d83cc019SAndroid Build Coastguard Worker }
1171*d83cc019SAndroid Build Coastguard Worker close(testdirfd);
1172*d83cc019SAndroid Build Coastguard Worker }
1173*d83cc019SAndroid Build Coastguard Worker
1174*d83cc019SAndroid Build Coastguard Worker if ((fd = openat(dirfd, "aborted.txt", O_RDONLY)) >= 0) {
1175*d83cc019SAndroid Build Coastguard Worker char buf[4096];
1176*d83cc019SAndroid Build Coastguard Worker char piglit_name[] = "igt@runner@aborted";
1177*d83cc019SAndroid Build Coastguard Worker struct subtests abortsub = {};
1178*d83cc019SAndroid Build Coastguard Worker struct json_object *aborttest = get_or_create_json_object(results.tests, piglit_name);
1179*d83cc019SAndroid Build Coastguard Worker ssize_t s;
1180*d83cc019SAndroid Build Coastguard Worker
1181*d83cc019SAndroid Build Coastguard Worker add_subtest(&abortsub, strdup("aborted"));
1182*d83cc019SAndroid Build Coastguard Worker
1183*d83cc019SAndroid Build Coastguard Worker s = read(fd, buf, sizeof(buf));
1184*d83cc019SAndroid Build Coastguard Worker
1185*d83cc019SAndroid Build Coastguard Worker json_object_object_add(aborttest, "out",
1186*d83cc019SAndroid Build Coastguard Worker json_object_new_string_len(buf, s));
1187*d83cc019SAndroid Build Coastguard Worker json_object_object_add(aborttest, "err",
1188*d83cc019SAndroid Build Coastguard Worker json_object_new_string(""));
1189*d83cc019SAndroid Build Coastguard Worker json_object_object_add(aborttest, "dmesg",
1190*d83cc019SAndroid Build Coastguard Worker json_object_new_string(""));
1191*d83cc019SAndroid Build Coastguard Worker json_object_object_add(aborttest, "result",
1192*d83cc019SAndroid Build Coastguard Worker json_object_new_string("fail"));
1193*d83cc019SAndroid Build Coastguard Worker
1194*d83cc019SAndroid Build Coastguard Worker add_to_totals("runner", &abortsub, &results);
1195*d83cc019SAndroid Build Coastguard Worker
1196*d83cc019SAndroid Build Coastguard Worker free_subtests(&abortsub);
1197*d83cc019SAndroid Build Coastguard Worker }
1198*d83cc019SAndroid Build Coastguard Worker
1199*d83cc019SAndroid Build Coastguard Worker free_settings(&settings);
1200*d83cc019SAndroid Build Coastguard Worker free_job_list(&job_list);
1201*d83cc019SAndroid Build Coastguard Worker
1202*d83cc019SAndroid Build Coastguard Worker return obj;
1203*d83cc019SAndroid Build Coastguard Worker }
1204*d83cc019SAndroid Build Coastguard Worker
generate_results(int dirfd)1205*d83cc019SAndroid Build Coastguard Worker bool generate_results(int dirfd)
1206*d83cc019SAndroid Build Coastguard Worker {
1207*d83cc019SAndroid Build Coastguard Worker struct json_object *obj = generate_results_json(dirfd);
1208*d83cc019SAndroid Build Coastguard Worker const char *json_string;
1209*d83cc019SAndroid Build Coastguard Worker int resultsfd;
1210*d83cc019SAndroid Build Coastguard Worker
1211*d83cc019SAndroid Build Coastguard Worker if (obj == NULL)
1212*d83cc019SAndroid Build Coastguard Worker return false;
1213*d83cc019SAndroid Build Coastguard Worker
1214*d83cc019SAndroid Build Coastguard Worker /* TODO: settings.overwrite */
1215*d83cc019SAndroid Build Coastguard Worker if ((resultsfd = openat(dirfd, "results.json", O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
1216*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "resultgen: Cannot create results file\n");
1217*d83cc019SAndroid Build Coastguard Worker return false;
1218*d83cc019SAndroid Build Coastguard Worker }
1219*d83cc019SAndroid Build Coastguard Worker
1220*d83cc019SAndroid Build Coastguard Worker json_string = json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PRETTY);
1221*d83cc019SAndroid Build Coastguard Worker write(resultsfd, json_string, strlen(json_string));
1222*d83cc019SAndroid Build Coastguard Worker close(resultsfd);
1223*d83cc019SAndroid Build Coastguard Worker return true;
1224*d83cc019SAndroid Build Coastguard Worker }
1225*d83cc019SAndroid Build Coastguard Worker
generate_results_path(char * resultspath)1226*d83cc019SAndroid Build Coastguard Worker bool generate_results_path(char *resultspath)
1227*d83cc019SAndroid Build Coastguard Worker {
1228*d83cc019SAndroid Build Coastguard Worker int dirfd = open(resultspath, O_DIRECTORY | O_RDONLY);
1229*d83cc019SAndroid Build Coastguard Worker
1230*d83cc019SAndroid Build Coastguard Worker if (dirfd < 0)
1231*d83cc019SAndroid Build Coastguard Worker return false;
1232*d83cc019SAndroid Build Coastguard Worker
1233*d83cc019SAndroid Build Coastguard Worker return generate_results(dirfd);
1234*d83cc019SAndroid Build Coastguard Worker }
1235