[igt-dev] [PATCH i-g-t 1/9] lib/tests: Extract fork helpers

Petri Latvala petri.latvala at intel.com
Fri Feb 14 11:57:29 UTC 2020


On Wed, Feb 12, 2020 at 03:21:15PM +0200, Arkadiusz Hiler wrote:
> Because of excessive 'copy and paste' we ended up with multiple copies
> of almost the same fork helper. This patch extracts the do_fork helper
> out and switches all the tests over to it.
> 
> Additionally, preemptively I have extracted the more fancy fork helper
> that captures stderr/out + related functions out of igt_describe tests.
> 
> Signed-off-by: Arkadiusz Hiler <arkadiusz.hiler at intel.com>

Reviewed-by: Petri Latvala <petri.latvala at intel.com>


> ---
>  lib/tests/igt_assert.c               |  35 +++----
>  lib/tests/igt_conflicting_args.c     |  25 ++---
>  lib/tests/igt_describe.c             | 135 ++++++---------------------
>  lib/tests/igt_dynamic_subtests.c     |  18 ----
>  lib/tests/igt_fork.c                 |  71 ++++++--------
>  lib/tests/igt_invalid_subtest_name.c |  18 ----
>  lib/tests/igt_no_exit.c              |  18 ----
>  lib/tests/igt_segfault.c             |  59 +++++-------
>  lib/tests/igt_simulation.c           | 101 +++++++++-----------
>  lib/tests/igt_tests_common.h         |  91 ++++++++++++++++++
>  10 files changed, 232 insertions(+), 339 deletions(-)
> 
> diff --git a/lib/tests/igt_assert.c b/lib/tests/igt_assert.c
> index 1caf5d88..c94ac698 100644
> --- a/lib/tests/igt_assert.c
> +++ b/lib/tests/igt_assert.c
> @@ -38,8 +38,6 @@
>  
>  #include "igt_tests_common.h"
>  
> -char test[] = "test";
> -char *argv_run[] = { test };
>  void (*test_to_run)(void) = NULL;
>  
>  /*
> @@ -55,26 +53,17 @@ void (*test_to_run)(void) = NULL;
>  	exec_total++; \
>  }
>  
> -static int do_fork(void)
> +static void fake_test(void)
>  {
> -	int pid, status;
> -	int argc;
> -
> -	switch (pid = fork()) {
> -	case -1:
> -		internal_assert(0);
> -	case 0:
> -		argc = ARRAY_SIZE(argv_run);
> -		igt_simple_init(argc, argv_run);
> -		test_to_run();
> -		igt_exit();
> -	default:
> -		while (waitpid(pid, &status, 0) == -1 &&
> -		       errno == EINTR)
> -			;
> -
> -		return status;
> -	}
> +	char test[] = "test";
> +	char *argv_run[] = { test };
> +	int argc = ARRAY_SIZE(argv_run);
> +
> +	igt_simple_init(argc, argv_run);
> +
> +	test_to_run();
> +
> +	igt_exit();
>  }
>  
>  static void test_cmpint_negative(void)
> @@ -150,7 +139,7 @@ igt_main
>  	 * we inherit the state from the parent, so ...
>  	 */
>  	test_to_run = test_cmpint_negative;
> -	ret = do_fork();
> +	ret = do_fork(fake_test);
>  	igt_subtest("igt_cmpint_negative")
>  		internal_assert_wexited(ret, IGT_EXIT_FAILURE);
>  
> @@ -158,7 +147,7 @@ igt_main
>  		test_fd();
>  
>  	test_to_run = test_fd_negative;
> -	ret = do_fork();
> +	ret = do_fork(fake_test);
>  	igt_subtest("igt_assert_fd_negative")
>  		internal_assert_wexited(ret, IGT_EXIT_FAILURE);
>  }
> diff --git a/lib/tests/igt_conflicting_args.c b/lib/tests/igt_conflicting_args.c
> index f600abd4..b644fd4b 100644
> --- a/lib/tests/igt_conflicting_args.c
> +++ b/lib/tests/igt_conflicting_args.c
> @@ -43,25 +43,12 @@ static int opt_handler(int option, int option_index, void *input)
>  	return 0;
>  }
>  
> -static int do_fork(void)
> +static void fake_test(void)
>  {
>  	char test_name[] = "test";
> -
>  	char *argv[] = { test_name };
>  	int argc = ARRAY_SIZE(argv);
>  
> -	pid_t pid = fork();
> -	internal_assert(pid != -1);
> -
> -	if (pid) {
> -		int status;
> -		while (waitpid(pid, &status, 0) == -1 && errno == EINTR)
> -			;
> -
> -		return status;
> -	}
> -
> -
>  	igt_subtest_init_parse_opts(&argc, argv, short_options, long_options,
>  				    "", opt_handler, NULL);
>  	igt_subtest("dummy") {}
> @@ -73,27 +60,27 @@ int main(int argc, char **argv)
>  	/* no conflict */
>  	long_options[0] = (struct option) { "iterations", required_argument, NULL, 'i'};
>  	short_options = "";
> -	internal_assert_wexited(do_fork(), 0);
> +	internal_assert_wexited(do_fork(fake_test), 0);
>  
>  	/* conflict on short option */
>  	long_options[0] = (struct option) { "iterations", required_argument, NULL, 'i'};
>  	short_options = "h";
> -	internal_assert_wsignaled(do_fork(), SIGABRT);
> +	internal_assert_wsignaled(do_fork(fake_test), SIGABRT);
>  
>  	/* conflict on long option name */
>  	long_options[0] = (struct option) { "help", required_argument, NULL, 'i'};
>  	short_options = "";
> -	internal_assert_wsignaled(do_fork(), SIGABRT);
> +	internal_assert_wsignaled(do_fork(fake_test), SIGABRT);
>  
>  	/* conflict on long option 'val' representation vs short option */
>  	long_options[0] = (struct option) { "iterations", required_argument, NULL, 'h'};
>  	short_options = "";
> -	internal_assert_wsignaled(do_fork(), SIGABRT);
> +	internal_assert_wsignaled(do_fork(fake_test), SIGABRT);
>  
>  	/* conflict on long option 'val' representations */
>  	long_options[0] = (struct option) { "iterations", required_argument, NULL, 500};
>  	short_options = "";
> -	internal_assert_wsignaled(do_fork(), SIGABRT);
> +	internal_assert_wsignaled(do_fork(fake_test), SIGABRT);
>  
>  	return 0;
>  }
> diff --git a/lib/tests/igt_describe.c b/lib/tests/igt_describe.c
> index 6f3a4319..7b4fa9af 100644
> --- a/lib/tests/igt_describe.c
> +++ b/lib/tests/igt_describe.c
> @@ -28,9 +28,15 @@
>  #include "drmtest.h"
>  #include "igt_tests_common.h"
>  
> +char prog[] = "igt_describe";
> +char fake_arg[100];
> +char *fake_argv[] = {prog, fake_arg};
> +int fake_argc = ARRAY_SIZE(fake_argv);
> +
>  IGT_TEST_DESCRIPTION("the top level description");
> -static void fake_main(int argc, char **argv) {
> -	igt_subtest_init(argc, argv);
> +static void fake_main(void)
> +{
> +	igt_subtest_init(fake_argc, fake_argv);
>  
>  	igt_describe("Basic A");
>  	igt_subtest("A")
> @@ -101,33 +107,33 @@ static void fake_main(int argc, char **argv) {
>  static const char DESCRIBE_ALL_OUTPUT[] = \
>  	"the top level description\n"
>  	"\n"
> -	"SUB A ../lib/tests/igt_describe.c:36:\n"
> +	"SUB A ../lib/tests/igt_describe.c:42:\n"
>  	"  Basic A\n"
>  	"\n"
> -	"SUB B ../lib/tests/igt_describe.c:45:\n"
> +	"SUB B ../lib/tests/igt_describe.c:51:\n"
>  	"  Group with B, C & D\n"
>  	"\n"
>  	"  Basic B\n"
>  	"\n"
> -	"SUB C ../lib/tests/igt_describe.c:54:\n"
> +	"SUB C ../lib/tests/igt_describe.c:60:\n"
>  	"  Group with B, C & D\n"
>  	"\n"
>  	"  Group with C & D\n"
>  	"\n"
>  	"  Basic C\n"
>  	"\n"
> -	"SUB D ../lib/tests/igt_describe.c:58:\n"
> +	"SUB D ../lib/tests/igt_describe.c:64:\n"
>  	"  Group with B, C & D\n"
>  	"\n"
>  	"  Group with C & D\n"
>  	"\n"
> -	"SUB E ../lib/tests/igt_describe.c:66:\n"
> +	"SUB E ../lib/tests/igt_describe.c:72:\n"
>  	"  NO DOCUMENTATION!\n"
>  	"\n"
> -	"SUB F ../lib/tests/igt_describe.c:71:\n"
> +	"SUB F ../lib/tests/igt_describe.c:77:\n"
>  	"  NO DOCUMENTATION!\n"
>  	"\n"
> -	"SUB G ../lib/tests/igt_describe.c:80:\n"
> +	"SUB G ../lib/tests/igt_describe.c:86:\n"
>  	"  this description should be so long that it wraps itself nicely in the terminal this\n"
>  	"  description should be so long that it wraps itself nicely in the terminal this description\n"
>  	"  should be so long that it wraps itself nicely in the terminal this description should be so\n"
> @@ -135,17 +141,17 @@ static const char DESCRIBE_ALL_OUTPUT[] = \
>  	"  wraps itself nicely in the terminal this description should be so long that it wraps itself\n"
>  	"  nicely in the terminal\n"
>  	"\n"
> -	"SUB F ../lib/tests/igt_describe.c:87:\n"
> +	"SUB F ../lib/tests/igt_describe.c:93:\n"
>  	"  verylongwordthatshoudlbeprintedeventhoughitspastthewrppinglimitverylongwordthatshoudlbeprintedeventhoughitspastthewrappinglimit\n"
>  	"  verylongwordthatshoudlbeprintedeventhoughitspastthewrappinglimitverylongwordthatshoudlbeprintedeventhoughitspastthewrappinglimit\n"
>  	"\n"
> -	"SUB G ../lib/tests/igt_describe.c:91:\n"
> +	"SUB G ../lib/tests/igt_describe.c:97:\n"
>  	"  Subtest with dynamic subsubtests\n\n";
>  
>  static const char JUST_C_OUTPUT[] = \
>  	"the top level description\n"
>  	"\n"
> -	"SUB C ../lib/tests/igt_describe.c:54:\n"
> +	"SUB C ../lib/tests/igt_describe.c:60:\n"
>  	"  Group with B, C & D\n"
>  	"\n"
>  	"  Group with C & D\n"
> @@ -153,95 +159,22 @@ static const char JUST_C_OUTPUT[] = \
>  	"  Basic C\n"
>  	"\n";
>  
> -static void assert_pipe_empty(int fd)
> -{
> -	char buf[5];
> -	internal_assert(0 == read(fd, buf, sizeof(buf)));
> -}
> -
> -static void read_whole_pipe(int fd, char *buf, size_t buflen)
> -{
> -	ssize_t readlen;
> -	off_t offset;
> -
> -	offset = 0;
> -	while ((readlen = read(fd, buf+offset, buflen-offset))) {
> -		if (readlen == -1) {
> -			if (errno == EINTR) {
> -				continue;
> -			} else {
> -				printf("read failed with %s\n", strerror(errno));
> -				exit(1);
> -			}
> -		}
> -		internal_assert(readlen != -1);
> -		offset += readlen;
> -	}
> -}
> -
> -static pid_t do_fork(int argc, char **argv, int *out, int *err)
> -{
> -	int outfd[2], errfd[2];
> -	pid_t pid;
> -
> -	internal_assert(pipe(outfd) != -1);
> -	internal_assert(pipe(errfd) != -1);
> -
> -	pid = fork();
> -	internal_assert(pid != -1);
> -
> -	if (pid == 0) {
> -		while (dup2(outfd[1], STDOUT_FILENO) == -1 && errno == EINTR) {}
> -		while (dup2(errfd[1], STDERR_FILENO) == -1 && errno == EINTR) {}
> -
> -		close(outfd[0]);
> -		close(outfd[1]);
> -		close(errfd[0]);
> -		close(errfd[1]);
> -
> -		fake_main(argc, argv);
> -
> -		exit(-1);
> -	} else {
> -		/* close the writing ends */
> -		close(outfd[1]);
> -		close(errfd[1]);
> -
> -		*out = outfd[0];
> -		*err = errfd[0];
> -
> -		return pid;
> -	}
> -}
> -
> -static int _wait(pid_t pid, int *status) {
> -	int ret;
> -
> -	do {
> -		ret = waitpid(pid, status, 0);
> -	} while (ret == -1 && errno == EINTR);
> -
> -	return ret;
> -}
> -
>  int main(int argc, char **argv)
>  {
> -	char prog[] = "igt_describe";
>  	int status;
>  	int outfd, errfd;
> +	pid_t pid;
>  
>  	/* describe all subtest */ {
>  		static char out[4096];
> -		char arg[] = "--describe";
> -		char *fake_argv[] = {prog, arg};
> -		int fake_argc = ARRAY_SIZE(fake_argv);
> +		strncpy(fake_arg, "--describe", sizeof(fake_arg));
>  
> -		pid_t pid = do_fork(fake_argc, fake_argv, &outfd, &errfd);
> +		pid = do_fork_bg_with_pipes(fake_main, &outfd, &errfd);
>  
>  		read_whole_pipe(outfd, out, sizeof(out));
>  		assert_pipe_empty(errfd);
>  
> -		internal_assert(_wait(pid, &status) != -1);
> +		internal_assert(safe_wait(pid, &status) != -1);
>  		internal_assert(WIFEXITED(status));
>  		internal_assert(WEXITSTATUS(status) == IGT_EXIT_SUCCESS);
>  		internal_assert(0 == strcmp(DESCRIBE_ALL_OUTPUT, out));
> @@ -252,16 +185,14 @@ int main(int argc, char **argv)
>  
>  	/* describe C using a pattern */ {
>  		static char out[4096];
> -		char arg[] = "--describe=C";
> -		char *fake_argv[] = {prog, arg};
> -		int fake_argc = ARRAY_SIZE(fake_argv);
> +		strncpy(fake_arg, "--describe=C", sizeof(fake_arg));
>  
> -		pid_t pid = do_fork(fake_argc, fake_argv, &outfd, &errfd);
> +		pid = do_fork_bg_with_pipes(fake_main, &outfd, &errfd);
>  
>  		read_whole_pipe(outfd, out, sizeof(out));
>  		assert_pipe_empty(errfd);
>  
> -		internal_assert(_wait(pid, &status) != -1);
> +		internal_assert(safe_wait(pid, &status) != -1);
>  		internal_assert(WIFEXITED(status));
>  		internal_assert(WEXITSTATUS(status) == IGT_EXIT_SUCCESS);
>  		internal_assert(0 == strcmp(JUST_C_OUTPUT, out));
> @@ -272,15 +203,13 @@ int main(int argc, char **argv)
>  
>  	/* fail describing with a bad pattern */ {
>  		static char err[4096];
> -		char arg[] = "--describe=Z";
> -		char *fake_argv[] = {prog, arg};
> -		int fake_argc = ARRAY_SIZE(fake_argv);
> +		strncpy(fake_arg, "--describe=Z", sizeof(fake_arg));
>  
> -		pid_t pid = do_fork(fake_argc, fake_argv, &outfd, &errfd);
> +		pid = do_fork_bg_with_pipes(fake_main, &outfd, &errfd);
>  
>  		read_whole_pipe(errfd, err, sizeof(err));
>  
> -		internal_assert(_wait(pid, &status) != -1);
> +		internal_assert(safe_wait(pid, &status) != -1);
>  		internal_assert(WIFEXITED(status));
>  		internal_assert(WEXITSTATUS(status) == IGT_EXIT_INVALID);
>  		internal_assert(strstr(err, "Unknown subtest: Z"));
> @@ -291,15 +220,13 @@ int main(int argc, char **argv)
>  
>  	/* trying to igt_describe a dynamic subsubtest should assert */ {
>  		static char err[4096];
> -		char arg[] = "--run-subtest=G";
> -		char *fake_argv[] = {prog, arg};
> -		int fake_argc = ARRAY_SIZE(fake_argv);
> +		strncpy(fake_arg, "--run-subtest=G", sizeof(fake_arg));
>  
> -		pid_t pid = do_fork(fake_argc, fake_argv, &outfd, &errfd);
> +		pid = do_fork_bg_with_pipes(fake_main, &outfd, &errfd);
>  
>  		read_whole_pipe(errfd, err, sizeof(err));
>  
> -		internal_assert(_wait(pid, &status) != -1);
> +		internal_assert(safe_wait(pid, &status) != -1);
>  		internal_assert_wsignaled(status, SIGABRT);
>  
>  		close(outfd);
> diff --git a/lib/tests/igt_dynamic_subtests.c b/lib/tests/igt_dynamic_subtests.c
> index 606104c5..bd1e1675 100644
> --- a/lib/tests/igt_dynamic_subtests.c
> +++ b/lib/tests/igt_dynamic_subtests.c
> @@ -29,24 +29,6 @@
>  
>  #include "igt_tests_common.h"
>  
> -static int do_fork(void (*test_to_run)(void))
> -{
> -	int pid, status;
> -
> -	switch (pid = fork()) {
> -	case -1:
> -		internal_assert(0);
> -	case 0:
> -		test_to_run();
> -	default:
> -		while (waitpid(pid, &status, 0) == -1 &&
> -		       errno == EINTR)
> -			;
> -
> -		return status;
> -	}
> -}
> -
>  static void dynamic_subtest_in_normal_subtest(void)
>  {
>  	char prog[] = "igt_no_exit";
> diff --git a/lib/tests/igt_fork.c b/lib/tests/igt_fork.c
> index e30584fd..4fd0e0c8 100644
> --- a/lib/tests/igt_fork.c
> +++ b/lib/tests/igt_fork.c
> @@ -35,37 +35,52 @@
>  #include "igt_tests_common.h"
>  
>  char test[] = "test";
> -char *argv_run[] = { test };
> +char *fake_argv[] = { test };
> +int fake_argc = ARRAY_SIZE(fake_argv);
>  
>  static void igt_fork_vs_skip(void)
>  {
> +	igt_simple_init(fake_argc, fake_argv);
> +
>  	igt_fork(i, 1) {
>  		igt_skip("skipping");
>  	}
>  
>  	igt_waitchildren();
> +
> +	igt_exit();
>  }
>  
>  static void igt_fork_vs_assert(void)
>  {
> +	igt_simple_init(fake_argc, fake_argv);
> +
>  	igt_fork(i, 1) {
>  		igt_assert(0);
>  	}
>  
>  	igt_waitchildren();
> +
> +	igt_exit();
>  }
>  
>  static void igt_fork_leak(void)
>  {
> +	igt_simple_init(fake_argc, fake_argv);
> +
>  	igt_fork(i, 1) {
>  		sleep(10);
>  	}
> +
> +	igt_exit();
>  }
>  
>  static void plain_fork_leak(void)
>  {
>  	int pid;
>  
> +	igt_simple_init(fake_argc, fake_argv);
> +
>  	switch (pid = fork()) {
>  	case -1:
>  		internal_assert(0);
> @@ -74,59 +89,21 @@ static void plain_fork_leak(void)
>  	default:
>  		exit(0);
>  	}
> +
> +	igt_exit();
>  }
>  
>  static void igt_fork_timeout_leak(void)
>  {
> +	igt_simple_init(fake_argc, fake_argv);
> +
>  	igt_fork(i, 1) {
>  		sleep(10);
>  	}
>  
>  	igt_waitchildren_timeout(1, "library test");
> -}
> -
> -static int do_fork(void (*test_to_run)(void))
> -{
> -	int pid, status;
> -	int argc;
> -
> -	switch (pid = fork()) {
> -	case -1:
> -		internal_assert(0);
> -	case 0:
> -		argc = ARRAY_SIZE(argv_run);
> -		igt_simple_init(argc, argv_run);
> -		test_to_run();
> -		igt_exit();
> -	default:
> -		while (waitpid(pid, &status, 0) == -1 &&
> -		       errno == EINTR)
> -			;
> -
> -		return status;
> -	}
> -}
> -
> -static int do_subtest(void (*test_to_run)(void))
> -{
> -	int pid, status;
> -	int argc;
> -
> -	switch (pid = fork()) {
> -	case -1:
> -		internal_assert(0);
> -	case 0:
> -		argc = ARRAY_SIZE(argv_run);
> -		igt_subtest_init(argc, argv_run);
> -		test_to_run();
> -		igt_exit();
> -	default:
> -		while (waitpid(pid, &status, 0) == -1 &&
> -		       errno == EINTR)
> -			;
>  
> -		return status;
> -	}
> +	igt_exit();
>  }
>  
>  static void subtest_leak(void)
> @@ -135,6 +112,8 @@ static void subtest_leak(void)
>  		mmap(0, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
>  	const int num_children = 4096 / sizeof(*children);
>  
> +	igt_subtest_init(fake_argc, fake_argv);
> +
>  	igt_subtest("fork-leak") {
>  		igt_fork(child, num_children)
>  			children[child] = getpid();
> @@ -148,6 +127,8 @@ static void subtest_leak(void)
>  		assert(kill(children[i], 0) == -1 && errno == ESRCH);
>  
>  	munmap(children, 4096);
> +
> +	igt_exit();
>  }
>  
>  int main(int argc, char **argv)
> @@ -174,6 +155,6 @@ int main(int argc, char **argv)
>  	ret = do_fork(plain_fork_leak);
>  	internal_assert_wsignaled(ret, SIGABRT);
>  
> -	ret = do_subtest(subtest_leak);
> +	ret = do_fork(subtest_leak);
>  	internal_assert_wexited(ret, IGT_EXIT_FAILURE); /* not asserted! */
>  }
> diff --git a/lib/tests/igt_invalid_subtest_name.c b/lib/tests/igt_invalid_subtest_name.c
> index 92e767ab..32c4bcbc 100644
> --- a/lib/tests/igt_invalid_subtest_name.c
> +++ b/lib/tests/igt_invalid_subtest_name.c
> @@ -60,24 +60,6 @@ static void nonexisting_subtest(void)
>  	igt_exit();
>  }
>  
> -static int do_fork(void (*test_to_run)(void))
> -{
> -	int pid, status;
> -
> -	switch (pid = fork()) {
> -	case -1:
> -		internal_assert(0);
> -	case 0:
> -		test_to_run();
> -	default:
> -		while (waitpid(pid, &status, 0) == -1 &&
> -		       errno == EINTR)
> -			;
> -
> -		return status;
> -	}
> -}
> -
>  int main(int argc, char **argv)
>  {
>  	int ret;
> diff --git a/lib/tests/igt_no_exit.c b/lib/tests/igt_no_exit.c
> index 82f00b52..d303eba7 100644
> --- a/lib/tests/igt_no_exit.c
> +++ b/lib/tests/igt_no_exit.c
> @@ -56,24 +56,6 @@ static void no_exit(void)
>  		;
>  }
>  
> -static int do_fork(void (*test_to_run)(void))
> -{
> -	int pid, status;
> -
> -	switch (pid = fork()) {
> -	case -1:
> -		internal_assert(0);
> -	case 0:
> -		test_to_run();
> -	default:
> -		while (waitpid(pid, &status, 0) == -1 &&
> -		       errno == EINTR)
> -			;
> -
> -		return status;
> -	}
> -}
> -
>  int main(int argc, char **argv)
>  {
>  	int ret;
> diff --git a/lib/tests/igt_segfault.c b/lib/tests/igt_segfault.c
> index 0d872f67..38c040a6 100644
> --- a/lib/tests/igt_segfault.c
> +++ b/lib/tests/igt_segfault.c
> @@ -48,51 +48,38 @@
>  bool simple;
>  bool runa;
>  bool runc;
> -char test[] = "test";
> -char *argv_run[] = { test };
>  
>  static void crashme(void)
>  {
>  	raise(SIGSEGV);
>  }
>  
> -static int do_fork(void)
> +static void fake_test(void)
>  {
> -	int pid, status;
> -	int argc;
> -
> -	switch (pid = fork()) {
> -	case -1:
> -		internal_assert(0);
> -	case 0:
> -		argc = ARRAY_SIZE(argv_run);
> -		if (simple) {
> -			igt_simple_init(argc, argv_run);
> -			crashme();
> +	char prog[] = "test";
> +	char *fake_argv[] = { prog };
> +	int fake_argc = ARRAY_SIZE(fake_argv);
>  
> -			igt_exit();
> -		} else {
> -			igt_subtest_init(argc, argv_run);
>  
> -			if(runa)
> -				igt_subtest("A")
> -					;
> +	if (simple) {
> +		igt_simple_init(fake_argc, fake_argv);
> +		crashme();
>  
> -			igt_subtest("B")
> -				crashme();
> +		igt_exit();
> +	} else {
> +		igt_subtest_init(fake_argc, fake_argv);
> +		if(runa)
> +			igt_subtest("A")
> +				;
>  
> -			if(runc)
> -				igt_subtest("C")
> -					;
> +		igt_subtest("B")
> +			crashme();
>  
> -			igt_exit();
> -		}
> -	default:
> -		while (waitpid(pid, &status, 0) == -1 &&
> -		       errno == EINTR)
> -			;
> +		if(runc)
> +			igt_subtest("C")
> +				;
>  
> -		return status;
> +		igt_exit();
>  	}
>  }
>  
> @@ -104,20 +91,20 @@ int main(int argc, char **argv)
>  	runc=false;
>  	igt_info("Simple test.\n");
>  	fflush(stdout);
> -	internal_assert_wsignaled(do_fork(), SIGSEGV);
> +	internal_assert_wsignaled(do_fork(fake_test), SIGSEGV);
>  
>  	/* Test crash in a single subtest is reported */
>  	simple = false;
>  	igt_info("Single subtest.\n");
>  	fflush(stdout);
> -	internal_assert_wexited(do_fork(), SIGSEGV + 128);
> +	internal_assert_wexited(do_fork(fake_test), SIGSEGV + 128);
>  
>  	/* Test crash in a subtest following a pass is reported */
>  	simple = false;
>  	runa=true;
>  	igt_info("Passing then crashing subtest.\n");
>  	fflush(stdout);
> -	internal_assert_wexited(do_fork(), SIGSEGV + 128);
> +	internal_assert_wexited(do_fork(fake_test), SIGSEGV + 128);
>  
>  	/* Test crash in a subtest preceeding a pass is reported */
>  	simple = false;
> @@ -125,7 +112,7 @@ int main(int argc, char **argv)
>  	runc=true;
>  	igt_info("Crashing then passing subtest.\n");
>  	fflush(stdout);
> -	internal_assert_wexited(do_fork(), SIGSEGV + 128);
> +	internal_assert_wexited(do_fork(fake_test), SIGSEGV + 128);
>  
>  	return 0;
>  }
> diff --git a/lib/tests/igt_simulation.c b/lib/tests/igt_simulation.c
> index 3f3cd88f..a0ea7000 100644
> --- a/lib/tests/igt_simulation.c
> +++ b/lib/tests/igt_simulation.c
> @@ -40,59 +40,44 @@ bool list_subtests;
>  bool in_fixture;
>  bool in_subtest;
>  
> -char test[] = "test";
> -char list[] = "--list-subtests";
> -char *argv_list[] = { test, list };
> -char *argv_run[] = { test };
> -
> -static int do_fork(void)
> +static void fake_test(void)
>  {
> -	int pid, status;
> +	char test[] = "test";
> +	char list[] = "--list-subtests";
> +	char *argv_list[] = { test, list };
> +	char *argv_run[] = { test };
>  	int argc;
>  
> -	switch (pid = fork()) {
> -	case -1:
> -		internal_assert(0);
> -	case 0:
> -		if (simple) {
> -			argc = 1;
> -			igt_simple_init(argc, argv_run);
> +	if (simple) {
> +		argc = 1;
> +		igt_simple_init(argc, argv_run);
>  
> -			igt_skip_on_simulation();
> +		igt_skip_on_simulation();
>  
> -			igt_exit();
> +		igt_exit();
> +	} else {
> +		if (list_subtests) {
> +			argc = 2;
> +			igt_subtest_init(argc, argv_list);
>  		} else {
> -			if (list_subtests) {
> -				argc = 2;
> -				igt_subtest_init(argc, argv_list);
> -			} else {
> -				argc = 1;
> -				igt_subtest_init(argc, argv_run);
> -			}
> -
> -			if (in_fixture) {
> -				igt_fixture
> -					igt_skip_on_simulation();
> -			} if (in_subtest) {
> -				igt_subtest("sim")
> -					igt_skip_on_simulation();
> -			} else
> -				igt_skip_on_simulation();
> -
> -			if (!in_subtest)
> -				igt_subtest("foo")
> -					;
> -
> -			igt_exit();
> +			argc = 1;
> +			igt_subtest_init(argc, argv_run);
>  		}
> -	default:
> -		while (waitpid(pid, &status, 0) == -1 &&
> -		       errno == EINTR)
> -			;
>  
> -		internal_assert(WIFEXITED(status));
> +		if (in_fixture) {
> +			igt_fixture
> +				igt_skip_on_simulation();
> +		} if (in_subtest) {
> +			igt_subtest("sim")
> +				igt_skip_on_simulation();
> +		} else
> +			igt_skip_on_simulation();
> +
> +		if (!in_subtest)
> +			igt_subtest("foo")
> +				;
>  
> -		return status;
> +		igt_exit();
>  	}
>  }
>  
> @@ -101,10 +86,10 @@ int main(int argc, char **argv)
>  	/* simple tests */
>  	simple = true;
>  	internal_assert(setenv("INTEL_SIMULATION", "1", 1) == 0);
> -	internal_assert(WEXITSTATUS(do_fork()) == IGT_EXIT_SKIP);
> +	internal_assert(WEXITSTATUS(do_fork(fake_test)) == IGT_EXIT_SKIP);
>  
>  	internal_assert(setenv("INTEL_SIMULATION", "0", 1) == 0);
> -	internal_assert(WEXITSTATUS(do_fork()) == IGT_EXIT_SUCCESS);
> +	internal_assert(WEXITSTATUS(do_fork(fake_test)) == IGT_EXIT_SUCCESS);
>  
>  	/* subtests, list mode */
>  	simple = false;
> @@ -112,28 +97,28 @@ int main(int argc, char **argv)
>  
>  	in_fixture = false;
>  	internal_assert(setenv("INTEL_SIMULATION", "1", 1) == 0);
> -	internal_assert(WEXITSTATUS(do_fork()) == IGT_EXIT_SUCCESS);
> +	internal_assert(WEXITSTATUS(do_fork(fake_test)) == IGT_EXIT_SUCCESS);
>  
>  	internal_assert(setenv("INTEL_SIMULATION", "0", 1) == 0);
> -	internal_assert(WEXITSTATUS(do_fork()) == IGT_EXIT_SUCCESS);
> +	internal_assert(WEXITSTATUS(do_fork(fake_test)) == IGT_EXIT_SUCCESS);
>  
>  	in_fixture = true;
>  	internal_assert(setenv("INTEL_SIMULATION", "1", 1) == 0);
> -	internal_assert(WEXITSTATUS(do_fork()) == IGT_EXIT_SUCCESS);
> +	internal_assert(WEXITSTATUS(do_fork(fake_test)) == IGT_EXIT_SUCCESS);
>  
>  
>  	internal_assert(setenv("INTEL_SIMULATION", "0", 1) == 0);
> -	internal_assert(WEXITSTATUS(do_fork()) == IGT_EXIT_SUCCESS);
> +	internal_assert(WEXITSTATUS(do_fork(fake_test)) == IGT_EXIT_SUCCESS);
>  
>  
>  	in_fixture = false;
>  	in_subtest = true;
>  	internal_assert(setenv("INTEL_SIMULATION", "1", 1) == 0);
> -	internal_assert(WEXITSTATUS(do_fork()) == IGT_EXIT_SUCCESS);
> +	internal_assert(WEXITSTATUS(do_fork(fake_test)) == IGT_EXIT_SUCCESS);
>  
>  
>  	internal_assert(setenv("INTEL_SIMULATION", "0", 1) == 0);
> -	internal_assert(WEXITSTATUS(do_fork()) == IGT_EXIT_SUCCESS);
> +	internal_assert(WEXITSTATUS(do_fork(fake_test)) == IGT_EXIT_SUCCESS);
>  
>  
>  	/* subtest, run mode */
> @@ -142,29 +127,29 @@ int main(int argc, char **argv)
>  
>  	in_fixture = false;
>  	internal_assert(setenv("INTEL_SIMULATION", "1", 1) == 0);
> -	internal_assert(WEXITSTATUS(do_fork()) == IGT_EXIT_SKIP);
> +	internal_assert(WEXITSTATUS(do_fork(fake_test)) == IGT_EXIT_SKIP);
>  
>  	internal_assert(setenv("INTEL_SIMULATION", "0", 1) == 0);
> -	internal_assert(WEXITSTATUS(do_fork()) == IGT_EXIT_SUCCESS);
> +	internal_assert(WEXITSTATUS(do_fork(fake_test)) == IGT_EXIT_SUCCESS);
>  
>  
>  	in_fixture = true;
>  	internal_assert(setenv("INTEL_SIMULATION", "1", 1) == 0);
> -	internal_assert(WEXITSTATUS(do_fork()) == IGT_EXIT_SKIP);
> +	internal_assert(WEXITSTATUS(do_fork(fake_test)) == IGT_EXIT_SKIP);
>  
>  
>  	internal_assert(setenv("INTEL_SIMULATION", "0", 1) == 0);
> -	internal_assert(WEXITSTATUS(do_fork()) == IGT_EXIT_SUCCESS);
> +	internal_assert(WEXITSTATUS(do_fork(fake_test)) == IGT_EXIT_SUCCESS);
>  
>  
>  	in_fixture = false;
>  	in_subtest = true;
>  	internal_assert(setenv("INTEL_SIMULATION", "1", 1) == 0);
> -	internal_assert(WEXITSTATUS(do_fork()) == IGT_EXIT_SKIP);
> +	internal_assert(WEXITSTATUS(do_fork(fake_test)) == IGT_EXIT_SKIP);
>  
>  
>  	internal_assert(setenv("INTEL_SIMULATION", "0", 1) == 0);
> -	internal_assert(WEXITSTATUS(do_fork()) == IGT_EXIT_SUCCESS);
> +	internal_assert(WEXITSTATUS(do_fork(fake_test)) == IGT_EXIT_SUCCESS);
>  
>  
>  	return 0;
> diff --git a/lib/tests/igt_tests_common.h b/lib/tests/igt_tests_common.h
> index e66ee37c..b3da3b34 100644
> --- a/lib/tests/igt_tests_common.h
> +++ b/lib/tests/igt_tests_common.h
> @@ -26,6 +26,8 @@
>  #define IGT_LIB_TESTS_COMMON_H
>  
>  #include <assert.h>
> +#include <sys/wait.h>
> +#include <errno.h>
>  
>  /*
>   * We need to hide assert from the cocci igt test refactor spatch.
> @@ -46,4 +48,93 @@ static inline void internal_assert_wsignaled(int wstatus, int signal)
>  	internal_assert(WIFSIGNALED(wstatus) &&
>  			WTERMSIG(wstatus) == signal);
>  }
> +
> +static inline int do_fork(void (*test_to_run)(void))
> +{
> +	int pid, status;
> +
> +	switch (pid = fork()) {
> +	case -1:
> +		internal_assert(0);
> +	case 0:
> +		test_to_run();
> +	default:
> +		while (waitpid(pid, &status, 0) == -1 &&
> +		       errno == EINTR)
> +			;
> +
> +		return status;
> +	}
> +}
> +
> +static inline pid_t do_fork_bg_with_pipes(void (*test_to_run)(void), int *out, int *err)
> +{
> +	int outfd[2], errfd[2];
> +	pid_t pid;
> +
> +	internal_assert(pipe(outfd) != -1);
> +	internal_assert(pipe(errfd) != -1);
> +
> +	pid = fork();
> +	internal_assert(pid != -1);
> +
> +	if (pid == 0) {
> +		while (dup2(outfd[1], STDOUT_FILENO) == -1 && errno == EINTR) {}
> +		while (dup2(errfd[1], STDERR_FILENO) == -1 && errno == EINTR) {}
> +
> +		close(outfd[0]);
> +		close(outfd[1]);
> +		close(errfd[0]);
> +		close(errfd[1]);
> +
> +		test_to_run();
> +
> +		exit(-1);
> +	} else {
> +		/* close the writing ends */
> +		close(outfd[1]);
> +		close(errfd[1]);
> +
> +		*out = outfd[0];
> +		*err = errfd[0];
> +
> +		return pid;
> +	}
> +}
> +
> +static inline int safe_wait(pid_t pid, int *status) {
> +	int ret;
> +
> +	do {
> +		ret = waitpid(pid, status, 0);
> +	} while (ret == -1 && errno == EINTR);
> +
> +	return ret;
> +}
> +
> +static inline void assert_pipe_empty(int fd)
> +{
> +	char buf[5];
> +	internal_assert(0 == read(fd, buf, sizeof(buf)));
> +}
> +
> +static inline void read_whole_pipe(int fd, char *buf, size_t buflen)
> +{
> +	ssize_t readlen;
> +	off_t offset;
> +
> +	offset = 0;
> +	while ((readlen = read(fd, buf+offset, buflen-offset))) {
> +		if (readlen == -1) {
> +			if (errno == EINTR) {
> +				continue;
> +			} else {
> +				printf("read failed with %s\n", strerror(errno));
> +				exit(1);
> +			}
> +		}
> +		internal_assert(readlen != -1);
> +		offset += readlen;
> +	}
> +}
>  #endif
> -- 
> 2.24.1
> 


More information about the igt-dev mailing list