litest.c 97.1 KB
Newer Older
Peter Hutterer's avatar
Peter Hutterer committed
1 2
/*
 * Copyright © 2013 Red Hat, Inc.
3
 * Copyright © 2013 Marcin Slusarz <marcin.slusarz@gmail.com>
Peter Hutterer's avatar
Peter Hutterer committed
4
 *
5 6 7 8 9 10
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
Peter Hutterer's avatar
Peter Hutterer committed
11
 *
12 13 14 15 16 17 18 19 20 21 22
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
Peter Hutterer's avatar
Peter Hutterer committed
23 24 25 26 27
 */

#include "config.h"

#include <check.h>
28
#include <dirent.h>
Peter Hutterer's avatar
Peter Hutterer committed
29
#include <errno.h>
30
#include <libgen.h>
Peter Hutterer's avatar
Peter Hutterer committed
31
#include <fcntl.h>
32
#include <fnmatch.h>
Peter Hutterer's avatar
Peter Hutterer committed
33 34
#include <getopt.h>
#include <poll.h>
35
#include <signal.h>
Peter Hutterer's avatar
Peter Hutterer committed
36 37 38
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
39
#include <stdarg.h>
Peter Hutterer's avatar
Peter Hutterer committed
40 41
#include <time.h>
#include <unistd.h>
42
#include "linux/input.h"
Peter Hutterer's avatar
Peter Hutterer committed
43
#include <sys/ptrace.h>
44
#include <sys/resource.h>
Peter Hutterer's avatar
Peter Hutterer committed
45 46
#include <sys/timerfd.h>
#include <sys/wait.h>
47 48
#include <sys/stat.h>
#include <sys/types.h>
49
#include <libudev.h>
50 51 52
#if HAVE_LIBSYSTEMD
#include <systemd/sd-bus.h>
#endif
53 54 55
#ifdef __FreeBSD__
#include <termios.h>
#endif
Peter Hutterer's avatar
Peter Hutterer committed
56

57 58
#include <valgrind/valgrind.h>

Peter Hutterer's avatar
Peter Hutterer committed
59 60 61
#include "litest.h"
#include "litest-int.h"
#include "libinput-util.h"
62
#include "quirks.h"
63
#include "builddir.h"
Peter Hutterer's avatar
Peter Hutterer committed
64

65 66
#include <linux/kd.h>

67 68
#define UDEV_RULES_D "/run/udev/rules.d"
#define UDEV_RULE_PREFIX "99-litest-"
69 70
#define UDEV_FUZZ_OVERRIDE_RULE_FILE UDEV_RULES_D \
	"/91-litest-fuzz-override-REMOVEME-XXXXXX.rules"
71
#define UDEV_TEST_DEVICE_RULE_FILE UDEV_RULES_D \
72
	"/91-litest-test-device-REMOVEME-XXXXXXX.rules"
73
#define UDEV_DEVICE_GROUPS_FILE UDEV_RULES_D \
74
	"/80-libinput-device-groups-litest-XXXXXX.rules"
75

76
static int jobs = 8;
77 78
static bool in_debugger = false;
static bool verbose = false;
79
static bool run_deviceless = false;
80
static bool use_system_rules_quirks = false;
81
const char *filter_test = NULL;
82
const char *filter_device = NULL;
83
const char *filter_group = NULL;
84
static struct quirks_context *quirks_context;
Peter Hutterer's avatar
Peter Hutterer committed
85

86 87 88 89 90
struct created_file {
	struct list link;
	char *path;
};

91 92 93
struct list created_files_list; /* list of all files to remove at the end of
				   the test run */

94 95
static void litest_init_udev_rules(struct list *created_files_list);
static void litest_remove_udev_rules(struct list *created_files_list);
96 97 98 99 100 101 102 103

enum quirks_setup_mode {
	QUIRKS_SETUP_USE_SRCDIR,
	QUIRKS_SETUP_ONLY_DEVICE,
	QUIRKS_SETUP_FULL,
};
static void litest_setup_quirks(struct list *created_files_list,
				enum quirks_setup_mode mode);
104

