xref: /aosp_15_r20/external/igt-gpu-tools/runner/job_list.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker #include <ctype.h>
2*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
3*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
4*d83cc019SAndroid Build Coastguard Worker #include <linux/limits.h>
5*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
6*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
7*d83cc019SAndroid Build Coastguard Worker #include <string.h>
8*d83cc019SAndroid Build Coastguard Worker #include <sys/stat.h>
9*d83cc019SAndroid Build Coastguard Worker #include <sys/types.h>
10*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
11*d83cc019SAndroid Build Coastguard Worker 
12*d83cc019SAndroid Build Coastguard Worker #include "job_list.h"
13*d83cc019SAndroid Build Coastguard Worker #include "igt_core.h"
14*d83cc019SAndroid Build Coastguard Worker 
matches_any(const char * str,struct regex_list * list)15*d83cc019SAndroid Build Coastguard Worker static bool matches_any(const char *str, struct regex_list *list)
16*d83cc019SAndroid Build Coastguard Worker {
17*d83cc019SAndroid Build Coastguard Worker 	size_t i;
18*d83cc019SAndroid Build Coastguard Worker 
19*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < list->size; i++) {
20*d83cc019SAndroid Build Coastguard Worker 		if (g_regex_match(list->regexes[i], str, 0, NULL))
21*d83cc019SAndroid Build Coastguard Worker 			return true;
22*d83cc019SAndroid Build Coastguard Worker 	}
23*d83cc019SAndroid Build Coastguard Worker 
24*d83cc019SAndroid Build Coastguard Worker 	return false;
25*d83cc019SAndroid Build Coastguard Worker }
26*d83cc019SAndroid Build Coastguard Worker 
add_job_list_entry(struct job_list * job_list,char * binary,char ** subtests,size_t subtest_count)27*d83cc019SAndroid Build Coastguard Worker static void add_job_list_entry(struct job_list *job_list,
28*d83cc019SAndroid Build Coastguard Worker 			       char *binary,
29*d83cc019SAndroid Build Coastguard Worker 			       char **subtests,
30*d83cc019SAndroid Build Coastguard Worker 			       size_t subtest_count)
31*d83cc019SAndroid Build Coastguard Worker {
32*d83cc019SAndroid Build Coastguard Worker 	struct job_list_entry *entry;
33*d83cc019SAndroid Build Coastguard Worker 
34*d83cc019SAndroid Build Coastguard Worker 	job_list->size++;
35*d83cc019SAndroid Build Coastguard Worker 	job_list->entries = realloc(job_list->entries, job_list->size * sizeof(*job_list->entries));
36*d83cc019SAndroid Build Coastguard Worker 	entry = &job_list->entries[job_list->size - 1];
37*d83cc019SAndroid Build Coastguard Worker 
38*d83cc019SAndroid Build Coastguard Worker 	entry->binary = binary;
39*d83cc019SAndroid Build Coastguard Worker 	entry->subtests = subtests;
40*d83cc019SAndroid Build Coastguard Worker 	entry->subtest_count = subtest_count;
41*d83cc019SAndroid Build Coastguard Worker }
42*d83cc019SAndroid Build Coastguard Worker 
add_subtests(struct job_list * job_list,struct settings * settings,char * binary,struct regex_list * include,struct regex_list * exclude)43*d83cc019SAndroid Build Coastguard Worker static void add_subtests(struct job_list *job_list, struct settings *settings,
44*d83cc019SAndroid Build Coastguard Worker 			 char *binary,
45*d83cc019SAndroid Build Coastguard Worker 			 struct regex_list *include, struct regex_list *exclude)
46*d83cc019SAndroid Build Coastguard Worker {
47*d83cc019SAndroid Build Coastguard Worker 	FILE *p;
48*d83cc019SAndroid Build Coastguard Worker 	char cmd[256] = {};
49*d83cc019SAndroid Build Coastguard Worker 	char *subtestname;
50*d83cc019SAndroid Build Coastguard Worker 	char **subtests = NULL;
51*d83cc019SAndroid Build Coastguard Worker 	size_t num_subtests = 0;
52*d83cc019SAndroid Build Coastguard Worker 	int s;
53*d83cc019SAndroid Build Coastguard Worker 
54*d83cc019SAndroid Build Coastguard Worker 	s = snprintf(cmd, sizeof(cmd), "%s/%s --list-subtests",
55*d83cc019SAndroid Build Coastguard Worker 		     settings->test_root, binary);
56*d83cc019SAndroid Build Coastguard Worker 	if (s < 0) {
57*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "Failure generating command string, this shouldn't happen.\n");
58*d83cc019SAndroid Build Coastguard Worker 		return;
59*d83cc019SAndroid Build Coastguard Worker 	}
60*d83cc019SAndroid Build Coastguard Worker 
61*d83cc019SAndroid Build Coastguard Worker 	if (s >= sizeof(cmd)) {
62*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "Path to binary too long, ignoring: %s/%s\n",
63*d83cc019SAndroid Build Coastguard Worker 			settings->test_root, binary);
64*d83cc019SAndroid Build Coastguard Worker 		return;
65*d83cc019SAndroid Build Coastguard Worker 	}
66*d83cc019SAndroid Build Coastguard Worker 
67*d83cc019SAndroid Build Coastguard Worker 	p = popen(cmd, "r");
68*d83cc019SAndroid Build Coastguard Worker 	if (!p) {
69*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "popen failed when executing %s: %s\n",
70*d83cc019SAndroid Build Coastguard Worker 			cmd,
71*d83cc019SAndroid Build Coastguard Worker 			strerror(errno));
72*d83cc019SAndroid Build Coastguard Worker 		return;
73*d83cc019SAndroid Build Coastguard Worker 	}
74*d83cc019SAndroid Build Coastguard Worker 
75*d83cc019SAndroid Build Coastguard Worker 	while (fscanf(p, "%ms", &subtestname) == 1) {
76*d83cc019SAndroid Build Coastguard Worker 		char piglitname[256];
77*d83cc019SAndroid Build Coastguard Worker 
78*d83cc019SAndroid Build Coastguard Worker 		generate_piglit_name(binary, subtestname, piglitname, sizeof(piglitname));
79*d83cc019SAndroid Build Coastguard Worker 
80*d83cc019SAndroid Build Coastguard Worker 		if (exclude && exclude->size && matches_any(piglitname, exclude)) {
81*d83cc019SAndroid Build Coastguard Worker 			free(subtestname);
82*d83cc019SAndroid Build Coastguard Worker 			continue;
83*d83cc019SAndroid Build Coastguard Worker 		}
84*d83cc019SAndroid Build Coastguard Worker 
85*d83cc019SAndroid Build Coastguard Worker 		if (include && include->size && !matches_any(piglitname, include)) {
86*d83cc019SAndroid Build Coastguard Worker 			free(subtestname);
87*d83cc019SAndroid Build Coastguard Worker 			continue;
88*d83cc019SAndroid Build Coastguard Worker 		}
89*d83cc019SAndroid Build Coastguard Worker 
90*d83cc019SAndroid Build Coastguard Worker 		if (settings->multiple_mode) {
91*d83cc019SAndroid Build Coastguard Worker 			num_subtests++;
92*d83cc019SAndroid Build Coastguard Worker 			subtests = realloc(subtests, num_subtests * sizeof(*subtests));
93*d83cc019SAndroid Build Coastguard Worker 			subtests[num_subtests - 1] = strdup(subtestname);
94*d83cc019SAndroid Build Coastguard Worker 		} else {
95*d83cc019SAndroid Build Coastguard Worker 			subtests = malloc(sizeof(*subtests));
96*d83cc019SAndroid Build Coastguard Worker 			*subtests = strdup(subtestname);
97*d83cc019SAndroid Build Coastguard Worker 			add_job_list_entry(job_list, strdup(binary), subtests, 1);
98*d83cc019SAndroid Build Coastguard Worker 			subtests = NULL;
99*d83cc019SAndroid Build Coastguard Worker 		}
100*d83cc019SAndroid Build Coastguard Worker 
101*d83cc019SAndroid Build Coastguard Worker 		free(subtestname);
102*d83cc019SAndroid Build Coastguard Worker 	}
103*d83cc019SAndroid Build Coastguard Worker 
104*d83cc019SAndroid Build Coastguard Worker 	if (num_subtests)
105*d83cc019SAndroid Build Coastguard Worker 		add_job_list_entry(job_list, strdup(binary), subtests, num_subtests);
106*d83cc019SAndroid Build Coastguard Worker 
107*d83cc019SAndroid Build Coastguard Worker 	s = pclose(p);
108*d83cc019SAndroid Build Coastguard Worker 	if (s == 0) {
109*d83cc019SAndroid Build Coastguard Worker 		return;
110*d83cc019SAndroid Build Coastguard Worker 	} else if (s == -1) {
111*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "popen error when executing %s: %s\n", binary, strerror(errno));
112*d83cc019SAndroid Build Coastguard Worker 	} else if (WIFEXITED(s)) {
113*d83cc019SAndroid Build Coastguard Worker 		if (WEXITSTATUS(s) == IGT_EXIT_INVALID) {
114*d83cc019SAndroid Build Coastguard Worker 			char piglitname[256];
115*d83cc019SAndroid Build Coastguard Worker 
116*d83cc019SAndroid Build Coastguard Worker 			generate_piglit_name(binary, NULL,
117*d83cc019SAndroid Build Coastguard Worker 					     piglitname, sizeof(piglitname));
118*d83cc019SAndroid Build Coastguard Worker 			/* No subtests on this one */
119*d83cc019SAndroid Build Coastguard Worker 			if (exclude && exclude->size &&
120*d83cc019SAndroid Build Coastguard Worker 			    matches_any(piglitname, exclude)) {
121*d83cc019SAndroid Build Coastguard Worker 				return;
122*d83cc019SAndroid Build Coastguard Worker 			}
123*d83cc019SAndroid Build Coastguard Worker 			if (!include || !include->size ||
124*d83cc019SAndroid Build Coastguard Worker 			    matches_any(piglitname, include)) {
125*d83cc019SAndroid Build Coastguard Worker 				add_job_list_entry(job_list, strdup(binary), NULL, 0);
126*d83cc019SAndroid Build Coastguard Worker 				return;
127*d83cc019SAndroid Build Coastguard Worker 			}
128*d83cc019SAndroid Build Coastguard Worker 		}
129*d83cc019SAndroid Build Coastguard Worker 	} else {
130*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "Test binary %s died unexpectedly\n", binary);
131*d83cc019SAndroid Build Coastguard Worker 	}
132*d83cc019SAndroid Build Coastguard Worker }
133*d83cc019SAndroid Build Coastguard Worker 
filtered_job_list(struct job_list * job_list,struct settings * settings,int fd)134*d83cc019SAndroid Build Coastguard Worker static bool filtered_job_list(struct job_list *job_list,
135*d83cc019SAndroid Build Coastguard Worker 			      struct settings *settings,
136*d83cc019SAndroid Build Coastguard Worker 			      int fd)
137*d83cc019SAndroid Build Coastguard Worker {
138*d83cc019SAndroid Build Coastguard Worker 	FILE *f;
139*d83cc019SAndroid Build Coastguard Worker 	char buf[128];
140*d83cc019SAndroid Build Coastguard Worker 	bool ok;
141*d83cc019SAndroid Build Coastguard Worker 
142*d83cc019SAndroid Build Coastguard Worker 	if (job_list->entries != NULL) {
143*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "Caller didn't clear the job list, this shouldn't happen\n");
144*d83cc019SAndroid Build Coastguard Worker 		exit(1);
145*d83cc019SAndroid Build Coastguard Worker 	}
146*d83cc019SAndroid Build Coastguard Worker 
147*d83cc019SAndroid Build Coastguard Worker 	f = fdopen(fd, "r");
148*d83cc019SAndroid Build Coastguard Worker 
149*d83cc019SAndroid Build Coastguard Worker 	while (fscanf(f, "%127s", buf) == 1) {
150*d83cc019SAndroid Build Coastguard Worker 		if (!strcmp(buf, "TESTLIST") || !(strcmp(buf, "END")))
151*d83cc019SAndroid Build Coastguard Worker 			continue;
152*d83cc019SAndroid Build Coastguard Worker 
153*d83cc019SAndroid Build Coastguard Worker 		/*
154*d83cc019SAndroid Build Coastguard Worker 		 * If the binary name matches exclude filters, no
155*d83cc019SAndroid Build Coastguard Worker 		 * subtests are added.
156*d83cc019SAndroid Build Coastguard Worker 		 */
157*d83cc019SAndroid Build Coastguard Worker 		if (settings->exclude_regexes.size && matches_any(buf, &settings->exclude_regexes))
158*d83cc019SAndroid Build Coastguard Worker 			continue;
159*d83cc019SAndroid Build Coastguard Worker 
160*d83cc019SAndroid Build Coastguard Worker 		/*
161*d83cc019SAndroid Build Coastguard Worker 		 * If the binary name matches include filters (or include filters not present),
162*d83cc019SAndroid Build Coastguard Worker 		 * all subtests except those matching exclude filters are added.
163*d83cc019SAndroid Build Coastguard Worker 		 */
164*d83cc019SAndroid Build Coastguard Worker 		if (!settings->include_regexes.size || matches_any(buf, &settings->include_regexes)) {
165*d83cc019SAndroid Build Coastguard Worker 			if (settings->multiple_mode && !settings->exclude_regexes.size)
166*d83cc019SAndroid Build Coastguard Worker 				/*
167*d83cc019SAndroid Build Coastguard Worker 				 * Optimization; we know that all
168*d83cc019SAndroid Build Coastguard Worker 				 * subtests will be included, so we
169*d83cc019SAndroid Build Coastguard Worker 				 * get to omit executing
170*d83cc019SAndroid Build Coastguard Worker 				 * --list-subtests.
171*d83cc019SAndroid Build Coastguard Worker 				 */
172*d83cc019SAndroid Build Coastguard Worker 				add_job_list_entry(job_list, strdup(buf), NULL, 0);
173*d83cc019SAndroid Build Coastguard Worker 			else
174*d83cc019SAndroid Build Coastguard Worker 				add_subtests(job_list, settings, buf,
175*d83cc019SAndroid Build Coastguard Worker 					     NULL, &settings->exclude_regexes);
176*d83cc019SAndroid Build Coastguard Worker 			continue;
177*d83cc019SAndroid Build Coastguard Worker 		}
178*d83cc019SAndroid Build Coastguard Worker 
179*d83cc019SAndroid Build Coastguard Worker 		/*
180*d83cc019SAndroid Build Coastguard Worker 		 * Binary name doesn't match exclude or include filters.
181*d83cc019SAndroid Build Coastguard Worker 		 */
182*d83cc019SAndroid Build Coastguard Worker 		add_subtests(job_list, settings, buf,
183*d83cc019SAndroid Build Coastguard Worker 			     &settings->include_regexes,
184*d83cc019SAndroid Build Coastguard Worker 			     &settings->exclude_regexes);
185*d83cc019SAndroid Build Coastguard Worker 	}
186*d83cc019SAndroid Build Coastguard Worker 
187*d83cc019SAndroid Build Coastguard Worker 	ok = job_list->size != 0;
188*d83cc019SAndroid Build Coastguard Worker 	if (!ok)
189*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "Filter didn't match any job name\n");
190*d83cc019SAndroid Build Coastguard Worker 
191*d83cc019SAndroid Build Coastguard Worker 	return ok;
192*d83cc019SAndroid Build Coastguard Worker }
193*d83cc019SAndroid Build Coastguard Worker 
job_list_from_test_list(struct job_list * job_list,struct settings * settings)194*d83cc019SAndroid Build Coastguard Worker static bool job_list_from_test_list(struct job_list *job_list,
195*d83cc019SAndroid Build Coastguard Worker 				    struct settings *settings)
196*d83cc019SAndroid Build Coastguard Worker {
197*d83cc019SAndroid Build Coastguard Worker 	FILE *f;
198*d83cc019SAndroid Build Coastguard Worker 	char *line = NULL;
199*d83cc019SAndroid Build Coastguard Worker 	size_t line_len = 0;
200*d83cc019SAndroid Build Coastguard Worker 	struct job_list_entry entry = {};
201*d83cc019SAndroid Build Coastguard Worker 	bool any = false;
202*d83cc019SAndroid Build Coastguard Worker 
203*d83cc019SAndroid Build Coastguard Worker 	if ((f = fopen(settings->test_list, "r")) == NULL) {
204*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "Cannot open test list file %s\n", settings->test_list);
205*d83cc019SAndroid Build Coastguard Worker 		return false;
206*d83cc019SAndroid Build Coastguard Worker 	}
207*d83cc019SAndroid Build Coastguard Worker 
208*d83cc019SAndroid Build Coastguard Worker 	while (1) {
209*d83cc019SAndroid Build Coastguard Worker 		char *binary;
210*d83cc019SAndroid Build Coastguard Worker 		char *delim;
211*d83cc019SAndroid Build Coastguard Worker 
212*d83cc019SAndroid Build Coastguard Worker 		if (getline(&line, &line_len, f) == -1) {
213*d83cc019SAndroid Build Coastguard Worker 			if (errno == EINTR)
214*d83cc019SAndroid Build Coastguard Worker 				continue;
215*d83cc019SAndroid Build Coastguard Worker 			else
216*d83cc019SAndroid Build Coastguard Worker 				break;
217*d83cc019SAndroid Build Coastguard Worker 		}
218*d83cc019SAndroid Build Coastguard Worker 
219*d83cc019SAndroid Build Coastguard Worker 		/* # starts a comment */
220*d83cc019SAndroid Build Coastguard Worker 		if ((delim = strchr(line, '#')) != NULL)
221*d83cc019SAndroid Build Coastguard Worker 			*delim = '\0';
222*d83cc019SAndroid Build Coastguard Worker 
223*d83cc019SAndroid Build Coastguard Worker 		if (settings->exclude_regexes.size && matches_any(line, &settings->exclude_regexes))
224*d83cc019SAndroid Build Coastguard Worker 			continue;
225*d83cc019SAndroid Build Coastguard Worker 
226*d83cc019SAndroid Build Coastguard Worker 		if (settings->include_regexes.size && !matches_any(line, &settings->include_regexes))
227*d83cc019SAndroid Build Coastguard Worker 			continue;
228*d83cc019SAndroid Build Coastguard Worker 
229*d83cc019SAndroid Build Coastguard Worker 		if (sscanf(line, "igt@%ms", &binary) == 1) {
230*d83cc019SAndroid Build Coastguard Worker 			if ((delim = strchr(binary, '@')) != NULL)
231*d83cc019SAndroid Build Coastguard Worker 				*delim++ = '\0';
232*d83cc019SAndroid Build Coastguard Worker 
233*d83cc019SAndroid Build Coastguard Worker 			if (!settings->multiple_mode) {
234*d83cc019SAndroid Build Coastguard Worker 				char **subtests = NULL;
235*d83cc019SAndroid Build Coastguard Worker 				if (delim) {
236*d83cc019SAndroid Build Coastguard Worker 					subtests = malloc(sizeof(char*));
237*d83cc019SAndroid Build Coastguard Worker 					subtests[0] = strdup(delim);
238*d83cc019SAndroid Build Coastguard Worker 				}
239*d83cc019SAndroid Build Coastguard Worker 				add_job_list_entry(job_list, strdup(binary),
240*d83cc019SAndroid Build Coastguard Worker 						   subtests, (size_t)(subtests != NULL));
241*d83cc019SAndroid Build Coastguard Worker 				any = true;
242*d83cc019SAndroid Build Coastguard Worker 				free(binary);
243*d83cc019SAndroid Build Coastguard Worker 				binary = NULL;
244*d83cc019SAndroid Build Coastguard Worker 				continue;
245*d83cc019SAndroid Build Coastguard Worker 			}
246*d83cc019SAndroid Build Coastguard Worker 
247*d83cc019SAndroid Build Coastguard Worker 			/*
248*d83cc019SAndroid Build Coastguard Worker 			 * If the currently built entry has the same
249*d83cc019SAndroid Build Coastguard Worker 			 * binary, add a subtest. Otherwise submit
250*d83cc019SAndroid Build Coastguard Worker 			 * what's already built and start a new one.
251*d83cc019SAndroid Build Coastguard Worker 			 */
252*d83cc019SAndroid Build Coastguard Worker 			if (entry.binary && !strcmp(entry.binary, binary)) {
253*d83cc019SAndroid Build Coastguard Worker 				if (!delim) {
254*d83cc019SAndroid Build Coastguard Worker 					/* ... except we didn't get a subtest */
255*d83cc019SAndroid Build Coastguard Worker 					fprintf(stderr,
256*d83cc019SAndroid Build Coastguard Worker 						"Error: Unexpected test without subtests "
257*d83cc019SAndroid Build Coastguard Worker 						"after same test had subtests\n");
258*d83cc019SAndroid Build Coastguard Worker 					free(binary);
259*d83cc019SAndroid Build Coastguard Worker 					fclose(f);
260*d83cc019SAndroid Build Coastguard Worker 					return false;
261*d83cc019SAndroid Build Coastguard Worker 				}
262*d83cc019SAndroid Build Coastguard Worker 				entry.subtest_count++;
263*d83cc019SAndroid Build Coastguard Worker 				entry.subtests = realloc(entry.subtests,
264*d83cc019SAndroid Build Coastguard Worker 							 entry.subtest_count *
265*d83cc019SAndroid Build Coastguard Worker 							 sizeof(*entry.subtests));
266*d83cc019SAndroid Build Coastguard Worker 				entry.subtests[entry.subtest_count - 1] = strdup(delim);
267*d83cc019SAndroid Build Coastguard Worker 				free(binary);
268*d83cc019SAndroid Build Coastguard Worker 				binary = NULL;
269*d83cc019SAndroid Build Coastguard Worker 				continue;
270*d83cc019SAndroid Build Coastguard Worker 			}
271*d83cc019SAndroid Build Coastguard Worker 
272*d83cc019SAndroid Build Coastguard Worker 			if (entry.binary) {
273*d83cc019SAndroid Build Coastguard Worker 				add_job_list_entry(job_list, entry.binary, entry.subtests, entry.subtest_count);
274*d83cc019SAndroid Build Coastguard Worker 				any = true;
275*d83cc019SAndroid Build Coastguard Worker 			}
276*d83cc019SAndroid Build Coastguard Worker 
277*d83cc019SAndroid Build Coastguard Worker 			memset(&entry, 0, sizeof(entry));
278*d83cc019SAndroid Build Coastguard Worker 			entry.binary = strdup(binary);
279*d83cc019SAndroid Build Coastguard Worker 			if (delim) {
280*d83cc019SAndroid Build Coastguard Worker 				entry.subtests = malloc(sizeof(*entry.subtests));
281*d83cc019SAndroid Build Coastguard Worker 				entry.subtests[0] = strdup(delim);
282*d83cc019SAndroid Build Coastguard Worker 				entry.subtest_count = 1;
283*d83cc019SAndroid Build Coastguard Worker 			}
284*d83cc019SAndroid Build Coastguard Worker 
285*d83cc019SAndroid Build Coastguard Worker 			free(binary);
286*d83cc019SAndroid Build Coastguard Worker 			binary = NULL;
287*d83cc019SAndroid Build Coastguard Worker 		}
288*d83cc019SAndroid Build Coastguard Worker 	}
289*d83cc019SAndroid Build Coastguard Worker 
290*d83cc019SAndroid Build Coastguard Worker 	if (entry.binary) {
291*d83cc019SAndroid Build Coastguard Worker 		add_job_list_entry(job_list, entry.binary, entry.subtests, entry.subtest_count);
292*d83cc019SAndroid Build Coastguard Worker 		any = true;
293*d83cc019SAndroid Build Coastguard Worker 	}
294*d83cc019SAndroid Build Coastguard Worker 
295*d83cc019SAndroid Build Coastguard Worker 	free(line);
296*d83cc019SAndroid Build Coastguard Worker 	fclose(f);
297*d83cc019SAndroid Build Coastguard Worker 	return any;
298*d83cc019SAndroid Build Coastguard Worker }
299*d83cc019SAndroid Build Coastguard Worker 
list_all_tests(struct job_list * lst)300*d83cc019SAndroid Build Coastguard Worker void list_all_tests(struct job_list *lst)
301*d83cc019SAndroid Build Coastguard Worker {
302*d83cc019SAndroid Build Coastguard Worker 	char piglit_name[256];
303*d83cc019SAndroid Build Coastguard Worker 
304*d83cc019SAndroid Build Coastguard Worker 	for (size_t test_idx = 0; test_idx < lst->size; ++test_idx) {
305*d83cc019SAndroid Build Coastguard Worker 		struct job_list_entry *current_entry = lst->entries + test_idx;
306*d83cc019SAndroid Build Coastguard Worker 		char *binary = current_entry->binary;
307*d83cc019SAndroid Build Coastguard Worker 
308*d83cc019SAndroid Build Coastguard Worker 		if (current_entry->subtest_count == 0) {
309*d83cc019SAndroid Build Coastguard Worker 			generate_piglit_name(binary, NULL,
310*d83cc019SAndroid Build Coastguard Worker 					     piglit_name, sizeof(piglit_name));
311*d83cc019SAndroid Build Coastguard Worker 			printf("%s\n", piglit_name);
312*d83cc019SAndroid Build Coastguard Worker 			continue;
313*d83cc019SAndroid Build Coastguard Worker 		}
314*d83cc019SAndroid Build Coastguard Worker 		for (size_t subtest_idx = 0;
315*d83cc019SAndroid Build Coastguard Worker 		    subtest_idx < current_entry->subtest_count;
316*d83cc019SAndroid Build Coastguard Worker 		    ++subtest_idx) {
317*d83cc019SAndroid Build Coastguard Worker 			generate_piglit_name(binary, current_entry->subtests[subtest_idx],
318*d83cc019SAndroid Build Coastguard Worker 					     piglit_name, sizeof(piglit_name));
319*d83cc019SAndroid Build Coastguard Worker 			printf("%s\n", piglit_name);
320*d83cc019SAndroid Build Coastguard Worker 		}
321*d83cc019SAndroid Build Coastguard Worker 	}
322*d83cc019SAndroid Build Coastguard Worker }
323*d83cc019SAndroid Build Coastguard Worker 
lowercase(const char * str)324*d83cc019SAndroid Build Coastguard Worker static char *lowercase(const char *str)
325*d83cc019SAndroid Build Coastguard Worker {
326*d83cc019SAndroid Build Coastguard Worker 	char *ret = malloc(strlen(str) + 1);
327*d83cc019SAndroid Build Coastguard Worker 	char *q = ret;
328*d83cc019SAndroid Build Coastguard Worker 
329*d83cc019SAndroid Build Coastguard Worker 	while (*str) {
330*d83cc019SAndroid Build Coastguard Worker 		if (isspace(*str))
331*d83cc019SAndroid Build Coastguard Worker 			break;
332*d83cc019SAndroid Build Coastguard Worker 
333*d83cc019SAndroid Build Coastguard Worker 		*q++ = tolower(*str++);
334*d83cc019SAndroid Build Coastguard Worker 	}
335*d83cc019SAndroid Build Coastguard Worker 	*q = '\0';
336*d83cc019SAndroid Build Coastguard Worker 
337*d83cc019SAndroid Build Coastguard Worker 	return ret;
338*d83cc019SAndroid Build Coastguard Worker }
339*d83cc019SAndroid Build Coastguard Worker 
generate_piglit_name(const char * binary,const char * subtest,char * namebuf,size_t namebuf_size)340*d83cc019SAndroid Build Coastguard Worker void generate_piglit_name(const char *binary, const char *subtest,
341*d83cc019SAndroid Build Coastguard Worker 			  char *namebuf, size_t namebuf_size)
342*d83cc019SAndroid Build Coastguard Worker {
343*d83cc019SAndroid Build Coastguard Worker 	char *lc_binary = lowercase(binary);
344*d83cc019SAndroid Build Coastguard Worker 	char *lc_subtest = NULL;
345*d83cc019SAndroid Build Coastguard Worker 
346*d83cc019SAndroid Build Coastguard Worker 	if (!subtest) {
347*d83cc019SAndroid Build Coastguard Worker 		snprintf(namebuf, namebuf_size, "igt@%s", lc_binary);
348*d83cc019SAndroid Build Coastguard Worker 		free(lc_binary);
349*d83cc019SAndroid Build Coastguard Worker 		return;
350*d83cc019SAndroid Build Coastguard Worker 	}
351*d83cc019SAndroid Build Coastguard Worker 
352*d83cc019SAndroid Build Coastguard Worker 	lc_subtest = lowercase(subtest);
353*d83cc019SAndroid Build Coastguard Worker 
354*d83cc019SAndroid Build Coastguard Worker 	snprintf(namebuf, namebuf_size, "igt@%s@%s", lc_binary, lc_subtest);
355*d83cc019SAndroid Build Coastguard Worker 
356*d83cc019SAndroid Build Coastguard Worker 	free(lc_binary);
357*d83cc019SAndroid Build Coastguard Worker 	free(lc_subtest);
358*d83cc019SAndroid Build Coastguard Worker }
359*d83cc019SAndroid Build Coastguard Worker 
init_job_list(struct job_list * job_list)360*d83cc019SAndroid Build Coastguard Worker void init_job_list(struct job_list *job_list)
361*d83cc019SAndroid Build Coastguard Worker {
362*d83cc019SAndroid Build Coastguard Worker 	memset(job_list, 0, sizeof(*job_list));
363*d83cc019SAndroid Build Coastguard Worker }
364*d83cc019SAndroid Build Coastguard Worker 
free_job_list(struct job_list * job_list)365*d83cc019SAndroid Build Coastguard Worker void free_job_list(struct job_list *job_list)
366*d83cc019SAndroid Build Coastguard Worker {
367*d83cc019SAndroid Build Coastguard Worker 	int i, k;
368*d83cc019SAndroid Build Coastguard Worker 
369*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < job_list->size; i++) {
370*d83cc019SAndroid Build Coastguard Worker 		struct job_list_entry *entry = &job_list->entries[i];
371*d83cc019SAndroid Build Coastguard Worker 
372*d83cc019SAndroid Build Coastguard Worker 		free(entry->binary);
373*d83cc019SAndroid Build Coastguard Worker 		for (k = 0; k < entry->subtest_count; k++) {
374*d83cc019SAndroid Build Coastguard Worker 			free(entry->subtests[k]);
375*d83cc019SAndroid Build Coastguard Worker 		}
376*d83cc019SAndroid Build Coastguard Worker 		free(entry->subtests);
377*d83cc019SAndroid Build Coastguard Worker 	}
378*d83cc019SAndroid Build Coastguard Worker 	free(job_list->entries);
379*d83cc019SAndroid Build Coastguard Worker 	init_job_list(job_list);
380*d83cc019SAndroid Build Coastguard Worker }
381*d83cc019SAndroid Build Coastguard Worker 
create_job_list(struct job_list * job_list,struct settings * settings)382*d83cc019SAndroid Build Coastguard Worker bool create_job_list(struct job_list *job_list,
383*d83cc019SAndroid Build Coastguard Worker 		     struct settings *settings)
384*d83cc019SAndroid Build Coastguard Worker {
385*d83cc019SAndroid Build Coastguard Worker 	int dirfd, fd;
386*d83cc019SAndroid Build Coastguard Worker 	bool result;
387*d83cc019SAndroid Build Coastguard Worker 
388*d83cc019SAndroid Build Coastguard Worker 	if (!settings->test_root) {
389*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "No test root set; this shouldn't happen\n");
390*d83cc019SAndroid Build Coastguard Worker 		return false;
391*d83cc019SAndroid Build Coastguard Worker 	}
392*d83cc019SAndroid Build Coastguard Worker 
393*d83cc019SAndroid Build Coastguard Worker 	free_job_list(job_list);
394*d83cc019SAndroid Build Coastguard Worker 
395*d83cc019SAndroid Build Coastguard Worker 	dirfd = open(settings->test_root, O_DIRECTORY | O_RDONLY);
396*d83cc019SAndroid Build Coastguard Worker 	if (dirfd < 0) {
397*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "Test directory %s cannot be opened\n", settings->test_root);
398*d83cc019SAndroid Build Coastguard Worker 		return false;
399*d83cc019SAndroid Build Coastguard Worker 	}
400*d83cc019SAndroid Build Coastguard Worker 
401*d83cc019SAndroid Build Coastguard Worker 	fd = openat(dirfd, "test-list.txt", O_RDONLY);
402*d83cc019SAndroid Build Coastguard Worker 	if (fd < 0) {
403*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "Cannot open %s/test-list.txt\n", settings->test_root);
404*d83cc019SAndroid Build Coastguard Worker 		close(dirfd);
405*d83cc019SAndroid Build Coastguard Worker 		return false;
406*d83cc019SAndroid Build Coastguard Worker 	}
407*d83cc019SAndroid Build Coastguard Worker 
408*d83cc019SAndroid Build Coastguard Worker 	/*
409*d83cc019SAndroid Build Coastguard Worker 	 * If a test_list is given (not to be confused with
410*d83cc019SAndroid Build Coastguard Worker 	 * test-list.txt), we use it directly without making tests
411*d83cc019SAndroid Build Coastguard Worker 	 * list their subtests. If include/exclude filters are given
412*d83cc019SAndroid Build Coastguard Worker 	 * we filter them directly from the test_list.
413*d83cc019SAndroid Build Coastguard Worker 	 */
414*d83cc019SAndroid Build Coastguard Worker 	if (settings->test_list)
415*d83cc019SAndroid Build Coastguard Worker 		result = job_list_from_test_list(job_list, settings);
416*d83cc019SAndroid Build Coastguard Worker 	else
417*d83cc019SAndroid Build Coastguard Worker 		result = filtered_job_list(job_list, settings, fd);
418*d83cc019SAndroid Build Coastguard Worker 
419*d83cc019SAndroid Build Coastguard Worker 	close(fd);
420*d83cc019SAndroid Build Coastguard Worker 	close(dirfd);
421*d83cc019SAndroid Build Coastguard Worker 
422*d83cc019SAndroid Build Coastguard Worker 	return result;
423*d83cc019SAndroid Build Coastguard Worker }
424*d83cc019SAndroid Build Coastguard Worker 
425*d83cc019SAndroid Build Coastguard Worker static char joblist_filename[] = "joblist.txt";
serialize_job_list(struct job_list * job_list,struct settings * settings)426*d83cc019SAndroid Build Coastguard Worker bool serialize_job_list(struct job_list *job_list, struct settings *settings)
427*d83cc019SAndroid Build Coastguard Worker {
428*d83cc019SAndroid Build Coastguard Worker 	int dirfd, fd;
429*d83cc019SAndroid Build Coastguard Worker 	size_t i, k;
430*d83cc019SAndroid Build Coastguard Worker 	FILE *f;
431*d83cc019SAndroid Build Coastguard Worker 
432*d83cc019SAndroid Build Coastguard Worker 	if (!settings->results_path) {
433*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "No results-path set; this shouldn't happen\n");
434*d83cc019SAndroid Build Coastguard Worker 		return false;
435*d83cc019SAndroid Build Coastguard Worker 	}
436*d83cc019SAndroid Build Coastguard Worker 
437*d83cc019SAndroid Build Coastguard Worker 	if ((dirfd = open(settings->results_path, O_DIRECTORY | O_RDONLY)) < 0) {
438*d83cc019SAndroid Build Coastguard Worker 		mkdir(settings->results_path, 0777);
439*d83cc019SAndroid Build Coastguard Worker 		if ((dirfd = open(settings->results_path, O_DIRECTORY | O_RDONLY)) < 0) {
440*d83cc019SAndroid Build Coastguard Worker 			fprintf(stderr, "Creating results-path failed\n");
441*d83cc019SAndroid Build Coastguard Worker 			return false;
442*d83cc019SAndroid Build Coastguard Worker 		}
443*d83cc019SAndroid Build Coastguard Worker 	}
444*d83cc019SAndroid Build Coastguard Worker 
445*d83cc019SAndroid Build Coastguard Worker 	if (!settings->overwrite &&
446*d83cc019SAndroid Build Coastguard Worker 	    faccessat(dirfd, joblist_filename, F_OK, 0) == 0) {
447*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "Job list file already exists and not overwriting\n");
448*d83cc019SAndroid Build Coastguard Worker 		close(dirfd);
449*d83cc019SAndroid Build Coastguard Worker 		return false;
450*d83cc019SAndroid Build Coastguard Worker 	}
451*d83cc019SAndroid Build Coastguard Worker 
452*d83cc019SAndroid Build Coastguard Worker 	if (settings->overwrite &&
453*d83cc019SAndroid Build Coastguard Worker 	    unlinkat(dirfd, joblist_filename, 0) != 0 &&
454*d83cc019SAndroid Build Coastguard Worker 	    errno != ENOENT) {
455*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "Error removing old job list\n");
456*d83cc019SAndroid Build Coastguard Worker 		close(dirfd);
457*d83cc019SAndroid Build Coastguard Worker 		return false;
458*d83cc019SAndroid Build Coastguard Worker 	}
459*d83cc019SAndroid Build Coastguard Worker 
460*d83cc019SAndroid Build Coastguard Worker 	if ((fd = openat(dirfd, joblist_filename, O_CREAT | O_EXCL | O_WRONLY, 0666)) < 0) {
461*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "Creating job list serialization file failed: %s\n", strerror(errno));
462*d83cc019SAndroid Build Coastguard Worker 		close(dirfd);
463*d83cc019SAndroid Build Coastguard Worker 		return false;
464*d83cc019SAndroid Build Coastguard Worker 	}
465*d83cc019SAndroid Build Coastguard Worker 
466*d83cc019SAndroid Build Coastguard Worker 	f = fdopen(fd, "w");
467*d83cc019SAndroid Build Coastguard Worker 	if (!f) {
468*d83cc019SAndroid Build Coastguard Worker 		close(fd);
469*d83cc019SAndroid Build Coastguard Worker 		close(dirfd);
470*d83cc019SAndroid Build Coastguard Worker 		return false;
471*d83cc019SAndroid Build Coastguard Worker 	}
472*d83cc019SAndroid Build Coastguard Worker 
473*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < job_list->size; i++) {
474*d83cc019SAndroid Build Coastguard Worker 		struct job_list_entry *entry = &job_list->entries[i];
475*d83cc019SAndroid Build Coastguard Worker 		fputs(entry->binary, f);
476*d83cc019SAndroid Build Coastguard Worker 
477*d83cc019SAndroid Build Coastguard Worker 		if (entry->subtest_count) {
478*d83cc019SAndroid Build Coastguard Worker 			const char *delim = "";
479*d83cc019SAndroid Build Coastguard Worker 
480*d83cc019SAndroid Build Coastguard Worker 			fprintf(f, " ");
481*d83cc019SAndroid Build Coastguard Worker 
482*d83cc019SAndroid Build Coastguard Worker 			for (k = 0; k < entry->subtest_count; k++) {
483*d83cc019SAndroid Build Coastguard Worker 				fprintf(f, "%s%s", delim, entry->subtests[k]);
484*d83cc019SAndroid Build Coastguard Worker 				delim = ",";
485*d83cc019SAndroid Build Coastguard Worker 			}
486*d83cc019SAndroid Build Coastguard Worker 		}
487*d83cc019SAndroid Build Coastguard Worker 
488*d83cc019SAndroid Build Coastguard Worker 		fprintf(f, "\n");
489*d83cc019SAndroid Build Coastguard Worker 	}
490*d83cc019SAndroid Build Coastguard Worker 
491*d83cc019SAndroid Build Coastguard Worker 	if (settings->sync) {
492*d83cc019SAndroid Build Coastguard Worker 		fsync(fd);
493*d83cc019SAndroid Build Coastguard Worker 		fsync(dirfd);
494*d83cc019SAndroid Build Coastguard Worker 	}
495*d83cc019SAndroid Build Coastguard Worker 
496*d83cc019SAndroid Build Coastguard Worker 	fclose(f);
497*d83cc019SAndroid Build Coastguard Worker 	close(dirfd);
498*d83cc019SAndroid Build Coastguard Worker 	return true;
499*d83cc019SAndroid Build Coastguard Worker }
500*d83cc019SAndroid Build Coastguard Worker 
read_job_list(struct job_list * job_list,int dirfd)501*d83cc019SAndroid Build Coastguard Worker bool read_job_list(struct job_list *job_list, int dirfd)
502*d83cc019SAndroid Build Coastguard Worker {
503*d83cc019SAndroid Build Coastguard Worker 	int fd;
504*d83cc019SAndroid Build Coastguard Worker 	FILE *f;
505*d83cc019SAndroid Build Coastguard Worker 	ssize_t read;
506*d83cc019SAndroid Build Coastguard Worker 	char *line = NULL;
507*d83cc019SAndroid Build Coastguard Worker 	size_t line_len = 0;
508*d83cc019SAndroid Build Coastguard Worker 
509*d83cc019SAndroid Build Coastguard Worker 	free_job_list(job_list);
510*d83cc019SAndroid Build Coastguard Worker 
511*d83cc019SAndroid Build Coastguard Worker 	if ((fd = openat(dirfd, joblist_filename, O_RDONLY)) < 0)
512*d83cc019SAndroid Build Coastguard Worker 		return false;
513*d83cc019SAndroid Build Coastguard Worker 
514*d83cc019SAndroid Build Coastguard Worker 	f = fdopen(fd, "r");
515*d83cc019SAndroid Build Coastguard Worker 	if (!f) {
516*d83cc019SAndroid Build Coastguard Worker 		close(fd);
517*d83cc019SAndroid Build Coastguard Worker 		return false;
518*d83cc019SAndroid Build Coastguard Worker 	}
519*d83cc019SAndroid Build Coastguard Worker 
520*d83cc019SAndroid Build Coastguard Worker 	while ((read = getline(&line, &line_len, f))) {
521*d83cc019SAndroid Build Coastguard Worker 		char *binary, *sublist, *comma;
522*d83cc019SAndroid Build Coastguard Worker 		char **subtests = NULL;
523*d83cc019SAndroid Build Coastguard Worker 		size_t num_subtests = 0, len;
524*d83cc019SAndroid Build Coastguard Worker 
525*d83cc019SAndroid Build Coastguard Worker 		if (read < 0) {
526*d83cc019SAndroid Build Coastguard Worker 			if (errno == EINTR)
527*d83cc019SAndroid Build Coastguard Worker 				continue;
528*d83cc019SAndroid Build Coastguard Worker 			else
529*d83cc019SAndroid Build Coastguard Worker 				break;
530*d83cc019SAndroid Build Coastguard Worker 		}
531*d83cc019SAndroid Build Coastguard Worker 
532*d83cc019SAndroid Build Coastguard Worker 		len = strlen(line);
533*d83cc019SAndroid Build Coastguard Worker 		if (len > 0 && line[len - 1] == '\n')
534*d83cc019SAndroid Build Coastguard Worker 			line[len - 1] = '\0';
535*d83cc019SAndroid Build Coastguard Worker 
536*d83cc019SAndroid Build Coastguard Worker 		sublist = strchr(line, ' ');
537*d83cc019SAndroid Build Coastguard Worker 		if (!sublist) {
538*d83cc019SAndroid Build Coastguard Worker 			add_job_list_entry(job_list, strdup(line), NULL, 0);
539*d83cc019SAndroid Build Coastguard Worker 			continue;
540*d83cc019SAndroid Build Coastguard Worker 		}
541*d83cc019SAndroid Build Coastguard Worker 
542*d83cc019SAndroid Build Coastguard Worker 		*sublist++ = '\0';
543*d83cc019SAndroid Build Coastguard Worker 		binary = strdup(line);
544*d83cc019SAndroid Build Coastguard Worker 
545*d83cc019SAndroid Build Coastguard Worker 		do {
546*d83cc019SAndroid Build Coastguard Worker 			comma = strchr(sublist, ',');
547*d83cc019SAndroid Build Coastguard Worker 			if (comma) {
548*d83cc019SAndroid Build Coastguard Worker 				*comma++ = '\0';
549*d83cc019SAndroid Build Coastguard Worker 			}
550*d83cc019SAndroid Build Coastguard Worker 
551*d83cc019SAndroid Build Coastguard Worker 			++num_subtests;
552*d83cc019SAndroid Build Coastguard Worker 			subtests = realloc(subtests, num_subtests * sizeof(*subtests));
553*d83cc019SAndroid Build Coastguard Worker 			subtests[num_subtests - 1] = strdup(sublist);
554*d83cc019SAndroid Build Coastguard Worker 			sublist = comma;
555*d83cc019SAndroid Build Coastguard Worker 		} while (comma != NULL);
556*d83cc019SAndroid Build Coastguard Worker 
557*d83cc019SAndroid Build Coastguard Worker 		add_job_list_entry(job_list, binary, subtests, num_subtests);
558*d83cc019SAndroid Build Coastguard Worker 	}
559*d83cc019SAndroid Build Coastguard Worker 
560*d83cc019SAndroid Build Coastguard Worker 	free(line);
561*d83cc019SAndroid Build Coastguard Worker 	fclose(f);
562*d83cc019SAndroid Build Coastguard Worker 
563*d83cc019SAndroid Build Coastguard Worker 	return true;
564*d83cc019SAndroid Build Coastguard Worker }
565