diff mbox

[i-g-t,5/5] lib: write out recent log output if a test fails

Message ID 1417540539-23069-5-git-send-email-thomas.wood@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Thomas Wood Dec. 2, 2014, 5:15 p.m. UTC
Signed-off-by: Thomas Wood <thomas.wood@intel.com>
---
 lib/igt_core.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 58 insertions(+), 10 deletions(-)
diff mbox

Patch

diff --git a/lib/igt_core.c b/lib/igt_core.c
index d53fabb..c369ed7 100644
--- a/lib/igt_core.c
+++ b/lib/igt_core.c
@@ -50,6 +50,7 @@ 
 #include <termios.h>
 #include <errno.h>
 #include <time.h>
+#include <limits.h>
 
 #include "drmtest.h"
 #include "intel_chipset.h"
@@ -228,8 +229,16 @@  enum {
  OPT_HELP = 'h'
 };
 
+static const char *command_str;
+static int igt_exitcode = IGT_EXIT_SUCCESS;
+
 static char* igt_log_domain_filter;
 
+static struct {
+	char *entries[256];
+	uint8_t start, end;
+} log_buffer;
+
 __attribute__((format(printf, 1, 2)))
 static void kmsg(const char *format, ...)
 #define KERN_EMER	"<0>"
@@ -353,6 +362,38 @@  static void low_mem_killer_disable(bool disable)
 	chmod(adj_fname, buf.st_mode);
 }
 
+static void write_log(void)
+{
+	uint8_t i;
+	int log, pos;
+	char filename[NAME_MAX];
+	const char *ext = ".log";
+
+	/* don't write an empty log */
+	if (log_buffer.start == log_buffer.end)
+		return;
+
+	/* copy the test filename and append ".log" in a signal handler safe
+	 * way */
+	for (i = 0; command_str[i] && i < NAME_MAX - 5; i++)
+		filename[i] = command_str[i];
+	pos = i;
+	for (i = 0; pos + i < NAME_MAX; i++) {
+		filename[pos + i] = ext[i];
+		if (ext[i] == '\0')
+			break;
+	}
+
+	log = open(filename, O_CREAT|O_WRONLY);
+	i = log_buffer.start;
+	do {
+		int len = strlen(log_buffer.entries[i]);
+		write(log, log_buffer.entries[i], len);
+		i++;
+	} while (i != log_buffer.start && i != log_buffer.end);
+	close(log);
+}
+
 bool igt_exit_called;
 static void common_exit_handler(int sig)
 {
@@ -361,6 +402,10 @@  static void common_exit_handler(int sig)
 	/* When not killed by a signal check that igt_exit() has been properly
 	 * called. */
 	assert(sig != 0 || igt_exit_called);
+
+	/* write the log out to a file if the test failed */
+	if (sig || (igt_exitcode != IGT_EXIT_SUCCESS && igt_exitcode != IGT_EXIT_SKIP))
+		write_log();
 }
 
 static void print_test_description(void)
@@ -383,8 +428,6 @@  static void print_version(void)
 		uts.sysname, uts.release, uts.machine);
 }
 
-static const char *command_str;
-
 static void print_usage(const char *help_str, bool output_on_stderr)
 {
 	FILE *f = output_on_stderr ? stderr : stdout;
@@ -728,7 +771,6 @@  bool igt_only_list_subtests(void)
 static bool skipped_one = false;
 static bool succeeded_one = false;
 static bool failed_one = false;
-static int igt_exitcode = IGT_EXIT_SUCCESS;
 
 static void exit_subtest(const char *) __attribute__((noreturn));
 static void exit_subtest(const char *result)
@@ -1458,21 +1500,28 @@  void igt_log(const char *domain, enum igt_log_level level, const char *format, .
 void igt_vlog(const char *domain, enum igt_log_level level, const char *format, va_list args)
 {
 	FILE *file;
+	char *line;
 
 	assert(format);
 
 	if (list_subtests)
 		return;
 
-	if (igt_log_level > level)
-		return;
+	if (!domain)
+		domain = command_str;
+
+	/* store any log output in ring buffer */
+	free(log_buffer.entries[log_buffer.end]);
+	vasprintf(&line, format, args);
+	asprintf(&log_buffer.entries[log_buffer.end], "(%s:%d) %s",
+		 domain, getpid(), line);
+	log_buffer.end++;
+	if (log_buffer.end == log_buffer.start)
+		log_buffer.start++;
 
 	if (igt_log_level > level)
 		return;
 
-	if (!domain)
-		domain = command_str;
-
 	if (igt_log_domain_filter && strcmp(igt_log_domain_filter, domain))
 		return;
 
@@ -1483,8 +1532,7 @@  void igt_vlog(const char *domain, enum igt_log_level level, const char *format,
 	else
 		file = stdout;
 
-	fprintf(file, "(%s:%d) ", domain, getpid());
-	vfprintf(file, format, args);
+	fprintf(file, "(%s:%d) %s", domain, getpid(), line);
 }
 
 static void igt_alarm_handler(int signal)