Commit 01c7a28b authored by Greg Thompson's avatar Greg Thompson Committed by Commit Bot

Put Chrome installer logs into isolated outdir on test failure.

This will help in diagnosing failures that deposit error messages in the
installer's log file.

BUG=907979

Change-Id: Ib9ddf7d120ab4f29b33cce4d64f866e071dca362
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1744146
Auto-Submit: Greg Thompson <grt@chromium.org>
Reviewed-by: default avatarJulian Pastarmov <pastarmovj@chromium.org>
Commit-Queue: Greg Thompson <grt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#685153}
parent 5dc1be4c
......@@ -236,21 +236,21 @@
["test_chrome_with_chromedriver_dev",
"python test_chrome_with_chromedriver.py --chromedriver-path=\"$CHROMEDRIVER_PATH\" $QUIET $OUTPUT_DIR \"$LOCAL_APPDATA\\$CHROME_DIR_DEV\\Application\\chrome.exe\""],
["install_chrome_beta",
"\"$MINI_INSTALLER\" --chrome-beta --verbose-logging --do-not-launch-chrome"],
"\"$MINI_INSTALLER\" --chrome-beta \"$LOG_FILE\" --verbose-logging --do-not-launch-chrome"],
["install_chrome_canary",
"\"$MINI_INSTALLER\" --chrome-sxs --verbose-logging --do-not-launch-chrome"],
"\"$MINI_INSTALLER\" --chrome-sxs \"$LOG_FILE\" --verbose-logging --do-not-launch-chrome"],
["install_previous_chrome_canary",
"\"$PREVIOUS_VERSION_MINI_INSTALLER\" --chrome-sxs --verbose-logging --do-not-launch-chrome"],
"\"$PREVIOUS_VERSION_MINI_INSTALLER\" --chrome-sxs \"$LOG_FILE\" --verbose-logging --do-not-launch-chrome"],
["install_chrome_dev",
"\"$MINI_INSTALLER\" --chrome-dev --verbose-logging --do-not-launch-chrome"],
"\"$MINI_INSTALLER\" --chrome-dev \"$LOG_FILE\" --verbose-logging --do-not-launch-chrome"],
["install_chrome_system",
"\"$MINI_INSTALLER\" --verbose-logging --system-level --do-not-launch-chrome"],
"\"$MINI_INSTALLER\" \"$LOG_FILE\" --verbose-logging --system-level --do-not-launch-chrome"],
["install_previous_chrome_system",
"\"$PREVIOUS_VERSION_MINI_INSTALLER\" --verbose-logging --system-level --do-not-launch-chrome"],
"\"$PREVIOUS_VERSION_MINI_INSTALLER\" \"$LOG_FILE\" --verbose-logging --system-level --do-not-launch-chrome"],
["install_chrome_user",
"\"$MINI_INSTALLER\" --verbose-logging --do-not-launch-chrome"],
"\"$MINI_INSTALLER\" \"$LOG_FILE\" --verbose-logging --do-not-launch-chrome"],
["install_previous_chrome_user",
"\"$PREVIOUS_VERSION_MINI_INSTALLER\" --verbose-logging --do-not-launch-chrome"],
"\"$PREVIOUS_VERSION_MINI_INSTALLER\" \"$LOG_FILE\" --verbose-logging --do-not-launch-chrome"],
["make_chrome_user_multi",
"python make_chrome_multi.py --chrome-long-name \"$CHROME_LONG_NAME\" --chrome-clients-key \"$CHROME_UPDATE_REGISTRY_SUBKEY\" --chrome-client-state-key \"$CHROME_CLIENT_STATE_KEY\" --binaries-clients-key \"$BINARIES_UPDATE_REGISTRY_SUBKEY\""],
["kill_user_binaries",
......@@ -270,21 +270,21 @@
["quit_chrome_user",
"python quit_chrome.py \"$LOCAL_APPDATA\\$CHROME_DIR\\Application\\chrome.exe\""],
["uninstall_chrome_beta",
"python uninstall_chrome.py --chrome-long-name=\"$CHROME_LONG_NAME_BETA\""],
"python uninstall_chrome.py \"$LOG_FILE\" --chrome-long-name=\"$CHROME_LONG_NAME_BETA\""],
["uninstall_chrome_canary",
"python uninstall_chrome.py --chrome-long-name=\"$CHROME_LONG_NAME_SXS\""],
"python uninstall_chrome.py \"$LOG_FILE\" --chrome-long-name=\"$CHROME_LONG_NAME_SXS\""],
["uninstall_chrome_dev",
"python uninstall_chrome.py --chrome-long-name=\"$CHROME_LONG_NAME_DEV\""],
"python uninstall_chrome.py \"$LOG_FILE\" --chrome-long-name=\"$CHROME_LONG_NAME_DEV\""],
["uninstall_chrome_system",
"python uninstall_chrome.py --chrome-long-name=\"$CHROME_LONG_NAME\" --system-level"],
"python uninstall_chrome.py \"$LOG_FILE\" --chrome-long-name=\"$CHROME_LONG_NAME\" --system-level"],
["uninstall_chrome_user",
"python uninstall_chrome.py --chrome-long-name=\"$CHROME_LONG_NAME\""],
"python uninstall_chrome.py \"$LOG_FILE\" --chrome-long-name=\"$CHROME_LONG_NAME\""],
["update_chrome_canary",
"\"$MINI_INSTALLER\" --chrome-sxs --verbose-logging --do-not-launch-chrome"],
"\"$MINI_INSTALLER\" --chrome-sxs \"$LOG_FILE\" --verbose-logging --do-not-launch-chrome"],
["update_chrome_system",
"\"$MINI_INSTALLER\" --verbose-logging --system-level --do-not-launch-chrome"],
"\"$MINI_INSTALLER\" \"$LOG_FILE\" --verbose-logging --system-level --do-not-launch-chrome"],
["update_chrome_user",
"\"$MINI_INSTALLER\" --verbose-logging --do-not-launch-chrome"]
"\"$MINI_INSTALLER\" \"$LOG_FILE\" --verbose-logging --do-not-launch-chrome"]
],
"tests": [
{
......
......@@ -17,6 +17,7 @@ import os
import shutil
import subprocess
import sys
import tempfile
import time
import traceback
import unittest
......@@ -107,7 +108,7 @@ class Config(object):
class InstallerTest(unittest.TestCase):
"""Tests a test case in the config file."""
def __init__(self, name, test, config, variable_expander):
def __init__(self, name, test, config, variable_expander, output_dir):
"""Constructor.
Args:
......@@ -116,14 +117,18 @@ class InstallerTest(unittest.TestCase):
ending with state names.
config: The Config object.
variable_expander: A VariableExpander object.
output_dir: An optional directory into which diagnostics may be written
in case of failure.
"""
super(InstallerTest, self).__init__()
self._name = name
self._test = test
self._config = config
self._variable_expander = variable_expander
self._output_dir = output_dir
self._verifier_runner = verifier_runner.VerifierRunner()
self._clean_on_teardown = True
self._log_path = None
def __str__(self):
"""Returns a string representing the test case.
......@@ -141,6 +146,14 @@ class InstallerTest(unittest.TestCase):
# function.
return unittest.TestCase.id(self).replace(self._testMethodName, self._name)
def setUp(self):
# Create a temp file to contain the installer log(s) for this test.
log_file, self._log_path = tempfile.mkstemp()
os.close(log_file)
self.addCleanup(os.remove, self._log_path)
self._variable_expander.SetLogFile(self._log_path)
self.addCleanup(self._variable_expander.SetLogFile, None)
def runTest(self):
"""Run the test case."""
# |test| is an array of alternating state names and action names, starting
......@@ -170,6 +183,15 @@ class InstallerTest(unittest.TestCase):
"""Cleans up the machine if the test case fails."""
if self._clean_on_teardown:
RunCleanCommand(True, self._variable_expander)
# Either copy the log to isolated outdir or dump it to console.
if self._output_dir:
target = os.path.join(self._output_dir,
os.path.basename(self._log_path))
shutil.copyfile(self._log_path, target)
logging.error('Saved installer log to %s', target)
else:
with open(self._log_path) as fh:
logging.error(fh.read())
def shortDescription(self):
"""Overridden from unittest.TestCase.
......@@ -559,7 +581,7 @@ def DoMain():
test['name'])
if not tests_to_run or test_name in tests_to_run:
suite.addTest(InstallerTest(test['name'], test['traversal'], config,
variable_expander))
variable_expander, args.output_dir))
verbosity = 2 if not args.quiet else 1
result = unittest.TextTestRunner(verbosity=verbosity).run(suite)
......
......@@ -26,6 +26,9 @@ def main():
dest='no_error_if_absent', default=False,
help='No error if the registry key for uninstalling Chrome '
'is absent.')
parser.add_option('--log-file', dest='log_file',
help='File into which the installer is to write its logs',
metavar='FILE')
options, _ = parser.parse_args()
# TODO(sukolsak): Add support for uninstalling MSI-based Chrome installs when
......@@ -55,8 +58,10 @@ def main():
print >> sys.stderr, 'User aborted'
return 1
uninstall_string, _ = _winreg.QueryValueEx(key, 'UninstallString')
exit_status = subprocess.call(uninstall_string + ' --force-uninstall',
shell=True)
uninstall_string += ' --force-uninstall'
if options.log_file:
uninstall_string += ' --verbose-logging --log-file="%s"' % options.log_file
exit_status = subprocess.call(uninstall_string, shell=True)
# The exit status for successful uninstallation of Chrome is 19 (see
# chrome/installer/util/util_constants.h).
if exit_status != 19:
......
......@@ -101,6 +101,7 @@ class VariableExpander:
* Chrome'.
* $LOCAL_APPDATA: the unquoted path to the Local Application Data
folder.
* $LOG_FILE: "--log-file=FILE" or an empty string.
* $MINI_INSTALLER: the unquoted path to the mini_installer.
* $MINI_INSTALLER_BITNESS: the bitness of the mini_installer.
* $MINI_INSTALLER_FILE_VERSION: the file version of $MINI_INSTALLER.
......@@ -161,6 +162,7 @@ class VariableExpander:
'OUTPUT_DIR': '"--output-dir=%s"' % output_dir if output_dir else '',
'LOCAL_APPDATA': shell.SHGetFolderPath(0, shellcon.CSIDL_LOCAL_APPDATA,
None, 0),
'LOG_FILE': '',
'MINI_INSTALLER': mini_installer_abspath,
'MINI_INSTALLER_FILE_VERSION': _GetFileVersion(mini_installer_abspath),
'MINI_INSTALLER_BITNESS': _GetFileBitness(mini_installer_abspath),
......@@ -285,6 +287,12 @@ class VariableExpander:
mini_installer_product_name)
def SetLogFile(self, log_file):
"""Updates the value for the LOG_FILE variable"""
self._variable_mapping['LOG_FILE'] = (
'"--log-file=%s"' % log_file if log_file else '')
def Expand(self, str):
"""Expands variables in the given string.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment