Commit 92a819b0 authored by grt's avatar grt Committed by Commit bot

Reduce flakes in the mini_installer test.

This change makes the test more resilient to unexpected state on the
machine.

- RegistryVerifier can now verify that registry values are not present
  (and, as a result, optional registry keys). A key's "exists" property
  can be one of "required", "forbidden", or "optional". The first two
  behave identically to the true and false boolean values of the
  previous implementation. For an "optional" key, values within it may
  have an empty dict (i.e., with no "type" or "data" members) to
  indicate that the value must not be present in the key if the key is
  present.

- Each test now begins with the "no_pv" state rather than the "clean"
  state. This is more permissive, and simply ensures that Chrome is not
  registered with Google Update.

- After attempting to force-uninstall Chrome (either before executing a
  test or after a test failure), the harness will unconditionally delete
  the Google Update registration of that Chrome if it is present. This
  will clean the machine sufficiently for a subsequent test run.

BUG=375739,401148,402081
R=robertshield@chromium.org
NOTRY=true

Review URL: https://codereview.chromium.org/520633005

Cr-Commit-Position: refs/heads/master@{#292943}
parent bf8d3186
......@@ -14,13 +14,13 @@
},
"RegistryEntries": {
"HKEY_LOCAL_MACHINE\\$CHROME_UPDATE_REGISTRY_SUBKEY": {
"exists": true,
"exists": "required",
"values": {
"pv": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"}
}
},
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$CHROME_LONG_NAME": {
"exists": true,
"exists": "required",
"values": {
"UninstallString": {
"type": "SZ",
......@@ -31,7 +31,7 @@
},
"HKEY_LOCAL_MACHINE\\Software\\Classes\\$CHROME_SHORT_NAME": {
"condition": "$WINDOWS_VERSION >= $VERSION_WIN8",
"exists": true
"exists": "required"
}
}
}
{
"RegistryEntries": {
"HKEY_LOCAL_MACHINE\\$CHROME_UPDATE_REGISTRY_SUBKEY": {
"exists": "optional",
"values": {
"pv": {}
}
}
}
}
......@@ -3,11 +3,12 @@
"$PROGRAM_FILES\\$CHROME_DIR\\Application": {"exists": false}
},
"RegistryEntries": {
"HKEY_LOCAL_MACHINE\\$CHROME_UPDATE_REGISTRY_SUBKEY": {"exists": false},
"HKEY_LOCAL_MACHINE\\$CHROME_UPDATE_REGISTRY_SUBKEY": {
"exists": "forbidden"},
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$CHROME_LONG_NAME":
{"exists": false},
{"exists": "forbidden"},
"HKEY_LOCAL_MACHINE\\Software\\Classes\\$CHROME_SHORT_NAME": {
"exists": false
"exists": "forbidden"
}
}
}
......@@ -14,13 +14,13 @@
},
"RegistryEntries": {
"HKEY_CURRENT_USER\\$CHROME_UPDATE_REGISTRY_SUBKEY": {
"exists": true,
"exists": "required",
"values": {
"pv": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"}
}
},
"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$CHROME_LONG_NAME": {
"exists": true,
"exists": "required",
"values": {
"UninstallString": {
"type": "SZ",
......@@ -31,7 +31,7 @@
},
"HKEY_CURRENT_USER\\Software\\Classes\\$CHROME_SHORT_NAME$USER_SPECIFIC_REGISTRY_SUFFIX": {
"condition": "$WINDOWS_VERSION >= $VERSION_WIN8",
"exists": true
"exists": "required"
}
}
}
{
"RegistryEntries": {
"HKEY_CURRENT_USER\\$CHROME_UPDATE_REGISTRY_SUBKEY": {
"exists": "optional",
"values": {
"pv": {}
}
}
}
}
......@@ -4,11 +4,11 @@
},
"RegistryEntries": {
"HKEY_CURRENT_USER\\$CHROME_UPDATE_REGISTRY_SUBKEY\\Commands":
{"exists": false},
{"exists": "forbidden"},
"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$CHROME_LONG_NAME":
{"exists": false},
{"exists": "forbidden"},
"HKEY_CURRENT_USER\\Software\\Classes\\$CHROME_SHORT_NAME$USER_SPECIFIC_REGISTRY_SUFFIX": {
"exists": false
"exists": "forbidden"
}
}
}
{
"states": [
["no_pv", ["chrome_user_no_pv.prop",
"chrome_system_no_pv.prop"]],
["clean", ["chrome_user_not_installed.prop",
"chrome_system_not_installed.prop",
"chrome_user_not_inuse.prop",
......@@ -43,7 +45,7 @@
{
"name": "ChromeUserLevel",
"traversal": [
"clean",
"no_pv",
"install_chrome_user", "chrome_user_installed_not_inuse",
"launch_chrome_user", "chrome_user_installed_inuse",
"quit_chrome_user", "chrome_user_installed_not_inuse",
......@@ -53,7 +55,7 @@
{
"name": "ChromeSystemLevel",
"traversal": [
"clean",
"no_pv",
"install_chrome_system", "chrome_system_installed_not_inuse",
"launch_chrome_system", "chrome_system_installed_inuse",
"quit_chrome_system", "chrome_system_installed_not_inuse",
......
......@@ -49,13 +49,17 @@ class RegistryVerifier(verifier.Verifier):
expectation_name: The registry key being verified. It is expanded using
Expand.
expectation: A dictionary with the following keys and values:
'exists' a boolean indicating whether the registry key should exist.
'exists' a string indicating whether the registry key's existence is
'required', 'optional', or 'forbidden'. Values are not checked if
an 'optional' key is not present in the registry.
'values' (optional) a dictionary where each key is a registry value
and its associated value is a dictionary with the following key
and values:
'type' a string indicating the type of the registry value.
'data' the associated data of the registry value. If it is a
string, it is expanded using Expand.
'type' (optional) a string indicating the type of the registry
value. If not present, the corresponding value is expected
to be absent in the registry.
'data' the associated data of the registry value if 'type' is
specified. If it is a string, it is expanded using Expand.
variable_expander: A VariableExpander object.
"""
key = variable_expander.Expand(expectation_name)
......@@ -67,11 +71,13 @@ class RegistryVerifier(verifier.Verifier):
_winreg.KEY_QUERY_VALUE)
except WindowsError:
# Key doesn't exist. See that it matches the expectation.
assert not expectation['exists'], ('Registry key %s is missing' %
key)
assert expectation['exists'] is not 'required', ('Registry key %s is '
'missing' % key)
# Values are not checked if the missing key's existence is optional.
return
# The key exists, see that it matches the expectation.
assert expectation['exists'], ('Registry key %s exists' % key)
assert expectation['exists'] is not 'forbidden', ('Registry key %s exists' %
key)
# Verify the expected values.
if 'values' not in expectation:
......@@ -82,8 +88,13 @@ class RegistryVerifier(verifier.Verifier):
try:
data, value_type = _winreg.QueryValueEx(key_handle, value)
except WindowsError:
raise KeyError("Value '%s' of registry key %s is missing" % (
value, key))
# The value does not exist. See that this matches the expectation.
assert 'type' not in value_expectation, ('Value %s of registry key %s '
'is missing' % (value, key))
continue
assert 'type' in value_expectation, ('Value %s of registry key %s exists '
'with value %s' % (value, key, data))
# Verify the type of the value.
expected_value_type = value_expectation['type']
......
......@@ -16,6 +16,7 @@ import subprocess
import sys
import time
import unittest
import _winreg
from variable_expander import VariableExpander
import verifier_runner
......@@ -144,6 +145,26 @@ def RunCommand(command, variable_expander):
expanded_command, exit_status))
def DeleteGoogleUpdateRegistration(system_level, variable_expander):
"""Deletes Chrome's registration with Google Update.
Args:
system_level: True if system-level Chrome is to be deleted.
variable_expander: A VariableExpander object.
"""
root = (_winreg.HKEY_LOCAL_MACHINE if system_level
else _winreg.HKEY_CURRENT_USER)
key_name = variable_expander.Expand('$CHROME_UPDATE_REGISTRY_SUBKEY')
try:
key_handle = _winreg.OpenKey(root, key_name, 0,
_winreg.KEY_SET_VALUE |
_winreg.KEY_WOW64_32KEY)
_winreg.DeleteValue(key_handle, 'pv')
except WindowsError:
# The key isn't present, so there is no value to delete.
pass
def RunCleanCommand(force_clean, variable_expander):
"""Puts the machine in the clean state (i.e. Chrome not installed).
......@@ -152,17 +173,17 @@ def RunCleanCommand(force_clean, variable_expander):
installations.
variable_expander: A VariableExpander object.
"""
# TODO(sukolsak): Read the clean state from the config file and clean
# the machine according to it.
# TODO(sukolsak): Handle Chrome SxS installs.
commands = []
interactive_option = '--interactive' if not force_clean else ''
for level_option in ('', '--system-level'):
commands.append('python uninstall_chrome.py '
for system_level in (False, True):
level_option = '--system-level' if system_level else ''
command = ('python uninstall_chrome.py '
'--chrome-long-name="$CHROME_LONG_NAME" '
'--no-error-if-absent %s %s' %
(level_option, interactive_option))
RunCommand(' && '.join(commands), variable_expander)
RunCommand(command, variable_expander)
if force_clean:
DeleteGoogleUpdateRegistration(system_level, variable_expander)
def MergePropertyDictionaries(current_property, new_property):
......
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