105 106 107 108 109
/* defined for the litest selftest */
#ifndef LITEST_DISABLE_BACKTRACE_LOGGING
#define litest_log(...) fprintf(stderr, __VA_ARGS__)
#define litest_vlog(format_, args_) vfprintf(stderr, format_, args_)
#else
110 111
#define litest_log(...) { /* __VA_ARGS__ */ }
#define litest_vlog(...) { /* __VA_ARGS__ */ }
112 113 114 115 116
#endif

static void
litest_backtrace(void)
{
117 118 119
#if HAVE_GSTACK
	pid_t parent, child;
	int pipefd[2];
120

121 122 123 124 125
	if (RUNNING_ON_VALGRIND) {
		litest_log("  Using valgrind, omitting backtrace\n");
		return;
	}

126
	if (pipe(pipefd) == -1)
127 128
		return;

129 130
	parent = getpid();
	child = fork();
131

132 133
	if (child == 0) {
		char pid[8];
134

135 136
		close(pipefd[0]);
		dup2(pipefd[1], STDOUT_FILENO);
137

138
		sprintf(pid, "%d", parent);
139

140 141 142
		execlp("gstack", "gstack", pid, NULL);
		exit(errno);
	}
143

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
	/* parent */
	char buf[1024];
	int status, nread;

	close(pipefd[1]);
	waitpid(child, &status, 0);

	status = WEXITSTATUS(status);
	if (status != 0) {
		litest_log("ERROR: gstack failed, no backtrace available: %s\n",
			   strerror(status));
	} else {
		litest_log("\nBacktrace:\n");
		while ((nread = read(pipefd[0], buf, sizeof(buf) - 1)) > 0) {
			buf[nread] = '\0';
			litest_log("%s", buf);
160
		}
161
		litest_log("\n");
162
	}
163
	close(pipefd[0]);
164
#endif
165
}
166

167
LIBINPUT_ATTRIBUTE_PRINTF(5, 6)
168
__attribute__((noreturn))
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
void
litest_fail_condition(const char *file,
		      int line,
		      const char *func,
		      const char *condition,
		      const char *message,
		      ...)
{
	litest_log("FAILED: %s\n", condition);

	if (message) {
		va_list args;
		va_start(args, message);
		litest_vlog(message, args);
		va_end(args);
	}

	litest_log("in %s() (%s:%d)\n", func, file, line);
	litest_backtrace();
	abort();
}

191
__attribute__((noreturn))
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
void
litest_fail_comparison_int(const char *file,
			   int line,
			   const char *func,
			   const char *operator,
			   int a,
			   int b,
			   const char *astr,
			   const char *bstr)
{
	litest_log("FAILED COMPARISON: %s %s %s\n", astr, operator, bstr);
	litest_log("Resolved to: %d %s %d\n", a, operator, b);
	litest_log("in %s() (%s:%d)\n", func, file, line);
	litest_backtrace();
	abort();
}

209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
__attribute__((noreturn))
void
litest_fail_comparison_double(const char *file,
			      int line,
			      const char *func,
			      const char *operator,
			      double a,
			      double b,
			      const char *astr,
			      const char *bstr)
{
	litest_log("FAILED COMPARISON: %s %s %s\n", astr, operator, bstr);
	litest_log("Resolved to: %.3f %s %.3f\n", a, operator, b);
	litest_log("in %s() (%s:%d)\n", func, file, line);
	litest_backtrace();
	abort();
}

227
__attribute__((noreturn))
228 229 230 231 232 233 234 235 236 237 238
void
litest_fail_comparison_ptr(const char *file,
			   int line,
			   const char *func,
			   const char *comparison)
{
	litest_log("FAILED COMPARISON: %s\n", comparison);
	litest_log("in %s() (%s:%d)\n", func, file, line);
	litest_backtrace();
	abort();
}
Peter Hutterer's avatar
Peter Hutterer committed
239 240 241 242

struct test {
	struct list node;
	char *name;
243 244 245 246 247 248
	char *devname;
	void *func;
	void *setup;
	void *teardown;

	struct range range;
249
	bool deviceless;
Peter Hutterer's avatar
Peter Hutterer committed
250 251 252 253 254 255 256 257 258 259
};

struct suite {
	struct list node;
	struct list tests;
	char *name;
};

