All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ben Hutchings <bhutchings@solarflare.com>
To: <netdev@vger.kernel.org>
Cc: <linux-net-drivers@solarflare.com>
Subject: [PATCH ethtool 20/21] Run tests in-process
Date: Tue, 1 Nov 2011 23:23:46 +0000	[thread overview]
Message-ID: <1320189826.2758.52.camel@bwh-desktop> (raw)
In-Reply-To: <1320186901.2758.30.camel@bwh-desktop>

Change definition of main() and use of exit() so that ethtool commands
can be tested without starting a new process.  This will allow deeper
testing that covers ioctl requests and responses.

Fix the obvious socket and memory leaks.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 Makefile.am    |    6 +---
 ethtool.c      |   25 +++++++++++++-------
 internal.h     |    5 ++++
 test-cmdline.c |    6 +++++
 test-common.c  |   65 +++++++++++++++++++++++++++++++------------------------
 5 files changed, 66 insertions(+), 41 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 4b0eb17..cfc2b79 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,11 +12,9 @@ ethtool_SOURCES = ethtool.c ethtool-copy.h internal.h \
 		  rxclass.c
 
 TESTS = test-cmdline
-check_PROGRAMS = test-cmdline test-one-cmdline
-test_cmdline_SOURCES = test-cmdline.c test-common.c
+check_PROGRAMS = test-cmdline
+test_cmdline_SOURCES = test-cmdline.c test-common.c $(ethtool_SOURCES) 
 test_cmdline_CFLAGS = -DTEST_ETHTOOL
-test_one_cmdline_SOURCES = $(ethtool_SOURCES)
-test_one_cmdline_CFLAGS = -DTEST_ETHTOOL
 
 dist-hook:
 	cp $(top_srcdir)/ethtool.spec $(distdir)
diff --git a/ethtool.c b/ethtool.c
index 8e757e9..f192376 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -259,7 +259,7 @@ static void exit_bad_args(void)
 	fprintf(stderr,
 		"ethtool: bad command line argument(s)\n"
 		"For more information run ethtool -h\n");
-	exit(1);
+	ethtool_exit(1);
 }
 
 static int show_usage(struct cmd_context *ctx)
@@ -2754,6 +2754,7 @@ static int do_grxfhindir(struct cmd_context *ctx)
 	err = send_ioctl(ctx, indir);
 	if (err < 0) {
 		perror("Cannot get RX flow hash indirection table");
+		free(indir);
 		return 103;
 	}
 
@@ -2766,6 +2767,8 @@ static int do_grxfhindir(struct cmd_context *ctx)
 		if (i % 8 == 7)
 			fputc('\n', stdout);
 	}
+
+	free(indir);
 	return 0;
 }
 
@@ -2817,14 +2820,16 @@ static int do_srxfhindir(struct cmd_context *ctx)
 		if (sum == 0) {
 			fprintf(stderr,
 				"At least one weight must be non-zero\n");
-			exit(1);
+			free(indir);
+			ethtool_exit(1);
 		}
 
 		if (sum > indir->size) {
 			fprintf(stderr,
 				"Total weight exceeds the size of the "
 				"indirection table\n");
-			exit(1);
+			free(indir);
+			ethtool_exit(1);
 		}
 
 		j = -1;
@@ -2844,6 +2849,7 @@ static int do_srxfhindir(struct cmd_context *ctx)
 		return 105;
 	}
 
+	free(indir);
 	return 0;
 }
 
@@ -3199,18 +3205,15 @@ static int do_setfwdump(struct cmd_context *ctx)
 	return 0;
 }
 
+#ifndef TEST_ETHTOOL
 int send_ioctl(struct cmd_context *ctx, void *cmd)
 {
-#ifndef TEST_ETHTOOL
 	ctx->ifr.ifr_data = cmd;
 	return ioctl(ctx->fd, SIOCETHTOOL, &ctx->ifr);
-#else
-	/* If we get this far then parsing succeeded */
-	exit(0);
-#endif
 }
+#endif
 
