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

Side by Side Diff: chrome/test/mini_installer/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: Upload with NOTRY=True. Created 7 years, 4 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 unified diff | Download patch
« no previous file with comments | « chrome/test/mini_installer/settings.py ('k') | chrome/test/mini_installer/uninstall_chrome.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """This script tests the installer with test cases specified in the config file.
6
7 For each test case, it checks that the machine states after the execution of
8 each command match the expected machine states. For more details, take a look at
9 the design documentation at http://goo.gl/Q0rGM6
10 """
11
12 import argparse
13 import json
14 import os
15 import subprocess
16
17 import settings
18 import verifier
19
20
21 class Config:
22 """Describes the machine states, actions, and test cases.
23
24 A state is a dictionary where each key is a verifier's name and the
25 associated value is the input to that verifier. An action is a shorthand for
26 a command. A test is array of alternating state names and action names,
27 starting and ending with state names. An instance of this class stores a map
28 from state names to state objects, a map from action names to commands, and
29 an array of test objects.
30 """
31 def __init__(self):
32 self.states = {}
33 self.actions = {}
34 self.tests = []
35
36
37 def MergePropertyDictionaries(current_property, new_property):
38 """Merges the new property dictionary into the current property dictionary.
39
40 This is different from general dictionary merging in that, in case there are
41 keys with the same name, we merge values together in the first level, and we
42 override earlier values in the second level. For more details, take a look at
43 http://goo.gl/uE0RoR
44
45 Args:
46 current_property: The property dictionary to be modified.
47 new_property: The new property dictionary.
48 """
49 for key, value in new_property.iteritems():
50 if key not in current_property:
51 current_property[key] = value
52 else:
53 assert(isinstance(current_property[key], dict) and
54 isinstance(value, dict))
55 # This merges two dictionaries together. In case there are keys with
56 # the same name, the latter will override the former.
57 current_property[key] = dict(
58 current_property[key].items() + value.items())
59
60
61 def ParsePropertyFiles(directory, filenames):
62 """Parses an array of .prop files.
63
64 Args:
65 property_filenames: An array of Property filenames.
66 directory: The directory where the Config file and all Property files
67 reside in.
68
69 Returns:
70 A property dictionary created by merging all property dictionaries specified
71 in the array.
72 """
73 current_property = {}
74 for filename in filenames:
75 path = os.path.join(directory, filename)
76 new_property = json.load(open(path))
77 MergePropertyDictionaries(current_property, new_property)
78 return current_property
79
80
81 def ParseConfigFile(filename):
82 """Parses a .config file.
83
84 Args:
85 config_filename: A Config filename.
86
87 Returns:
88 A Config object.
89 """
90 config_data = json.load(open(filename, 'r'))
91 directory = os.path.dirname(os.path.abspath(filename))
92
93 config = Config()
94 config.tests = config_data['tests']
95 for state_name, state_property_filenames in config_data['states']:
96 config.states[state_name] = ParsePropertyFiles(directory,
97 state_property_filenames)
98 for action_name, action_command in config_data['actions']:
99 config.actions[action_name] = action_command
100 return config
101
102
103 def VerifyState(config, state):
104 """Verifies that the current machine states match the given machine states.
105
106 Args:
107 config: A Config object.
108 state: The current state.
109 """
110 # TODO(sukolsak): Think of ways of preserving the log when the test fails but
111 # not printing these when the test passes.
112 print settings.PRINT_STATE_PREFIX + state
113 verifier.Verify(config.states[state])
114
115
116 def RunCommand(command):
117 print settings.PRINT_COMMAND_PREFIX + command
118 subprocess.call(command, shell=True)
119
120
121 def RunResetCommand():
122 print settings.PRINT_COMMAND_PREFIX + 'Reset'
123 # TODO(sukolsak): Need to figure how exactly we want to reset.
124
125
126 def Test(config):
127 """Tests the installer using the given Config object.
128
129 Args:
130 config: A Config object.
131 """
132 for test in config.tests:
133 print settings.PRINT_TEST_PREFIX + ' -> '.join(test)
134
135 # A Test object is an array of alternating state names and action names.
136 # The array starts and ends with states. Therefore, the length must be odd.
137 assert(len(test) % 2 == 1)
138
139 RunResetCommand()
140
141 current_state = test[0]
142 VerifyState(config, current_state)
143 # TODO(sukolsak): Quit the test early if VerifyState fails at any point.
144
145 for i in range(1, len(test), 2):
146 action = test[i]
147 RunCommand(config.actions[action])
148
149 current_state = test[i + 1]
150 VerifyState(config, current_state)
151
152
153 def main():
154 parser = argparse.ArgumentParser(description='Test the installer.')
155 parser.add_argument('config_filename',
156 help='The relative/absolute path to the config file.')
157 args = parser.parse_args()
158
159 config = ParseConfigFile(args.config_filename)
160 Test(config)
161
162
163 if __name__ == '__main__':
164 main()
OLDNEW
« no previous file with comments | « chrome/test/mini_installer/settings.py ('k') | chrome/test/mini_installer/uninstall_chrome.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698