From bf3e19afbf1b05cb8ce58050fba1f892e85da099 Mon Sep 17 00:00:00 2001
From: Barath Raghavan <barath@google.com>
Date: Mon, 1 Jul 2013 15:00:40 -0700
Subject: [PATCH] net-test: Adds the --dry_run flag to packetdrill to verify
 but not start a run.

The --dry_run command line flag causes packetdrill to verify command
line args, load and parse the given script, but not execute it. If any
errors are found during these steps, packetdrill will print an error
as before.  Otherwise, it will exit(0) and produce no output.

Change-Id: Ibf4502c6ea326539346a58b58d7feb29d4b3da69
---
 gtests/net/packetdrill/config.c      |  6 ++++++
 gtests/net/packetdrill/config.h      |  3 ++-
 gtests/net/packetdrill/packetdrill.c |  4 ++++
 gtests/net/packetdrill/parser.y      | 10 +++++-----
 4 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/gtests/net/packetdrill/config.c b/gtests/net/packetdrill/config.c
index 5abe1b23..a286b265 100644
--- a/gtests/net/packetdrill/config.c
+++ b/gtests/net/packetdrill/config.c
@@ -57,6 +57,7 @@ enum option_codes {
 	OPT_WIRE_SERVER_DEV,
 	OPT_TCP_TS_TICK_USECS,
 	OPT_NON_FATAL,
+	OPT_DRY_RUN,
 	OPT_VERBOSE = 'v',	/* our only single-letter option */
 };
 
@@ -84,6 +85,7 @@ struct option options[] = {
 	{ "wire_server_dev",	.has_arg = true,  NULL, OPT_WIRE_SERVER_DEV },
 	{ "tcp_ts_tick_usecs",	.has_arg = true,  NULL, OPT_TCP_TS_TICK_USECS },
 	{ "non_fatal",		.has_arg = true,  NULL, OPT_NON_FATAL },
+	{ "dry_run",		.has_arg = false, NULL, OPT_DRY_RUN },
 	{ "verbose",		.has_arg = false, NULL, OPT_VERBOSE },
 	{ NULL },
 };
@@ -113,6 +115,7 @@ void show_usage(void)
 		"\t[--wire_server_port=<server_port>]\n"
 		"\t[--wire_client_dev=<eth_dev_name>]\n"
 		"\t[--wire_server_dev=<eth_dev_name>]\n"
+		"\t[--dry_run]\n"
 		"\t[--verbose|-v]\n"
 		"\tscript_path ...\n");
 }
@@ -443,6 +446,9 @@ static void process_option(int opt, char *optarg, struct config *config,
 	case OPT_WIRE_SERVER_DEV:
 		config->wire_server_device = strdup(optarg);
 		break;
+	case OPT_DRY_RUN:
+		config->dry_run = true;
+		break;
 	case OPT_VERBOSE:
 		config->verbose = true;
 		break;
diff --git a/gtests/net/packetdrill/config.h b/gtests/net/packetdrill/config.h
index 79518285..55190ce1 100644
--- a/gtests/net/packetdrill/config.h
+++ b/gtests/net/packetdrill/config.h
@@ -78,6 +78,8 @@ struct config {
 	bool non_fatal_packet;		/* treat packet asserts as non-fatal */
 	bool non_fatal_syscall;		/* treat syscall asserts as non-fatal */
 
+	bool dry_run;			/* parse script but don't execute? */
+
 	bool verbose;			/* print detailed debug info? */
 	char *script_path;		/* pathname of script file */
 
@@ -101,7 +103,6 @@ struct config {
 	struct ip_address wire_server_ip;  /* IP of on-the-wire server */
 	char *wire_server_ip_string;	   /* malloc-ed server IP string */
 	u16 wire_server_port;		   /* the port the server listens on */
-
 };
 
 /* Top-level info about the invocation of a test script */
diff --git a/gtests/net/packetdrill/packetdrill.c b/gtests/net/packetdrill/packetdrill.c
index 5818872d..d95c6aaa 100644
--- a/gtests/net/packetdrill/packetdrill.c
+++ b/gtests/net/packetdrill/packetdrill.c
@@ -101,6 +101,10 @@ int main(int argc, char *argv[])
 						script_path, NULL))
 			exit(EXIT_FAILURE);
 
+		/* If --dry_run, then don't actually execute the script. */
+		if (config.dry_run)
+			continue;
+
 		run_init_scripts(&config);
 		run_script(&config, &script);
 	}
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index 6203a0ba..a6d405f6 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -176,7 +176,7 @@ void read_script(const char *script_path, struct script *script)
 
 		/* Allocate a buffer big enough for the whole file. */
 		if (stat(script_path, &script_info) != 0)
-			die("stat() of script file '%s': %s\n",
+			die("parse error: stat() of script file '%s': %s\n",
 			    script_path, strerror(errno));
 
 		/* Pick a buffer size larger than the file, so we'll
@@ -190,12 +190,12 @@ void read_script(const char *script_path, struct script *script)
 		/* Read the file into our buffer. */
 		fd = open(script_path, O_RDONLY);
 		if (fd < 0)
-			die("error opening script file '%s': %s\n",
+			die("parse error opening script file '%s': %s\n",
 			    script_path, strerror(errno));
 
 		script->length = read(fd, script->buffer, size);
 		if (script->length < 0)
-			die("error reading script file '%s': %s\n",
+			die("parse error reading script file '%s': %s\n",
 			    script_path, strerror(errno));
 
 		/* If we filled the buffer, then probably another
@@ -239,7 +239,7 @@ int parse_script(const struct config *config,
 	/* Now parse the script from our buffer. */
 	yyin = fmemopen(script->buffer, script->length, "r");
 	if (yyin == NULL)
-		die_perror("fmemopen: error opening script buffer");
+		die_perror("fmemopen: parse error opening script buffer");
 
 	current_script_path = config->script_path;
 	in_config = config;
@@ -280,7 +280,7 @@ static void yyerror(const char *message)
 static void semantic_error(const char* message)
 {
 	assert(current_script_line >= 0);
-	die("%s:%d: error: %s\n",
+	die("%s:%d: semantic error: %s\n",
 	    current_script_path, current_script_line, message);
 }
 
-- 
GitLab