-int main(int argc, char **argp, char **envp)
+int ethtool_main(int argc, char **argp)
 {
 	int (*func)(struct cmd_context *);
 	int want_device;
@@ -3265,12 +3268,16 @@ opt_found:
 		memset(&ctx.ifr, 0, sizeof(ctx.ifr));
 		strcpy(ctx.ifr.ifr_name, ctx.devname);
 
+#ifndef TEST_ETHTOOL
 		/* Open control socket. */
 		ctx.fd = socket(AF_INET, SOCK_DGRAM, 0);
 		if (ctx.fd < 0) {
 			perror("Cannot get control socket");
 			return 70;
 		}
+#else
+		ctx.fd = -1;
+#endif
 	} else {
 		ctx.fd = -1;
 	}
diff --git a/internal.h b/internal.h
index cb126b3..8505396 100644
--- a/internal.h
+++ b/internal.h
@@ -98,7 +98,12 @@ struct cmd_context {
 };
 
 #ifdef TEST_ETHTOOL
+int ethtool_main(int argc, char **argp);
+void ethtool_exit(int rc) __attribute__((noreturn));
 int test_cmdline(const char *args);
+#else
+#define ethtool_main(...) main(__VA_ARGS__)
+#define ethtool_exit(rc) exit(rc)
 #endif
 
 int send_ioctl(struct cmd_context *ctx, void *cmd);
diff --git a/test-cmdline.c b/test-cmdline.c
index 7dd3b7c..df1aeed 100644
--- a/test-cmdline.c
+++ b/test-cmdline.c
@@ -213,6 +213,12 @@ static struct test_case {
 	{ 1, "-0" },
 };
 