static struct litest_device *current_device;

260 261
struct litest_device *litest_current_device(void)
{
Peter Hutterer's avatar
Peter Hutterer committed
262 263 264
	return current_device;
}

265 266
void litest_set_current_device(struct litest_device *device)
{
Peter Hutterer's avatar
Peter Hutterer committed
267 268 269 270 271 272 273 274 275
	current_device = device;
}

void litest_generic_device_teardown(void)
{
	litest_delete_device(current_device);
	current_device = NULL;
}

276
struct list devices;
Peter Hutterer's avatar
Peter Hutterer committed
277 278 279

static struct list all_tests;

280 281
static inline void
litest_system(const char *command)
282
{
283 284 285 286
	int ret;

	ret = system(command);

287
	if (ret == -1) {
288
		litest_abort_msg("Failed to execute: %s", command);
289 290
	} else if (WIFEXITED(ret)) {
		if (WEXITSTATUS(ret))
291 292
			litest_abort_msg("'%s' failed with %d",
					 command,
293 294
					 WEXITSTATUS(ret));
	} else if (WIFSIGNALED(ret)) {
295 296
		litest_abort_msg("'%s' terminated with signal %d",
				 command,
297 298
				 WTERMSIG(ret));
	}
299 300
}

301 302 303 304 305 306
static void
litest_reload_udev_rules(void)
{
	litest_system("udevadm control --reload-rules");
}

Peter Hutterer's avatar
Peter Hutterer committed
307 308
static void
litest_add_tcase_for_device(struct suite *suite,
309
			    const char *funcname,
Peter Hutterer's avatar
Peter Hutterer committed
310
			    void *func,
311 312
			    const struct litest_test_device *dev,
			    const struct range *range)
Peter Hutterer's avatar
Peter Hutterer committed
313 314 315 316
{
	struct test *t;

	t = zalloc(sizeof(*t));
Peter Hutterer's avatar
Peter Hutterer committed
317 318
	t->name = safe_strdup(funcname);
	t->devname = safe_strdup(dev->shortname);
319 320 321 322
	t->func = func;
	t->setup = dev->setup;
	t->teardown = dev->teardown ?
			dev->teardown : litest_generic_device_teardown;
323
	if (range)
324 325 326
		t->range = *range;

	list_insert(&suite->tests, &t->node);
Peter Hutterer's avatar
Peter Hutterer committed
327 328 329
}

static void
330 331
litest_add_tcase_no_device(struct suite *suite,
			   void *func,
332
			   const char *funcname,
333
			   const struct range *range)
Peter Hutterer's avatar
Peter Hutterer committed
334 335
{
	struct test *t;
336
	const char *test_name = funcname;
Peter Hutterer's avatar
Peter Hutterer committed
337

338 339 340 341
	if (filter_device &&
	    fnmatch(filter_device, test_name, 0) != 0)
		return;

Peter Hutterer's avatar
Peter Hutterer committed
342
	t = zalloc(sizeof(*t));
Peter Hutterer's avatar
Peter Hutterer committed
343 344
	t->name = safe_strdup(test_name);
	t->devname = safe_strdup("no device");
345
	t->func = func;
346
	if (range)
347 348 349 350 351
		t->range = *range;
	t->setup = NULL;
	t->teardown = NULL;

	list_insert(&suite->tests, &t->node);
Peter Hutterer's avatar
Peter Hutterer committed
352 353
}

354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
static void
litest_add_tcase_deviceless(struct suite *suite,
			    void *func,
			    const char *funcname,
			    const struct range *range)
{
	struct test *t;
	const char *test_name = funcname;

	if (filter_device &&
	    fnmatch(filter_device, test_name, 0) != 0)
		return;

	t = zalloc(sizeof(*t));
	t->deviceless = true;
	t->name = safe_strdup(test_name);
	t->devname = safe_strdup("deviceless");
	t->func = func;
	if (range)
		t->range = *range;
	t->setup = NULL;
	t->teardown = NULL;

	list_insert(&suite->tests, &t->node);
}

