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

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: Use argparse instead of optparse. 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.
gab 2013/08/06 14:12:56 Link to http://goo.gl/uE0RoR for details here. (h
sukolsak 2013/08/06 14:44:53 Done.
43
44 Args:
45 current_property: The property dictionary to be modified.
46 new_property: The new property dictionary.
47 """
48 for key, value in new_property.iteritems():
49 if key not in current_property:
50 current_property[key] = value
51 else:
52 assert(isinstance(current_property[key], dict) and
53 isinstance(value, dict))
54 # This merges two dictionaries together. In case there are keys with
55 # the same name, the latter will override the former.
56 current_property[key] = dict(
57 current_property[key].items() + value.items())
58
59
60 def ParsePropertyFiles(directory, filenames):
61 """Parses an array of .prop files.
62
63 Args:
64 property_filenames: An array of Property filenames.
65 directory: The directory where the Config file and all Property files
66 reside in.
67
68 Returns:
69 A property dictionary created by merging all property dictionaries specified
70 in the array.
71 """
72 current_property = {}
73 for filename in filenames:
74 path = os.path.join(directory, filename)
75 new_property = json.load(open(path))
76 MergePropertyDictionaries(current_property, new_property)
77 return current_property
78
79
80 def ParseConfigFile(filename):
81 """Parses a .config file.
82
83 Args:
84 config_filename: A Config filename.
85
86 Returns:
87 A Config object.
88 """
89 config_data = json.load(open(filename, 'r'))
90 directory = os.path.dirname(os.path.abspath(filename))
91
92 config = Config()
93 config.tests = config_data['tests']
94 for state_name, state_property_filenames in config_data['states']:
95 config.states[state_name] = ParsePropertyFiles(directory,
96 state_property_filenames)
97 for action_name, action_command in config_data['actions']:
98 config.actions[action_name] = action_command
99 return config
100
101
102 def VerifyState(config, state):
103 """Verifies that the current machine states match the given machine states.
104
105 Args:
106 config: A Config object.
107 state: The current state.
108 """
109 # TODO(sukolsak): Think of ways of preserving the log when the test fails but
110 # not printing these when the test passes.
111 print settings.PRINT_STATE_PREFIX + state
112 verifier.Verify(config.states[state])
113
114
115 def RunCommand(command):
116 print settings.PRINT_COMMAND_PREFIX + command
117 subprocess.call(command, shell=True)
118
119
120 def RunResetCommand():
121 print settings.PRINT_COMMAND_PREFIX + 'Reset'
122 # TODO(sukolsak): Need to figure how exactly we want to reset.
123
124
125 def Test(config):
126 """Tests the installer using the given Config object.
127
128 Args:
129 config: A Config object.
130 """
131 for test in config.tests:
132 print settings.PRINT_TEST_PREFIX + ' -> '.join(test)
133
134 # A Test object is an array of alternating state names and action names.
135 # The array starts and ends with states. Therefore, the length must be odd.
136 assert(len(test) % 2 == 1)
137
138 RunResetCommand()
139
140 current_state = test[0]
141 VerifyState(config, current_state)
142 # TODO(sukolsak): Quit the test early if VerifyState fails at any point.
143
144 for i in range(1, len(test), 2):
145 action = test[i]
146 RunCommand(config.actions[action])
147
148 current_state = test[i + 1]
149 VerifyState(config, current_state)
150
151
152 def main():
153 parser = argparse.ArgumentParser(description='Test the installer.')
154 parser.add_argument('config_filename', help='the config file')
gab 2013/08/06 14:12:56 optional nit: From ParseConfigFile() I gather that
sukolsak 2013/08/06 14:44:53 Done.
155 args = parser.parse_args()
156
157 config = ParseConfigFile(args.config_filename)
158 Test(config)
159
160
161 if __name__ == '__main__':
162 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