Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(469)

Unified Diff: chrome/test/mini_installer_test/test_installer.py

Issue 20578004: Initial commit for the Automated Installer Testing Framework. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/test/mini_installer_test/test_installer.py
diff --git a/chrome/test/mini_installer_test/test_installer.py b/chrome/test/mini_installer_test/test_installer.py
new file mode 100644
index 0000000000000000000000000000000000000000..0cb891aa56d8997dd6a5423e6938449280b0862f
--- /dev/null
+++ b/chrome/test/mini_installer_test/test_installer.py
@@ -0,0 +1,163 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""This script tests the installer with a series of test cases
+specified in the config file. For each test case, it checks that
+the machine states after the execution of each command match the
+expected machine states.
+
+Read the design documentation at http://goo.gl/Q0rGM6
gab 2013/07/31 13:45:16 s/Read/For more details take a look at
sukolsak 2013/07/31 18:20:30 Done.
+"""
+
+import argparse
+import json
+import os
+import settings
+import subprocess
+import verifier
+
+
+class Config:
+ """Describes the machine states, actions, and test cases."""
+
+ def __init__(self):
+ self.states = {}
+ self.actions = {}
+ self.tests = []
+
+
+def MergeProperties(current_property, new_property):
+ """Merges the new Property object into the current Property object
+
+ Args:
+ current_property: The Property object to be modified.
+ new_property: The new Property object.
+ """
+ for key, value in new_property.iteritems():
+ if key not in current_property:
+ current_property[key] = value
+ else:
+ assert(isinstance(current_property[key], dict) and
+ isinstance(value, dict))
gab 2013/07/31 13:45:16 fix indent (i.e., wrap to '(' above)
sukolsak 2013/07/31 18:20:30 Done.
+ current_property[key] = dict(
+ current_property[key].items() + value.items())
gab 2013/07/31 13:45:16 Does this merge (i.e., override) properties with t
sukolsak 2013/07/31 18:20:30 Yes. Comment added.
gab 2013/08/01 20:30:41 Sounds good, can you make it clear in the spec the
sukolsak 2013/08/02 22:59:55 Done.
+
+
+def ParseProperty(property_filename, directory):
gab 2013/07/31 13:45:16 I suggest flipping the arguments here since native
sukolsak 2013/07/31 18:20:30 Done.
+ """Parses a .prop file.
+
+ Args:
+ property_filename: A Property filename.
+ directory: The directory where the Config file and
+ all Property files reside in.
+
+ Returns:
+ A Property object.
+ """
+ property_path = os.path.join(directory, property_filename)
+ with open(property_path, "r") as property_file:
gab 2013/07/31 13:45:16 Any failure handling required here? Or will an exc
sukolsak 2013/07/31 18:20:30 The exception IOError will be bubbled back up and
+ return json.load(property_file)
+
+
+def ParseProperties(property_filenames, directory):
gab 2013/07/31 13:45:16 Same comment here about argument order
sukolsak 2013/07/31 18:20:30 Done.
+ """Parses an array of .prop files.
+
+ Args:
+ property_filenames: An array of Property filenames.
+ directory: The directory where the Config file and
+ all Property files reside in.
+
+ Returns:
+ A Property object created by merging all Property objects
+ specified in the array.
+ """
+ current_property = {}
+ for property_filename in property_filenames:
+ new_property = ParseProperty(property_filename, directory)
+ MergeProperties(current_property, new_property)
+ return current_property
+
+
+def ParseConfig(config_filename):
+ """Parses a .config file.
+
+ Args:
+ config_filename: A Config filename.
+
+ Returns:
+ A config object.
+ """
+ config = Config()
+
+ with open(config_filename, "r") as config_file:
gab 2013/07/31 13:45:16 Does config_filename need to be absolute? Either
sukolsak 2013/07/31 18:20:30 It can be relative or absolute. I think the open o
+ config_data = json.load(config_file)
+ directory = os.path.dirname(os.path.abspath(config_filename))
+
+ for state_name, state_property_filenames in config_data["states"]:
+ config.states[state_name] = ParseProperties(state_property_filenames,
+ directory)
gab 2013/07/31 13:45:16 fix indent
sukolsak 2013/07/31 18:20:30 Done.
+ for action_name, action_command in config_data["actions"]:
+ config.actions[action_name] = action_command
+ config.tests = config_data["tests"]
+ return config
+
+
+def VerifyState(config, state):
+ """Verifies that the current machine states match the given machine states.
+
+ Args:
+ config: A Config object.
+ state: The current state.
+ """
+ print settings.PRINT_STATE_PREFIX + state
+ verifier.Verify(config.states[state])
+
+
+def RunCommand(command):
+ print settings.PRINT_COMMAND_PREFIX + command
+ subprocess.call(command, shell=True)
+
+
+def RunResetCommand():
+ print settings.PRINT_COMMAND_PREFIX + "Reset"
+ # TODO(sukolsak): Need to figure how exactly we want to reset.
+
+
+def Test(config):
+ """Tests the installer using the given Config object.
+
+ Args:
+ config: A Config object.
+ """
+ for test in config.tests:
+ print settings.PRINT_TEST_PREFIX + " -> ".join(test)
+
+ # A Test object is an array of alternating states and actions.
+ # The array starts and ends with states. Therefore, the length must be odd.
+ assert(len(test) % 2 == 1)
+
+ RunResetCommand()
+
+ current_state = test[0]
+ VerifyState(config, current_state)
gab 2013/07/31 13:45:16 Add a TODO to quit the test early if VerifyState f
sukolsak 2013/07/31 18:20:30 Done.
+
+ for i in range(1, len(test), 2):
+ action = test[i]
+ RunCommand(config.actions[action])
+
+ current_state = test[i + 1]
+ VerifyState(config, current_state)
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Test the installer.")
+ parser.add_argument("config_filename", help="the config file")
+ args = parser.parse_args()
+
+ config = ParseConfig(args.config_filename)
+ Test(config)
+
+
+if __name__ == "__main__":
+ main()

Powered by Google App Engine
This is Rietveld 408576698