Browse Source

ccanlint: run tests under valgrind initially.

Unless it's not available or suppressed, we might as well run it under
valgrind the first time, which speeds things a little.

We save the valgrind output file for tests_pass_valgrind's use later.
Rusty Russell 14 years ago
parent
commit
ad6a6711a1

+ 3 - 0
tools/ccanlint/ccanlint.h

@@ -179,6 +179,9 @@ struct ccan_file {
 	/* Compiled with coverage information. */
 	char *cov_compiled;
 
+	/* Filename containing output from valgrind. */
+	char *valgrind_log;
+
 	/* Leak output from valgrind. */
 	char *leak_info;
 

+ 85 - 9
tools/ccanlint/tests/tests_pass.c

@@ -14,18 +14,77 @@
 #include <err.h>
 #include <string.h>
 #include <ctype.h>
+#include "tests_pass.h"
+
+bool do_valgrind = false;
 
 static const char *can_run(struct manifest *m)
 {
+	unsigned int timeleft = default_timeout_ms;
+	char *output;
 	if (safe_mode)
 		return "Safe mode enabled";
+
+	if (!is_excluded("tests_pass_valgrind")
+	    && run_command(m, &timeleft, &output,
+			   "valgrind -q true"))
+		do_valgrind = true;
+
 	return NULL;
 }
 
-static void do_run_tests(struct manifest *m,
-			 bool keep,
-			 unsigned int *timeleft,
-			 struct score *score)
+static const char *concat(struct score *score, char *bits[])
+{
+	unsigned int i;
+	char *ret = talloc_strdup(score, "");
+
+	for (i = 0; bits[i]; i++) {
+		if (i)
+			ret = talloc_append_string(ret, " ");
+		ret = talloc_append_string(ret, bits[i]);
+	}
+	return ret;
+}
+
+static bool run_test(void *ctx,
+		     struct manifest *m,
+		     unsigned int *timeleft, char **cmdout,
+		     struct ccan_file *i,
+		     bool use_valgrind)
+{
+	if (use_valgrind) {
+		const char *options;
+		options = concat(ctx,
+				 per_file_options(&tests_pass_valgrind, i));
+
+		if (!streq(options, "FAIL")) {
+			/* FIXME: Valgrind's output sucks.  XML is
+			 * unreadable by humans *and* doesn't support
+			 * children reporting. */
+			i->valgrind_log = talloc_asprintf(m,
+							  "%s.valgrind-log",
+							  i->compiled);
+			talloc_set_destructor(i->valgrind_log,
+					      unlink_file_destructor);
+
+			return run_command(ctx, timeleft, cmdout,
+					   "valgrind -q"
+					   " --leak-check=full"
+					   " --log-fd=3 %s %s"
+					   " 3> %s",
+					   options,
+					   i->compiled, i->valgrind_log);
+		}
+	}
+
+	return run_command(m, timeleft, cmdout, "%s", i->compiled);
+}
+
+static void run_tests(struct manifest *m,
+		      bool keep,
+		      unsigned int *timeleft,
+		      struct score *score,
+		      bool use_valgrind)
 {
 	struct list_head *list;
 	struct ccan_file *i;
@@ -35,8 +94,8 @@ static void do_run_tests(struct manifest *m,
 	foreach_ptr(list, &m->run_tests, &m->api_tests) {
 		list_for_each(list, i, list) {
 			score->total++;
-			if (run_command(m, timeleft, &cmdout, "%s",
-					i->compiled))
+			if (run_test(score, m, timeleft, &cmdout, i,
+				     use_valgrind))
 				score->score++;
 			else
 				score_file_error(score, i, 0, "%s", cmdout);
@@ -47,6 +106,22 @@ static void do_run_tests(struct manifest *m,
 		score->pass = true;
 }
 
+static void do_run_tests(struct manifest *m,
+			 bool keep,
+			 unsigned int *timeleft,
+			 struct score *score)
+{
+	run_tests(m, keep, timeleft, score, do_valgrind);
+}
+
+static void do_run_tests_without_features(struct manifest *m,
+					  bool keep,
+					  unsigned int *timeleft,
+					  struct score *score)
+{
+	run_tests(m, keep, timeleft, score, false);
+}
+
 /* Gcc's warn_unused_result is fascist bullshit. */
 #define doesnt_matter()
 
@@ -55,11 +130,12 @@ static void run_under_debugger(struct manifest *m, struct score *score)
 	char *command;
 	struct file_error *first;
 
+	first = list_top(&score->per_file_errors, struct file_error, list);
+
 	if (!ask("Should I run the first failing test under the debugger?"))
 		return;
 
-	first = list_top(&score->per_file_errors, struct file_error, list);
-	command = talloc_asprintf(m, "gdb -ex 'break tap.c:132' -ex 'run' %s",
+	command = talloc_asprintf(m, "gdb -ex 'break tap.c:139' -ex 'run' %s",
 				  first->file->compiled);
 	if (system(command))
 		doesnt_matter();
@@ -79,7 +155,7 @@ REGISTER_TEST(tests_pass);
 struct ccanlint tests_pass_without_features = {
 	.key = "tests_pass_without_features",
 	.name = "Module's run and api tests pass (without features)",
-	.check = do_run_tests,
+	.check = do_run_tests_without_features,
 	.handle = run_under_debugger,
 	.needs = "tests_compile_without_features"
 };

+ 4 - 0
tools/ccanlint/tests/tests_pass.h

@@ -0,0 +1,4 @@
+/* Set in tests_pass. */
+extern bool do_valgrind;
+
+extern struct ccanlint tests_pass_valgrind;

+ 11 - 34
tools/ccanlint/tests/tests_pass_valgrind.c

@@ -5,6 +5,7 @@
 #include <ccan/foreach/foreach.h>
 #include <ccan/grab_file/grab_file.h>
 #include <ccan/str_talloc/str_talloc.h>
+#include "tests_pass.h"
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -23,12 +24,8 @@ REGISTER_TEST(tests_pass_valgrind_noleaks);
 /* Note: we already test safe_mode in run_tests.c */
 static const char *can_run_vg(struct manifest *m)
 {
-	unsigned int timeleft = default_timeout_ms;
-	char *output;
-
-	if (!run_command(m, &timeleft, &output,
-			 "valgrind -q --error-exitcode=0 true"))
-		return talloc_asprintf(m, "No valgrind support: %s", output);
+	if (!do_valgrind)
+		return talloc_asprintf(m, "No valgrind support");
 	return NULL;
 }
 
@@ -149,21 +146,19 @@ static const char *concat(struct score *score, char *bits[])
 
 /* FIXME: Run examples, too! */
 static void do_run_tests_vg(struct manifest *m,
-			     bool keep,
+			    bool keep,
 			    unsigned int *timeleft,
 			    struct score *score)
 {
 	struct ccan_file *i;
 	struct list_head *list;
-	char *cmdout;
 
 	/* This is slow, so we run once but grab leak info. */
 	score->total = 0;
 	score->pass = true;
 	foreach_ptr(list, &m->run_tests, &m->api_tests) {
 		list_for_each(list, i, list) {
-			char *output, *err, *log;
-			bool pass;
+			char *err, *output;
 			const char *options;
 
 			score->total++;
@@ -173,31 +168,13 @@ static void do_run_tests_vg(struct manifest *m,
 			if (streq(options, "FAIL"))
 				continue;
 
-			/* FIXME: Valgrind's output sucks.  XML is unreadable by
-			 * humans *and* doesn't support children reporting. */
-			log = talloc_asprintf(score,
-					      "%s.valgrind-log", i->compiled);
-			if (!keep)
-				talloc_set_destructor(log,
-						      unlink_file_destructor);
-
-			pass = run_command(score, timeleft, &cmdout,
-					 "valgrind -q --error-exitcode=101"
-					   " --leak-check=full"
-					   " --log-fd=3 %s %s"
-					   " 3> %s",
-					   options,
-					   i->compiled, log);
-			output = grab_file(i, log, NULL);
-			/* No valgrind errors?  Expect it to pass... */
+			if (keep)
+				talloc_set_destructor(i->valgrind_log, NULL);
+
+			output = grab_file(i, i->valgrind_log, NULL);
+			/* No valgrind errors? */
 			if (!output || output[0] == '\0') {
-				if (!pass) {
-					err = talloc_asprintf(score,
-							      "Test failed:\n"
-							      "%s",
-							      cmdout);
-				} else
-					err = NULL;
+				err = NULL;
 				i->leak_info = NULL;
 			} else {
 				i->leak_info = analyze_output(output, &err);