380 381 382 383 384 385
static struct suite *
get_suite(const char *name)
{
	struct suite *s;

	list_for_each(s, &all_tests, node) {
386
		if (streq(s->name, name))
387 388 389 390
			return s;
	}

	s = zalloc(sizeof(*s));
Peter Hutterer's avatar
Peter Hutterer committed
391
	s->name = safe_strdup(name);
392 393 394 395 396 397 398

	list_init(&s->tests);
	list_insert(&all_tests, &s->node);

	return s;
}

Peter Hutterer's avatar
Peter Hutterer committed
399
static void
400 401 402
litest_add_tcase(const char *suite_name,
		 const char *funcname,
		 void *func,
Peter Hutterer's avatar
Peter Hutterer committed
403
		 enum litest_device_feature required,
404 405
		 enum litest_device_feature excluded,
		 const struct range *range)
Peter Hutterer's avatar
Peter Hutterer committed
406
{
407
	struct suite *suite;
408
	bool added = false;
Peter Hutterer's avatar
Peter Hutterer committed
409

410 411
	litest_assert(required >= LITEST_DEVICELESS);
	litest_assert(excluded >= LITEST_DEVICELESS);
412

413 414 415 416
	if (filter_test &&
	    fnmatch(filter_test, funcname, 0) != 0)
		return;

417 418 419 420
	if (filter_group &&
	    fnmatch(filter_group, suite_name, 0) != 0)
		return;

421 422
	suite = get_suite(suite_name);

423 424 425 426 427
	if (required == LITEST_DEVICELESS &&
	    excluded == LITEST_DEVICELESS) {
		litest_add_tcase_deviceless(suite, func, funcname, range);
		added = true;
	} else if (required == LITEST_DISABLE_DEVICE &&
Peter Hutterer's avatar
Peter Hutterer committed
428
	    excluded == LITEST_DISABLE_DEVICE) {
429
		litest_add_tcase_no_device(suite, func, funcname, range);
430
		added = true;
Peter Hutterer's avatar
Peter Hutterer committed
431
	} else if (required != LITEST_ANY || excluded != LITEST_ANY) {
432 433 434 435
		struct litest_test_device *dev;

		list_for_each(dev, &devices, node) {
			if (dev->features & LITEST_IGNORED)
436 437
				continue;

438
			if (filter_device &&
439
			    fnmatch(filter_device, dev->shortname, 0) != 0)
440
				continue;
441 442
			if ((dev->features & required) != required ||
			    (dev->features & excluded) != 0)
443 444 445 446 447
				continue;

			litest_add_tcase_for_device(suite,
						    funcname,
						    func,
448
						    dev,
449
						    range);
450
			added = true;
Peter Hutterer's avatar
Peter Hutterer committed
451 452
		}
	} else {
453 454 455 456
		struct litest_test_device *dev;

		list_for_each(dev, &devices, node) {
			if (dev->features & LITEST_IGNORED)
457 458
				continue;

459
			if (filter_device &&
460
			    fnmatch(filter_device, dev->shortname, 0) != 0)
461 462
				continue;

463 464 465
			litest_add_tcase_for_device(suite,
						    funcname,
						    func,
466
						    dev,
467
						    range);
468
			added = true;
Peter Hutterer's avatar
Peter Hutterer committed
469 470
		}
	}
471

472 473 474 475
	if (!added &&
	    filter_test == NULL &&
	    filter_device == NULL &&
	    filter_group == NULL) {
476 477 478
		fprintf(stderr, "Test '%s' does not match any devices. Aborting.\n", funcname);
		abort();
	}
Peter Hutterer's avatar
Peter Hutterer committed
479 480 481
}

void
482
_litest_add_no_device(const char *name, const char *funcname, void *func)
Peter Hutterer's avatar
Peter Hutterer committed
483
{
484
	_litest_add(name, funcname, func, LITEST_DISABLE_DEVICE, LITEST_DISABLE_DEVICE);
Peter Hutterer's avatar
Peter Hutterer committed
485 486
}

487
void
488 489 490 491
_litest_add_ranged_no_device(const char *name,
			     const char *funcname,
			     void *func,
			     const struct range *range)
Peter Hutterer's avatar
Peter Hutterer committed
492
{
493 494 495 496 497 498
	_litest_add_ranged(name,
			   funcname,
			   func,
			   LITEST_DISABLE_DEVICE,
			   LITEST_DISABLE_DEVICE,
			   range);
499
}
Peter Hutterer's avatar
Peter Hutterer committed
500

501 502 503 504 505 506 507 508 509 510 511 512 513
void
_litest_add_deviceless(const char *name,
		       const char *funcname,
		       void *func)
{
	_litest_add_ranged(name,
			   funcname,
			   func,
			   LITEST_DEVICELESS,
			   LITEST_DEVICELESS,
			   NULL);
}

514
void
515 516 517 518 519
_litest_add(const char *name,
	    const char *funcname,
	    void *func,
	    enum litest_device_feature required,
	    enum litest_device_feature excluded)
520
{
521 522 523 524 525 526
	_litest_add_ranged(name,
			   funcname,
			   func,
			   required,
			   excluded,
			   NULL);
527
}
528

529
void
530 531 532 533 534 535
_litest_add_ranged(const char *name,
		   const char *funcname,
		   void *func,
		   enum litest_device_feature required,
		   enum litest_device_feature excluded,
		   const struct range *range)
536
{
537
	litest_add_tcase(name, funcname, func, required, excluded, range);
538 539 540
}

void
541 542 543 544
_litest_add_for_device(const char *name,
		       const char *funcname,
		       void *func,
		       enum litest_device_type type)
545
{
546
	_litest_add_ranged_for_device(name, funcname, func, type, NULL);
547 548 549
}

void
550 551 552 553 554
_litest_add_ranged_for_device(const char *name,
			      const char *funcname,
			      void *func,
			      enum litest_device_type type,
			      const struct range *range)
555 556
{
	struct suite *s;
557
	struct litest_test_device *dev;
558
	bool device_filtered = false;
559

560
	litest_assert(type < LITEST_NO_DEVICE);
561

562 563 564 565
	if (filter_test &&
	    fnmatch(filter_test, funcname, 0) != 0)
		return;

566 567 568 569
	if (filter_group &&
	    fnmatch(filter_group, name, 0) != 0)
		return;

570
	s = get_suite(name);
571
	list_for_each(dev, &devices, node) {
572
		if (filter_device &&
573
		    fnmatch(filter_device, dev->shortname, 0) != 0) {
574
			device_filtered = true;
575
			continue;
576
		}
577

578
		if (dev->type == type) {
579 580 581
			litest_add_tcase_for_device(s,
						    funcname,
						    func,
582
						    dev,
583
						    range);
584 585 586 587
			return;
		}
	}

588 589
	/* only abort if no filter was set, that's a bug */
	if (!device_filtered)
590
		litest_abort_msg("Invalid test device type\n");
Peter Hutterer's avatar
Peter Hutterer committed
591 592
}

593
LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
594
static void
595 596
litest_log_handler(struct libinput *libinput,
		   enum libinput_log_priority pri,
597 598 599
		   const char *format,
		   va_list args)
{
600
	static int is_tty = -1;
601
	const char *priority = NULL;
602 603 604 605
	const char *color;

	if (is_tty == -1)
		is_tty = isatty(STDERR_FILENO);
606 607

	switch(pri) {
608 609 610 611 612 613
	case LIBINPUT_LOG_PRIORITY_INFO:
		priority =  "info ";
		color = ANSI_HIGHLIGHT;
		break;
	case LIBINPUT_LOG_PRIORITY_ERROR:
		priority = "error";
614
		color = ANSI_BRIGHT_RED;
615 616 617 618 619
		break;
	case LIBINPUT_LOG_PRIORITY_DEBUG:
		priority = "debug";
		color = ANSI_NORMAL;
		break;
620 621
	default:
		  abort();
622 623
	}

624 625
	if (!is_tty)
		color = "";
626
	else if (strstr(format, "tap:"))
627 628 629 630 631 632 633 634 635 636 637
		color = ANSI_BLUE;
	else if (strstr(format, "thumb state:"))
		color = ANSI_YELLOW;
	else if (strstr(format, "button state:"))
		color = ANSI_MAGENTA;
	else if (strstr(format, "touch-size:") ||
		 strstr(format, "pressure:"))
		color = ANSI_GREEN;
	else if (strstr(format, "palm:") ||
		 strstr(format, "thumb:"))
		color = ANSI_CYAN;
638
	else if (strstr(format, "edge-scroll:"))
639 640
		color = ANSI_BRIGHT_GREEN;

641
	fprintf(stderr, "%slitest %s ", color, priority);
642
	vfprintf(stderr, format, args);
643
	if (is_tty)
644 645
		fprintf(stderr, ANSI_NORMAL);

646
	if (strstr(format, "client bug: ") ||
647 648 649 650
	    strstr(format, "libinput bug: ")) {
		/* valgrind is too slow and some of our offsets are too
		 * short, don't abort if during a valgrind run we get a
		 * negative offset */
651
		if ((!RUNNING_ON_VALGRIND && !in_debugger) ||
652
		    !strstr(format, "offset negative"))
653
		litest_abort_msg("libinput bug triggered, aborting.\n");
654
	}
655 656 657 658

	if (strstr(format, "Touch jump detected and discarded")) {
		litest_abort_msg("libinput touch jump triggered, aborting.\n");
	}
659 660
}

