validate:launcher: Handle stdout/stderr as possible logfiles

Allowing people to get all the logs in the terminal
This commit is contained in:
Thibault Saunier 2014-08-10 12:04:31 +02:00
parent 32dac5014a
commit 20c28def3c
4 changed files with 84 additions and 35 deletions

View file

@ -30,6 +30,7 @@ import subprocess
import reporters import reporters
import ConfigParser import ConfigParser
import loggable import loggable
import tempfile
from loggable import Loggable from loggable import Loggable
from optparse import OptionGroup from optparse import OptionGroup
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
@ -61,9 +62,12 @@ class Test(Loggable):
self.process = None self.process = None
self.duration = duration self.duration = duration
self.clean() self.clean(True)
def clean(self, full=True):
if not full:
return
def clean(self):
self.message = "" self.message = ""
self.error_str = "" self.error_str = ""
self.time_taken = 0.0 self.time_taken = 0.0
@ -78,10 +82,11 @@ class Test(Loggable):
string += ": " + self.result string += ": " + self.result
if self.result in [Result.FAILED, Result.TIMEOUT]: if self.result in [Result.FAILED, Result.TIMEOUT]:
string += " '%s'\n" \ string += " '%s'\n" \
" You can reproduce with: %s\n" \ " You can reproduce with: %s\n" % (self.message, self.command)
" You can find logs in:\n" \
" - %s" % (self.message, self.command, if not self.reporter.uses_standard_output():
self.logfile) string += " You can find logs in:\n" \
" - %s" % (self.logfile)
for log in self.extra_logfiles: for log in self.extra_logfiles:
string += "\n - %s" % log string += "\n - %s" % log
@ -205,12 +210,13 @@ class Test(Loggable):
proc_env = self.get_subproc_env() proc_env = self.get_subproc_env()
message = "Launching: %s%s\n" \ message = "Launching: %s%s\n" \
" Command: '%s'\n" \ " Command: '%s'\n" %(Colors.ENDC, self.classname,
" Logs:\n" \ self.command)
" - %s" % (Colors.ENDC, self.classname, if not self.reporter.uses_standard_output():
self.command, self.logfile) message += " Logs:\n" \
for log in self.extra_logfiles: " - %s" % (self.logfile)
message += "\n - %s" % log for log in self.extra_logfiles:
message += "\n - %s" % log
printc(message, Colors.OKBLUE) printc(message, Colors.OKBLUE)
@ -232,12 +238,14 @@ class Test(Loggable):
self.time_taken = time.time() - self._starting_time self.time_taken = time.time() - self._starting_time
self.reporter.out.seek(0) if not self.reporter.uses_standard_output():
self.reporter.out.write("=================\n" self.reporter.out.seek(0)
"Test name: %s\n" self.reporter.out.write("=================\n"
"Command: '%s'\n" "Test name: %s\n"
"=================\n\n" "Command: '%s'\n"
% (self.classname, self.command)) "=================\n\n"
% (self.classname, self.command))
printc("Result: %s%s\n" % (self.result, printc("Result: %s%s\n" % (self.result,
" (" + self.message + ")" if self.message else ""), " (" + self.message + ")" if self.message else ""),
color=utils.get_color_for_result(self.result)) color=utils.get_color_for_result(self.result))
@ -270,23 +278,38 @@ class GstValidateTest(Test):
self.scenario = scenario self.scenario = scenario
def get_subproc_env(self): def get_subproc_env(self):
if self.reporter.uses_standard_output():
self.validatelogs = os.path.join (tempfile.gettempdir(), 'tmp.validate.logs')
logfiles = self.validatelogs
logfiles += os.pathsep + self.reporter.out.name.replace("<", '').replace(">", '')
else:
self.validatelogs = self.logfile + '.validate.logs'
logfiles = self.validatelogs
subproc_env = os.environ.copy() subproc_env = os.environ.copy()
self.validatelogs = self.logfile + '.validate.logs'
utils.touch(self.validatelogs) utils.touch(self.validatelogs)
subproc_env["GST_VALIDATE_FILE"] = self.validatelogs subproc_env["GST_VALIDATE_FILE"] = logfiles
self.extra_logfiles.append(self.validatelogs) self.extra_logfiles.append(self.validatelogs)
if 'GST_DEBUG' in os.environ: if 'GST_DEBUG' in os.environ and \
not self.reporter.uses_standard_output():
gstlogsfile = self.logfile + '.gstdebug' gstlogsfile = self.logfile + '.gstdebug'
self.extra_logfiles.append(gstlogsfile) self.extra_logfiles.append(gstlogsfile)
subproc_env["GST_DEBUG_FILE"] = gstlogsfile subproc_env["GST_DEBUG_FILE"] = gstlogsfile
return subproc_env return subproc_env
def clean(self): def clean(self, full=True):
Test.clean(self) Test.clean(self, full=full)
self._sent_eos_pos = None if self.reporter.uses_standard_output():
try:
os.remove(self.validatelogs)
except OSError:
pass
if full:
self._sent_eos_pos = None
def build_arguments(self): def build_arguments(self):
if self.scenario is not None: if self.scenario is not None:
@ -681,6 +704,7 @@ class TestsManager(Loggable):
self.reporter.after_test() self.reporter.after_test()
if res != Result.PASSED and (self.options.forever or if res != Result.PASSED and (self.options.forever or
self.options.fatal_error): self.options.fatal_error):
test.clean(full=False)
return test.result return test.result
return Result.PASSED return Result.PASSED
@ -754,7 +778,8 @@ class _TestsLauncher(Loggable):
def set_settings(self, options, args): def set_settings(self, options, args):
self.reporter = reporters.XunitReporter(options) self.reporter = reporters.XunitReporter(options)
mkdir(options.logsdir) if not options.logsdir in[sys.stderr, sys.stdout]:
mkdir(options.logsdir)
self.options = options self.options = options
wanted_testers = None wanted_testers = None
@ -920,7 +945,11 @@ class ScenarioManager(Loggable):
""" """
scenarios = [] scenarios = []
scenario_defs = os.path.join(self.config.main_dir, "scenarios.def") scenario_defs = os.path.join(self.config.main_dir, "scenarios.def")
logs = open(os.path.join(self.config.logsdir, "scenarios_discovery.log"), 'w') if self.config.logsdir in ["stdout", "stderr"]:
logs = open(os.devnull)
else:
logs = open(os.path.join(self.config.logsdir, "scenarios_discovery.log"), 'w')
try: try:
command = [self.GST_VALIDATE_COMMAND, "--scenarios-defs-output-file", scenario_defs] command = [self.GST_VALIDATE_COMMAND, "--scenarios-defs-output-file", scenario_defs]
command.extend(scenario_paths) command.extend(scenario_paths)

