Tarantool development patches archive
 help / color / mirror / Atom feed
From: Cyrill Gorcunov <gorcunov@gmail.com>
To: Alexander Turenko <alexander.turenko@tarantool.org>
Cc: tml <tarantool-patches@dev.tarantool.org>
Subject: [Tarantool-patches] [PATCH v2 2/2] test: unit/popen -- provide a child process
Date: Thu, 26 Mar 2020 11:31:22 +0300	[thread overview]
Message-ID: <20200326083122.GN3197@uranus> (raw)
In-Reply-To: <20200326004737.nu4dcii7zpwesrsp@tkn_work_nb>

Testing via plain C interface with a shell is not stable,
the shell might simply be misconfigured or not found and
we will simply stuck forever (the signal handling in libev
is tricky and requires at least idle cycles or similar to
pass event processing). Thus lets rather run a program we
know is presenting in the system (popen-child executable).

Fixes #4811

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
---
 - fixed comments
 - add entry into .gitignore
 - read/write in a loop

pushed into branch gorcunov/gh-4811-popen-coio-3

 .gitignore               |   1 +
 test/unit/CMakeLists.txt |   4 ++
 test/unit/popen-child.c  | 123 +++++++++++++++++++++++++++++++++++++++
 test/unit/popen.c        |  28 ++++++---
 4 files changed, 148 insertions(+), 8 deletions(-)
 create mode 100644 test/unit/popen-child.c

diff --git a/.gitignore b/.gitignore
index e9508fc43..cda28d79f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -92,6 +92,7 @@ test/unit/fiob
 test/small
 test/var
 test/luajit-tap
+test/unit/popen-child
 third_party/luajit/src/luajit
 third_party/luajit/lib/vmdef.lua
 third_party/luajit/src/buildvm
diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
index bc6aebdcb..e1d506f58 100644
--- a/test/unit/CMakeLists.txt
+++ b/test/unit/CMakeLists.txt
@@ -246,5 +246,9 @@ target_link_libraries(swim_errinj.test unit swim)
 add_executable(merger.test merger.test.c)
 target_link_libraries(merger.test unit core box)
 
+#
+# Client for popen.test
+add_executable(popen-child popen-child.c)
+
 add_executable(popen.test popen.c)
 target_link_libraries(popen.test misc unit core)
diff --git a/test/unit/popen-child.c b/test/unit/popen-child.c
new file mode 100644
index 000000000..d11c4258a
--- /dev/null
+++ b/test/unit/popen-child.c
@@ -0,0 +1,123 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+static ssize_t
+read_safe(int pfd, char *dest, ssize_t bytes)
+{
+	ssize_t left = bytes;
+	ssize_t off = 0;
+
+	while (left > 0) {
+		ssize_t nr = read(pfd, &dest[off], left);
+		printf("read %zd", nr);
+		if (nr < 0) {
+			if (errno == EAGAIN ||
+			    errno == EWOULDBLOCK ||
+			    errno == EINTR)
+				continue;
+			return nr;
+		} else if (nr == 0) {
+			break;
+		}
+
+		off += nr;
+		left -= nr;
+	}
+
+	return off;
+}
+
+static ssize_t
+write_safe(int pfd, char *dest, ssize_t bytes)
+{
+	ssize_t left = bytes;
+	ssize_t off = 0;
+
+	while (left > 0) {
+		ssize_t nr = write(pfd, &dest[off], left);
+		if (nr < 0) {
+			if (errno == EAGAIN ||
+			    errno == EWOULDBLOCK ||
+			    errno == EINTR)
+				continue;
+			return nr;
+		} else if (nr == 0) {
+			break;
+		}
+
+		off += nr;
+		left -= nr;
+	}
+
+	return off;
+}
+
+int
+main(int argc, char *argv[])
+{
+	char buf[1024];
+
+	if (argc < 2) {
+		fprintf(stderr, "Not enough args\n");
+		exit(1);
+	}
+
+	/* read -n X and the just echo data read */
+	if (!strcmp(argv[1], "read") &&
+	    !strcmp(argv[2], "-n")) {
+		ssize_t nr = (ssize_t)atoi(argv[3]);
+		if (nr <= 0) {
+			fprintf(stderr, "Wrong number of args\n");
+			exit(1);
+		}
+
+		if (nr >= (ssize_t)sizeof(buf)) {
+			fprintf(stderr, "Too many bytes to read\n");
+			exit(1);
+		}
+
+		ssize_t n = read_safe(STDIN_FILENO, buf, nr);
+		if (n != nr) {
+			fprintf(stderr, "Can't read from stdin\n");
+			exit(1);
+		}
+
+		n = write_safe(STDOUT_FILENO, buf, nr);
+		if (n != nr) {
+			fprintf(stderr, "Can't write to stdout\n");
+			exit(1);
+		}
+
+		exit(0);
+	}
+
+	/* just echo the data */
+	if (!strcmp(argv[1], "echo")) {
+		ssize_t nr = (ssize_t)strlen(argv[2]) + 1;
+		if (nr <= 0) {
+			fprintf(stderr, "Wrong number of bytes\n");
+			exit(1);
+		}
+
+		ssize_t n = write_safe(STDOUT_FILENO, argv[2], nr);
+		if (n != nr) {
+			fprintf(stderr, "Can't write to stdout\n");
+			exit(1);
+		}
+
+		exit(0);
+	}
+
+	/* just sleep forever */
+	if (!strcmp(argv[1], "loop")) {
+		for (;;)
+			sleep(10);
+		exit(0);
+	}
+
+	fprintf(stderr, "Unknown command passed\n");
+	return 1;
+}
diff --git a/test/unit/popen.c b/test/unit/popen.c
index a40ca514c..caea9d552 100644
--- a/test/unit/popen.c
+++ b/test/unit/popen.c
@@ -11,9 +11,10 @@
 #include "popen.h"
 #include "say.h"
 