661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
static void
litest_init_device_udev_rules(struct litest_test_device *dev, FILE *f)
{
	const struct key_value_str *kv;
	static int count;

	if (!dev->udev_properties)
		return;

	count++;

	fprintf(f, "# %s\n", dev->shortname);
	fprintf(f, "ACTION==\"remove\", GOTO=\"rule%d_end\"\n", count);
	fprintf(f, "KERNEL!=\"event*\", GOTO=\"rule%d_end\"\n", count);

	fprintf(f, "ATTRS{name}==\"litest %s*\"", dev->name);

	kv = dev->udev_properties;
	while (kv->key) {
		fprintf(f, ", \\\n\tENV{%s}=\"%s\"", kv->key, kv->value);
		kv++;
	}

	fprintf(f, "\n");
	fprintf(f, "LABEL=\"rule%d_end\"\n\n", count);;
}
687 688 689 690

static void
litest_init_all_device_udev_rules(struct list *created_files)
{
691
	struct created_file *file = zalloc(sizeof(*file));
692
	struct litest_test_device *dev;
693 694 695 696
	char *path = NULL;
	FILE *f;
	int rc;
	int fd;
697

698 699 700 701 702
	rc = xasprintf(&path,
		      "%s/%s-XXXXXX.rules",
		      UDEV_RULES_D,
		      UDEV_RULE_PREFIX);
	litest_assert_int_gt(rc, 0);
703

704 705 706 707 708 709 710 711 712 713 714 715
	fd = mkstemps(path, 6);
	litest_assert_int_ne(fd, -1);
	f = fdopen(fd, "w");
	litest_assert_notnull(f);

	list_for_each(dev, &devices, node)
		litest_init_device_udev_rules(dev, f);

	fclose(f);

	file->path = path;
	list_insert(created_files, &file->link);
716 717
}

718 719 720
static int
open_restricted(const char *path, int flags, void *userdata)
{
721 722
	int fd = open(path, flags);
	return fd < 0 ? -errno : fd;
723 724 725 726 727 728 729 730 731 732 733 734 735
}

static void
close_restricted(int fd, void *userdata)
{
	close(fd);
}

struct libinput_interface interface = {
	.open_restricted = open_restricted,
	.close_restricted = close_restricted,
};

736 737 738 739 740 741 742 743
static void
litest_signal(int sig)
{
	struct created_file *f, *tmp;

	list_for_each_safe(f, tmp, &created_files_list, link) {
		list_remove(&f->link);
		unlink(f->path);
744
		rmdir(f->path);
745 746 747
		/* in the sighandler, we can't free */
	}

748 749 750 751 752 753
	if (fork() == 0) {
		/* child, we can run system() */
		litest_reload_udev_rules();
		exit(0);
	}

754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
	exit(1);
}

static inline void
litest_setup_sighandler(int sig)
{
	struct sigaction act, oact;
	int rc;

	sigemptyset(&act.sa_mask);
	sigaddset(&act.sa_mask, sig);
	act.sa_flags = 0;
	act.sa_handler = litest_signal;
	rc = sigaction(sig, &act, &oact);
	litest_assert_int_ne(rc, -1);
}

771 772
static void
litest_free_test_list(struct list *tests)
773
{
Peter Hutterer's avatar
Peter Hutterer committed
774
	struct suite *s, *snext;
775 776 777 778 779 780

	list_for_each_safe(s, snext, tests, node) {
		struct test *t, *tnext;

		list_for_each_safe(t, tnext, &s->tests, node) {
			free(t->name);
781
			free(t->devname);
782 783 784 785 786 787 788 789 790 791
			list_remove(&t->node);
			free(t);
		}

		list_remove(&s->node);
		free(s->name);
		free(s);
	}
}

792 793 794 795 796 797 798 799 800 801 802 803 804
LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
static inline void
quirk_log_handler(struct libinput *unused,
		  enum libinput_log_priority priority,
		  const char *format,
		  va_list args)
{
	if (priority < LIBINPUT_LOG_PRIORITY_ERROR)
		return;

	vfprintf(stderr, format, args);
}

805
static int
806
litest_run_suite(struct list *tests, int which, int max, int error_fd)
807 808 809 810
{
	int failed = 0;
	SRunner *sr = NULL;
	struct suite *s;
811
	struct test *t;
812
	int count = -1;
813 814 815 816 817 818
	struct name {
		struct list node;
		char *name;
	};
	struct name *n, *tmp;
	struct list testnames;
819
	const char *data_path;
820

821 822 823 824 825
	data_path = getenv("LIBINPUT_QUIRKS_DIR");
	if (!data_path)
		data_path = LIBINPUT_QUIRKS_DIR;

	quirks_context = quirks_init_subsystem(data_path,
826 827 828 829 830
					       NULL,
					       quirk_log_handler,
					       NULL,
					       QLOG_LIBINPUT_LOGGING);

831 832 833 834
	/* Check just takes the suite/test name pointers but doesn't strdup
	 * them - we have to keep them around */
	list_init(&testnames);

835 836 837 838
	/* For each test, create one test suite with one test case, then
	   add it to the test runner. The only benefit suites give us in
	   check is that we can filter them, but our test runner has a
	   --filter-group anyway. */
839
	list_for_each(s, tests, node) {
840 841 842
		list_for_each(t, &s->tests, node) {
			Suite *suite;
			TCase *tc;
843
			char *sname, *tname;
844

845 846 847 848 849
			/* We run deviceless tests as part of the normal
			 * test suite runner, just in case. Filtering
			 * all the other ones out just for the case where
			 * we can't run the full runner.
			 */
850
			if (run_deviceless && !t->deviceless)
851 852
				continue;

853 854 855
			count = (count + 1) % max;
			if (max != 1 && (count % max) != which)
				continue;
856

857 858 859 860 861
			xasprintf(&sname,
				  "%s:%s:%s",
				  s->name,
				  t->name,
				  t->devname);
862
			litest_assert_ptr_notnull(sname);
863 864 865 866 867 868 869 870
			n = zalloc(sizeof(*n));
			n->name = sname;
			list_insert(&testnames, &n->node);

			xasprintf(&tname,
				  "%s:%s",
				  t->name,
				  t->devname);
871
			litest_assert_ptr_notnull(tname);
872 873 874 875 876
			n = zalloc(sizeof(*n));
			n->name = tname;
			list_insert(&testnames, &n->node);

			tc = tcase_create(tname);
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895
			tcase_add_checked_fixture(tc,
						  t->setup,
						  t->teardown);
			if (t->range.upper != t->range.lower)
				tcase_add_loop_test(tc,
						    t->func,
						    t->range.lower,
						    t->range.upper);
			else
				tcase_add_test(tc, t->func);

			suite = suite_create(sname);
			suite_add_tcase(suite, tc);

			if (!sr)
				sr = srunner_create(suite);
			else
				srunner_add_suite(sr, suite);
		}
896 897 898
	}

	if (!sr)
899
		goto out;
900 901 902

	srunner_run_all(sr, CK_ENV);
	failed = srunner_ntests_failed(sr);
903 904 905 906 907
	if (failed) {
		TestResult **trs;

		trs = srunner_failures(sr);
		for (int i = 0; i < failed; i++) {
908 909 910 911 912 913 914 915 916 917 918
			char tname[256];
			char *c = tname;

			/* tr_tcname is in the form "suite:testcase", let's
			 * convert this to "suite(testcase)" to make
			 * double-click selection in the terminal a bit
			 * easier. */
			snprintf(tname, sizeof(tname), "%s)", tr_tcname(trs[i]));
			if ((c = index(c, ':')))
				*c = '(';

919
			dprintf(error_fd,
920
				":: Failure: %s:%d: %s\n",
921 922
				tr_lfile(trs[i]),
				tr_lno(trs[i]),
923
				tname);
924 925 926
		}
		free(trs);
	}
927
	srunner_free(sr);
928 929 930 931 932 933
out:
	list_for_each_safe(n, tmp, &testnames, node) {
		free(n->name);
		free(n);
	}

934 935
	quirks_context_unref(quirks_context);

936 937 938 939
	return failed;
}