View file

@ -22,6 +22,7 @@ import time
import loggable import loggable
import subprocess import subprocess
import sys import sys
import tempfile
logcat = "httpserver" logcat = "httpserver"
@ -54,7 +55,11 @@ class HTTPServer(loggable.Loggable):
def start(self): def start(self):
""" Start the server in a subprocess """ """ Start the server in a subprocess """
self._logsfile = open(os.path.join(self.options.logsdir, if self.options.logsdir in ["stdout", "stderr"]:
self.info("Using devnull as HTTP server log file")
self._logsfile = tempfile.TemporaryFile()
else:
self._logsfile = open(os.path.join(self.options.logsdir,
"httpserver.logs"), "httpserver.logs"),
'w+') 'w+')
if self.options.http_server_dir is not None: if self.options.http_server_dir is not None:

View file

@ -257,7 +257,9 @@ user argument, you can thus overrides command line options using that.
help="Directory where to store logs and rendered files. Default is MAIN_DIR") help="Directory where to store logs and rendered files. Default is MAIN_DIR")
dir_group.add_argument("-l", "--logs-dir", dest="logsdir", dir_group.add_argument("-l", "--logs-dir", dest="logsdir",
default=None, default=None,
help="Directory where to store logs, default is OUTPUT_DIR/logs") help="Directory where to store logs, default is OUTPUT_DIR/logs."
" Note that 'stdout' and 'sdterr' are valid values that lets you get all the logs"
" printed in the terminal")
dir_group.add_argument("-R", "--render-path", dest="dest", dir_group.add_argument("-R", "--render-path", dest="dest",
default=None, default=None,
help="Set the path to which projects should be rendered, default is OUTPUT_DIR/rendered") help="Set the path to which projects should be rendered, default is OUTPUT_DIR/rendered")

View file

@ -21,6 +21,7 @@
import os import os
import re import re
import sys
import time import time
import codecs import codecs
import datetime import datetime
@ -65,14 +66,24 @@ class Reporter(Loggable):
} }
self.results = [] self.results = []
def uses_standard_output(self):
return self.out in [sys.stdout, sys.stderr]
def before_test(self, test): def before_test(self, test):
"""Initialize a timer before starting a test.""" """Initialize a timer before starting a test."""
path = os.path.join(self.options.logsdir, if self.options.logsdir == 'stdout':
test.classname.replace(".", os.sep)) self.out = sys.stdout
mkdir(os.path.dirname(path)) test.logfile = 'stdout'
self.out = open(path, 'w+') elif self.options.logsdir == 'stderr':
self.out = sys.stderr
test.logfile = 'stderr'
else:
path = os.path.join(self.options.logsdir,
test.classname.replace(".", os.sep))
mkdir(os.path.dirname(path))
self.out = open(path, 'w+')
test.logfile = path
self._current_test = test self._current_test = test
test.logfile = path
if self._start_time == 0: if self._start_time == 0:
self._start_time = time.time() self._start_time = time.time()
@ -98,7 +109,9 @@ class Reporter(Loggable):
self.results.append(self._current_test) self.results.append(self._current_test)
self.add_results(self._current_test) self.add_results(self._current_test)
self.out.close() if not self.uses_standard_output():
self.out.close()
self.out = None self.out = None
self._current_test = None self._current_test = None
@ -146,7 +159,7 @@ class XunitReporter(Reporter):
def _get_captured(self): def _get_captured(self):
captured = "" captured = ""
if self.out: if self.out and not self.uses_standard_output():
self.out.seek(0) self.out.seek(0)
value = self.out.read() value = self.out.read()
if value: if value: