OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """This script tests the installer with test cases specified in the config file. | 5 """This script tests the installer with test cases specified in the config file. |
6 | 6 |
7 For each test case, it checks that the machine states after the execution of | 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 | 8 each command match the expected machine states. For more details, take a look at |
9 the design documentation at http://goo.gl/Q0rGM6 | 9 the design documentation at http://goo.gl/Q0rGM6 |
10 """ | 10 """ |
(...skipping 22 matching lines...) Expand all Loading... |
33 """ | 33 """ |
34 def __init__(self): | 34 def __init__(self): |
35 self.states = {} | 35 self.states = {} |
36 self.actions = {} | 36 self.actions = {} |
37 self.tests = [] | 37 self.tests = [] |
38 | 38 |
39 | 39 |
40 class InstallerTest(unittest.TestCase): | 40 class InstallerTest(unittest.TestCase): |
41 """Tests a test case in the config file.""" | 41 """Tests a test case in the config file.""" |
42 | 42 |
43 def __init__(self, name, test, config, variable_expander): | 43 def __init__(self, name, test, config, variable_expander, quiet): |
44 """Constructor. | 44 """Constructor. |
45 | 45 |
46 Args: | 46 Args: |
47 name: The name of this test. | 47 name: The name of this test. |
48 test: An array of alternating state names and action names, starting and | 48 test: An array of alternating state names and action names, starting and |
49 ending with state names. | 49 ending with state names. |
50 config: The Config object. | 50 config: The Config object. |
51 variable_expander: A VariableExpander object. | 51 variable_expander: A VariableExpander object. |
52 """ | 52 """ |
53 super(InstallerTest, self).__init__() | 53 super(InstallerTest, self).__init__() |
54 self._name = name | 54 self._name = name |
55 self._test = test | 55 self._test = test |
56 self._config = config | 56 self._config = config |
57 self._variable_expander = variable_expander | 57 self._variable_expander = variable_expander |
| 58 self._quiet = quiet |
58 self._verifier_runner = verifier_runner.VerifierRunner() | 59 self._verifier_runner = verifier_runner.VerifierRunner() |
59 self._clean_on_teardown = True | 60 self._clean_on_teardown = True |
60 | 61 |
61 def __str__(self): | 62 def __str__(self): |
62 """Returns a string representing the test case. | 63 """Returns a string representing the test case. |
63 | 64 |
64 Returns: | 65 Returns: |
65 A string created by joining state names and action names together with | 66 A string created by joining state names and action names together with |
66 ' -> ', for example, 'Test: clean -> install chrome -> chrome_installed'. | 67 ' -> ', for example, 'Test: clean -> install chrome -> chrome_installed'. |
67 """ | 68 """ |
(...skipping 12 matching lines...) Expand all Loading... |
80 # and ending with state names. Therefore, its length must be odd. | 81 # and ending with state names. Therefore, its length must be odd. |
81 self.assertEqual(1, len(self._test) % 2, | 82 self.assertEqual(1, len(self._test) % 2, |
82 'The length of test array must be odd') | 83 'The length of test array must be odd') |
83 | 84 |
84 state = self._test[0] | 85 state = self._test[0] |
85 self._VerifyState(state) | 86 self._VerifyState(state) |
86 | 87 |
87 # Starting at index 1, we loop through pairs of (action, state). | 88 # Starting at index 1, we loop through pairs of (action, state). |
88 for i in range(1, len(self._test), 2): | 89 for i in range(1, len(self._test), 2): |
89 action = self._test[i] | 90 action = self._test[i] |
| 91 if not self._quiet: |
| 92 sys.stderr.write('Beginning action %s\n' % action) |
90 RunCommand(self._config.actions[action], self._variable_expander) | 93 RunCommand(self._config.actions[action], self._variable_expander) |
| 94 if not self._quiet: |
| 95 sys.stderr.write('Finished action %s\n' % action) |
91 | 96 |
92 state = self._test[i + 1] | 97 state = self._test[i + 1] |
93 self._VerifyState(state) | 98 self._VerifyState(state) |
94 | 99 |
95 # If the test makes it here, it means it was successful, because RunCommand | 100 # If the test makes it here, it means it was successful, because RunCommand |
96 # and _VerifyState throw an exception on failure. | 101 # and _VerifyState throw an exception on failure. |
97 self._clean_on_teardown = False | 102 self._clean_on_teardown = False |
98 | 103 |
99 def tearDown(self): | 104 def tearDown(self): |
100 """Cleans up the machine if the test case fails.""" | 105 """Cleans up the machine if the test case fails.""" |
101 if self._clean_on_teardown: | 106 if self._clean_on_teardown: |
102 RunCleanCommand(True, self._variable_expander) | 107 RunCleanCommand(True, self._variable_expander) |
103 | 108 |
104 def shortDescription(self): | 109 def shortDescription(self): |
105 """Overridden from unittest.TestCase. | 110 """Overridden from unittest.TestCase. |
106 | 111 |
107 We return None as the short description to suppress its printing. | 112 We return None as the short description to suppress its printing. |
108 The default implementation of this method returns the docstring of the | 113 The default implementation of this method returns the docstring of the |
109 runTest method, which is not useful since it's the same for every test case. | 114 runTest method, which is not useful since it's the same for every test case. |
110 The description from the __str__ method is informative enough. | 115 The description from the __str__ method is informative enough. |
111 """ | 116 """ |
112 return None | 117 return None |
113 | 118 |
114 def _VerifyState(self, state): | 119 def _VerifyState(self, state): |
115 """Verifies that the current machine state matches a given state. | 120 """Verifies that the current machine state matches a given state. |
116 | 121 |
117 Args: | 122 Args: |
118 state: A state name. | 123 state: A state name. |
119 """ | 124 """ |
| 125 if not self._quiet: |
| 126 sys.stderr.write('Verifying state %s\n' % state) |
120 try: | 127 try: |
121 self._verifier_runner.VerifyAll(self._config.states[state], | 128 self._verifier_runner.VerifyAll(self._config.states[state], |
122 self._variable_expander) | 129 self._variable_expander) |
123 except AssertionError as e: | 130 except AssertionError as e: |
124 # If an AssertionError occurs, we intercept it and add the state name | 131 # If an AssertionError occurs, we intercept it and add the state name |
125 # to the error message so that we know where the test fails. | 132 # to the error message so that we know where the test fails. |
126 raise AssertionError("In state '%s', %s" % (state, e)) | 133 raise AssertionError("In state '%s', %s" % (state, e)) |
127 | 134 |
128 | 135 |
129 def RunCommand(command, variable_expander): | 136 def RunCommand(command, variable_expander): |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 | 255 |
249 def main(): | 256 def main(): |
250 parser = argparse.ArgumentParser() | 257 parser = argparse.ArgumentParser() |
251 parser.add_argument('--build-dir', default='out', | 258 parser.add_argument('--build-dir', default='out', |
252 help='Path to main build directory (the parent of the ' | 259 help='Path to main build directory (the parent of the ' |
253 'Release or Debug directory)') | 260 'Release or Debug directory)') |
254 parser.add_argument('--target', default='Release', | 261 parser.add_argument('--target', default='Release', |
255 help='Build target (Release or Debug)') | 262 help='Build target (Release or Debug)') |
256 parser.add_argument('--force-clean', action='store_true', default=False, | 263 parser.add_argument('--force-clean', action='store_true', default=False, |
257 help='Force cleaning existing installations') | 264 help='Force cleaning existing installations') |
258 parser.add_argument('-v', '--verbose', action='count', default=0, | 265 parser.add_argument('-q', '--quiet', action='store_true', default=False, |
259 help='Increase test runner verbosity level') | 266 help='Reduce test runner output') |
260 parser.add_argument('--write-full-results-to', metavar='FILENAME', | 267 parser.add_argument('--write-full-results-to', metavar='FILENAME', |
261 help='Path to write the list of full results to.') | 268 help='Path to write the list of full results to.') |
262 parser.add_argument('--config', metavar='FILENAME', | 269 parser.add_argument('--config', metavar='FILENAME', |
263 help='Path to test configuration file') | 270 help='Path to test configuration file') |
264 parser.add_argument('test', nargs='*', | 271 parser.add_argument('test', nargs='*', |
265 help='Name(s) of tests to run.') | 272 help='Name(s) of tests to run.') |
266 args = parser.parse_args() | 273 args = parser.parse_args() |
267 if not args.config: | 274 if not args.config: |
268 parser.error('missing mandatory --config FILENAME argument') | 275 parser.error('missing mandatory --config FILENAME argument') |
269 | 276 |
(...skipping 12 matching lines...) Expand all Loading... |
282 | 289 |
283 variable_expander = VariableExpander(mini_installer_path) | 290 variable_expander = VariableExpander(mini_installer_path) |
284 RunCleanCommand(args.force_clean, variable_expander) | 291 RunCleanCommand(args.force_clean, variable_expander) |
285 for test in config.tests: | 292 for test in config.tests: |
286 # If tests were specified via |tests|, their names are formatted like so: | 293 # If tests were specified via |tests|, their names are formatted like so: |
287 test_name = '%s.%s.%s' % (InstallerTest.__module__, | 294 test_name = '%s.%s.%s' % (InstallerTest.__module__, |
288 InstallerTest.__name__, | 295 InstallerTest.__name__, |
289 test['name']) | 296 test['name']) |
290 if not args.test or test_name in args.test: | 297 if not args.test or test_name in args.test: |
291 suite.addTest(InstallerTest(test['name'], test['traversal'], config, | 298 suite.addTest(InstallerTest(test['name'], test['traversal'], config, |
292 variable_expander)) | 299 variable_expander, args.quiet)) |
293 | 300 |
294 result = unittest.TextTestRunner(verbosity=(args.verbose + 1)).run(suite) | 301 verbosity = 2 if not args.quiet else 1 |
| 302 result = unittest.TextTestRunner(verbosity=verbosity).run(suite) |
295 if is_component_build: | 303 if is_component_build: |
296 print ('Component build is currently unsupported by the mini_installer: ' | 304 print ('Component build is currently unsupported by the mini_installer: ' |
297 'http://crbug.com/377839') | 305 'http://crbug.com/377839') |
298 if args.write_full_results_to: | 306 if args.write_full_results_to: |
299 with open(args.write_full_results_to, 'w') as fp: | 307 with open(args.write_full_results_to, 'w') as fp: |
300 json.dump(_FullResults(suite, result, {}), fp, indent=2) | 308 json.dump(_FullResults(suite, result, {}), fp, indent=2) |
301 fp.write("\n") | 309 fp.write("\n") |
302 return 0 if result.wasSuccessful() else 1 | 310 return 0 if result.wasSuccessful() else 1 |
303 | 311 |
304 | 312 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 trie[path] = value | 372 trie[path] = value |
365 return | 373 return |
366 directory, rest = path.split(TEST_SEPARATOR, 1) | 374 directory, rest = path.split(TEST_SEPARATOR, 1) |
367 if directory not in trie: | 375 if directory not in trie: |
368 trie[directory] = {} | 376 trie[directory] = {} |
369 _AddPathToTrie(trie[directory], rest, value) | 377 _AddPathToTrie(trie[directory], rest, value) |
370 | 378 |
371 | 379 |
372 if __name__ == '__main__': | 380 if __name__ == '__main__': |
373 sys.exit(main()) | 381 sys.exit(main()) |
OLD | NEW |