static int
940
litest_fork_subtests(struct list *tests, int max_forks)
941 942 943 944 945
{
	int failed = 0;
	int status;
	pid_t pid;
	int f;
946
	int pipes[max_forks];
947 948

	for (f = 0; f < max_forks; f++) {
949 950 951 952 953 954
		int rc;
		int pipefd[2];

		rc = pipe2(pipefd, O_NONBLOCK|O_NONBLOCK);
		assert(rc != -1);

955 956
		pid = fork();
		if (pid == 0) {
957 958 959 960 961 962
			close(pipefd[0]);
			failed = litest_run_suite(tests,
						  f,
						  max_forks,
						  pipefd[1]);

963 964 965
			litest_free_test_list(&all_tests);
			exit(failed);
			/* child always exits here */
966 967 968
		} else {
			pipes[f] = pipefd[0];
			close(pipefd[1]);
969 970 971 972 973
		}
	}

	/* parent process only */
	while (wait(&status) != -1 && errno != ECHILD) {
974
		if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
975 976 977
			failed = 1;
	}

978 979 980 981 982 983 984 985 986 987 988 989
	for (f = 0; f < max_forks; f++) {
		char buf[1024] = {0};
		int rc;

		while ((rc = read(pipes[f], buf, sizeof(buf) - 1)) > 0) {
			buf[rc] = '\0';
			fprintf(stderr, "%s", buf);
		}

		close(pipes[f]);
	}

990 991 992
	return failed;
}

993 994 995 996 997 998 999 1000 1001 1002
static inline int
inhibit(void)
{
	int lock_fd = -1;
#if HAVE_LIBSYSTEMD
	sd_bus_error error = SD_BUS_ERROR_NULL;
	sd_bus_message *m = NULL;
	sd_bus *bus = NULL;
	int rc;

1003 1004 1005
	if (run_deviceless)
		return -1;

1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
	rc = sd_bus_open_system(&bus);
	if (rc != 0) {
		fprintf(stderr, "Warning: inhibit failed: %s\n", strerror(-rc));
		goto out;
	}

	rc = sd_bus_call_method(bus,
				"org.freedesktop.login1",
				"/org/freedesktop/login1",
				"org.freedesktop.login1.Manager",
				"Inhibit",
				&error,
				&m,
				"ssss",
				"handle-lid-switch:handle-power-key:handle-suspend-key:handle-hibernate-key",
				"libinput test-suite runner",
				"testing in progress",
				"block");
	if (rc < 0) {
		fprintf(stderr, "Warning: inhibit failed: %s\n", error.message);
		goto out;
	}

	rc = sd_bus_message_read(m, "h", &lock_fd);
	if (rc < 0) {
		fprintf(stderr, "Warning: inhibit failed: %s\n", strerror(-rc));
		goto out;
	}

	lock_fd = dup(lock_fd);
out:
	sd_bus_error_free(&error);
	sd_bus_message_unref(m);
	sd_bus_close(bus);
	sd_bus_unref(bus);
#endif
	return lock_fd;
}

1045 1046 1047 1048
static inline int
litest_run(int argc, char **argv)
{
	int failed = 0;
1049
	int inhibit_lock_fd;
1050