All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arkadiusz Hiler <arkadiusz.hiler@intel.com>
To: igt-dev@lists.freedesktop.org
Cc: Petri Latvala <petri.latvala@intel.com>
Subject: [igt-dev] [PATCH i-g-t 1/9] lib/tests: Extract fork helpers
Date: Tue, 25 Feb 2020 18:52:38 +0200	[thread overview]
Message-ID: <20200225165246.213606-1-arkadiusz.hiler@intel.com> (raw)

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@intel.com>
Reviewed-by: Petri Latvala <petri.latvala@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

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

             reply	other threads:[~2020-02-25 16:53 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-25 16:52 Arkadiusz Hiler [this message]
2020-02-25 16:52 ` [igt-dev] [PATCH i-g-t 2/9] lib/tests: Add support for redirecting fork output to /dev/null Arkadiusz Hiler
2020-02-25 16:55 ` [igt-dev] [PATCH i-g-t 3/9] lib: Make it possible to abort the whole execution from inside of a test Arkadiusz Hiler
2020-02-25 16:55 ` [igt-dev] [PATCH i-g-t 4/9] runner/runner_tests: Extract helper for inspecting test result Arkadiusz Hiler
2020-02-25 16:55 ` [igt-dev] [PATCH i-g-t 5/9] runner: Abort the run when test exits with IGT_EXIT_ABORT Arkadiusz Hiler
2020-02-25 16:56 ` [igt-dev] [PATCH i-g-t 6/9] lib/chamelium: Clear error after checking if chamelium is reachable Arkadiusz Hiler
2020-02-25 16:56 ` [igt-dev] [PATCH i-g-t 7/9] lib/chamelium: Make it clear that function asserts Arkadiusz Hiler
2020-02-25 16:57 ` [igt-dev] [PATCH i-g-t 8/9] lib/chamelium: Add functions to initialize XMLRPC only Arkadiusz Hiler
2020-02-25 16:57 ` [igt-dev] [PATCH i-g-t 9/9] lib/kms: Try to plug all Chamelium ports, abort if it fails Arkadiusz Hiler
2020-02-26 10:31 ` [igt-dev] ✗ GitLab.Pipeline: failure for series starting with [i-g-t,1/9] lib/tests: Extract fork helpers Patchwork
2020-02-26 12:15 ` [igt-dev] ✓ Fi.CI.BAT: success " Patchwork
2020-02-26 18:49 ` [igt-dev] ✗ Fi.CI.IGT: failure " Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2020-02-12 13:21 [igt-dev] [PATCH i-g-t 0/9] Abort on Chamelium failure Arkadiusz Hiler
2020-02-12 13:21 ` [igt-dev] [PATCH i-g-t 1/9] lib/tests: Extract fork helpers Arkadiusz Hiler
2020-02-14 11:57   ` Petri Latvala

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200225165246.213606-1-arkadiusz.hiler@intel.com \
    --to=arkadiusz.hiler@intel.com \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=petri.latvala@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.