+int send_ioctl(struct cmd_context *ctx, void *cmd)
+{
+	/* If we get this far then parsing succeeded */
+	ethtool_exit(0);
+}
+
 int main(void)
 {
 	struct test_case *tc;
diff --git a/test-common.c b/test-common.c
index 4ea84c8..5a06ac7 100644
--- a/test-common.c
+++ b/test-common.c
@@ -7,22 +7,27 @@
  * by the Free Software Foundation, incorporated herein by reference.
  */
 
+#include <setjmp.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/fcntl.h>
-#include <sys/wait.h>
 #include <unistd.h>
 #include "internal.h"
 
+static jmp_buf test_return;
+
+void ethtool_exit(int rc)
+{
+	longjmp(test_return, rc + 1);
+}
+
 int test_cmdline(const char *args)
 {
 	int argc, i;
 	char **argv;
 	const char *arg;
 	size_t len;
-	pid_t pid;
-	int dev_null;
-	int status;
+	int dev_null = -1, old_stdout = -1, old_stderr = -1;
 	int rc;
 
 	/* Convert line to argv */
@@ -56,35 +61,39 @@ int test_cmdline(const char *args)
 	}
 
 	fflush(NULL);
-	pid = fork();
-
-	/* Child */
-	if (pid == 0) {
-		dup2(dev_null, STDIN_FILENO);
-		if (!getenv("ETHTOOL_TEST_VERBOSE")) {
-			dup2(dev_null, STDOUT_FILENO);
-			dup2(dev_null, STDERR_FILENO);
+	dup2(dev_null, STDIN_FILENO);
+	if (!getenv("ETHTOOL_TEST_VERBOSE")) {
+		old_stdout = dup(STDOUT_FILENO);
+		if (old_stdout < 0) {
+			perror("dup stdout");
+			rc = -1;
+			goto out;
 		}
-		execv("./test-one-cmdline", argv);
-		_exit(126);
+		dup2(dev_null, STDOUT_FILENO);
+		old_stderr = dup(STDERR_FILENO);
+		if (old_stderr < 0) {
+			perror("dup stderr");
+			rc = -1;
+			goto out;
+		}
+		dup2(dev_null, STDERR_FILENO);
 	}
 
-	/* Parent */
-	if (pid < 0) {
-		perror("fork");
-		close(dev_null);
-		rc = -1;
-		goto out;
-	}
-	close(dev_null);
-	if (waitpid(pid, &status, 0) < 0) {
-		perror("waitpid");
-		rc = -1;
-		goto out;
-	}
-	rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
+	rc = setjmp(test_return);
+	rc = rc ? rc - 1 : ethtool_main(argc, argv);
 
 out:
+	fflush(NULL);
+	if (old_stderr >= 0) {
+		dup2(old_stderr, STDERR_FILENO);
+		close(old_stderr);
+	}
+	if (old_stdout >= 0) {
+		dup2(old_stdout, STDOUT_FILENO);
+		close(old_stdout);
+	}
+	if (dev_null >= 0)
+		close(dev_null);
 	for (i = 0; i < argc; i++)
 		free(argv[i]);
 	free(argv);
-- 
1.7.4.4



-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

  parent reply	other threads:[~2011-11-01 23:23 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-11-01 22:35 [PATCH ethtool 00/21] ethtool refactoring and misc changes Ben Hutchings
2011-11-01 23:13 ` [PATCH ethtool 01/21] Report pause frame autonegotiation result Ben Hutchings
2011-11-01 23:13 ` [PATCH ethtool 02/21] ethtool.8: Fix initial blank line/page Ben Hutchings
2011-11-01 23:14 ` [PATCH ethtool 03/21] Combine ethtool-{bitops,util}.h into internal.h Ben Hutchings
2011-11-01 23:14 ` [PATCH ethtool 04/21] Fix type of bit-number parameter to set_bit() and clear_bit() Ben Hutchings
2011-11-01 23:15 ` [PATCH ethtool 05/21] ethtool.8: Change device name metavariable from 'ethX' to 'devname' Ben Hutchings
2011-11-01 23:15 ` [PATCH ethtool 06/21] ethtool.8: Allow line-break in description of parameters after -N Ben Hutchings
2011-11-01 23:15 ` [PATCH ethtool 07/21] Fix format of help text for -f option Ben Hutchings
2011-11-01 23:15 ` [PATCH ethtool 08/21] Use standard indentation for definition of struct option args Ben Hutchings
2011-11-01 23:16 ` [PATCH ethtool 09/21] Encapsulate command context in a structure Ben Hutchings
2011-11-01 23:17 ` [PATCH ethtool 10/21] Add test cases for command-line parsing Ben Hutchings
2011-11-01 23:17 ` [PATCH ethtool 11/21] Add more " Ben Hutchings
2011-11-01 23:18 ` [PATCH ethtool 12/21] Move argument parsing to sub-command functions Ben Hutchings
2011-11-01 23:18 ` [PATCH ethtool 13/21] Support arbitrary numbers of option names for each mode Ben Hutchings
2011-11-01 23:18 ` [PATCH ethtool 14/21] Fix reference to cmdline_ring in do_schannels() Ben Hutchings
2011-11-01 23:19 ` [PATCH ethtool 15/21] Convert cmdline_msglvl into array of named flags; convert back at run-time Ben Hutchings
2011-11-01 23:20 ` [PATCH ethtool 16/21] Replace global devname variable with a field in struct cmd_context Ben Hutchings
2011-11-01 23:21 ` [PATCH ethtool 17/21] Change most static global variables into automatic variables Ben Hutchings
2011-11-01 23:22 ` [PATCH ethtool 18/21] rxclass: Replace global rmgr with automatic variable/parameter Ben Hutchings
2011-11-01 23:22 ` [PATCH ethtool 19/21] Declare static variables const as appropriate Ben Hutchings
2011-11-01 23:23 ` Ben Hutchings [this message]
2011-11-02 20:25   ` [PATCH ethtool 20/21] Run tests in-process Ben Hutchings
2011-11-01 23:24 ` [PATCH ethtool 21/21] Rearrange definitions and remove unnecessary forward declarations Ben Hutchings
2011-11-03 19:17 ` [PATCH ethtool 00/21] ethtool refactoring and misc changes Ben Hutchings

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=1320189826.2758.52.camel@bwh-desktop \
    --to=bhutchings@solarflare.com \
    --cc=linux-net-drivers@solarflare.com \
    --cc=netdev@vger.kernel.org \
    /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.