+static char popen_child_path[PATH_MAX];
+
 #define TEST_POPEN_COMMON_FLAGS			\
 	(POPEN_FLAG_SETSID		|	\
-	POPEN_FLAG_SHELL		|	\
 	POPEN_FLAG_RESTORE_SIGNALS)
 
 /**
@@ -40,8 +41,8 @@ popen_write_exit(void)
 {
 	struct popen_handle *handle;
 	char *child_argv[] = {
-		"/bin/sh", "-c",
-		"prompt=''; read -n 5 prompt; echo $prompt",
+		popen_child_path,
+		"read", "-n", "5",
 		NULL,
 	};
 
@@ -108,8 +109,8 @@ popen_read_exit(void)
 {
 	struct popen_handle *handle;
 	char *child_argv[] = {
-		"/bin/sh", "-c",
-		"echo 1 2 3 4 5",
+		popen_child_path,
+		"echo", "1 2 3 4 5",
 		NULL,
 	};
 
@@ -165,8 +166,8 @@ popen_kill(void)
 {
 	struct popen_handle *handle;
 	char *child_argv[] = {
-		"/bin/sh", "-c",
-		"while [ 1 ]; do sleep 10; done",
+		popen_child_path,
+		"loop",
 		NULL,
 	};
 
@@ -234,9 +235,20 @@ main_f(va_list ap)
 int
 main(int argc, char *argv[])
 {
-	//say_logger_init(NULL, S_DEBUG, 0, "plain", 0);
+#if 0
+	say_logger_init(NULL, S_DEBUG, 0, "plain", 0);
+#endif
 	memory_init();
 
+	if (getenv("BUILDDIR") == NULL) {
+		size_t size = sizeof(popen_child_path);
+		strncpy(popen_child_path, "./test/unit/popen-child", size);
+		popen_child_path[size-1] = '\0';
+	} else {
+		snprintf(popen_child_path, sizeof(popen_child_path),
+			 "%s/test/unit/popen-child", getenv("BUILDDIR"));
+	}
+
 	fiber_init(fiber_c_invoke);
 	popen_init();
 	coio_init();
-- 
2.20.1

  parent reply	other threads:[~2020-03-26  8:31 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-24 10:03 [Tarantool-patches] [PATCH 0/2] popen: fix unit test Cyrill Gorcunov
2020-03-24 10:03 ` [Tarantool-patches] [PATCH 1/2] popen: do not require space for shell args Cyrill Gorcunov
2020-03-26  0:23   ` Alexander Turenko
2020-03-24 10:03 ` [Tarantool-patches] [PATCH 2/2] test: unit/popen -- provide a child process Cyrill Gorcunov
2020-03-26  0:47   ` Alexander Turenko
2020-03-26  0:59     ` Nikita Pettik
2020-03-26  8:31     ` Cyrill Gorcunov [this message]
2020-03-26  9:04       ` [Tarantool-patches] [PATCH v2 " Cyrill Gorcunov
2020-03-24 10:04 ` [Tarantool-patches] [PATCH 0/2] popen: fix unit test Cyrill Gorcunov
2020-03-26  0:52 ` Alexander Turenko
2020-03-26 11:57 ` Kirill Yukhin

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=20200326083122.GN3197@uranus \
    --to=gorcunov@gmail.com \
    --cc=alexander.turenko@tarantool.org \
    --cc=tarantool-patches@dev.tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH v2 2/2] test: unit/popen -- provide a child process' \
    /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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox