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 """ |
11 | 11 |
12 import argparse | 12 import argparse |
| 13 import datetime |
| 14 import inspect |
13 import json | 15 import json |
14 import os | 16 import os |
15 import subprocess | 17 import subprocess |
16 import sys | 18 import sys |
17 import time | 19 import time |
18 import unittest | 20 import unittest |
19 import _winreg | 21 import _winreg |
20 | 22 |
21 from variable_expander import VariableExpander | 23 from variable_expander import VariableExpander |
22 import verifier_runner | 24 import verifier_runner |
23 | 25 |
24 | 26 |
| 27 def LogMessage(message): |
| 28 """Logs a message to stderr. |
| 29 |
| 30 Args: |
| 31 message: The message string to be logged. |
| 32 """ |
| 33 now = datetime.datetime.now() |
| 34 frameinfo = inspect.getframeinfo(inspect.currentframe().f_back) |
| 35 filename = os.path.basename(frameinfo.filename) |
| 36 line = frameinfo.lineno |
| 37 sys.stderr.write('[%s:%s(%s)] %s\n' % (now.strftime('%m%d/%H%M%S'), |
| 38 filename, line, message)) |
| 39 |
| 40 |
25 class Config: | 41 class Config: |
26 """Describes the machine states, actions, and test cases. | 42 """Describes the machine states, actions, and test cases. |
27 | 43 |
28 Attributes: | 44 Attributes: |
29 states: A dictionary where each key is a state name and the associated value | 45 states: A dictionary where each key is a state name and the associated value |
30 is a property dictionary describing that state. | 46 is a property dictionary describing that state. |
31 actions: A dictionary where each key is an action name and the associated | 47 actions: A dictionary where each key is an action name and the associated |
32 value is the action's command. | 48 value is the action's command. |
33 tests: An array of test cases. | 49 tests: An array of test cases. |
34 """ | 50 """ |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 self.assertEqual(1, len(self._test) % 2, | 99 self.assertEqual(1, len(self._test) % 2, |
84 'The length of test array must be odd') | 100 'The length of test array must be odd') |
85 | 101 |
86 state = self._test[0] | 102 state = self._test[0] |
87 self._VerifyState(state) | 103 self._VerifyState(state) |
88 | 104 |
89 # Starting at index 1, we loop through pairs of (action, state). | 105 # Starting at index 1, we loop through pairs of (action, state). |
90 for i in range(1, len(self._test), 2): | 106 for i in range(1, len(self._test), 2): |
91 action = self._test[i] | 107 action = self._test[i] |
92 if not self._quiet: | 108 if not self._quiet: |
93 sys.stderr.write('Beginning action %s\n' % action) | 109 LogMessage('Beginning action %s' % action) |
94 RunCommand(self._config.actions[action], self._variable_expander) | 110 RunCommand(self._config.actions[action], self._variable_expander) |
95 if not self._quiet: | 111 if not self._quiet: |
96 sys.stderr.write('Finished action %s\n' % action) | 112 LogMessage('Finished action %s' % action) |
97 | 113 |
98 state = self._test[i + 1] | 114 state = self._test[i + 1] |
99 self._VerifyState(state) | 115 self._VerifyState(state) |
100 | 116 |
101 # If the test makes it here, it means it was successful, because RunCommand | 117 # If the test makes it here, it means it was successful, because RunCommand |
102 # and _VerifyState throw an exception on failure. | 118 # and _VerifyState throw an exception on failure. |
103 self._clean_on_teardown = False | 119 self._clean_on_teardown = False |
104 | 120 |
105 def tearDown(self): | 121 def tearDown(self): |
106 """Cleans up the machine if the test case fails.""" | 122 """Cleans up the machine if the test case fails.""" |
(...skipping 10 matching lines...) Expand all Loading... |
117 """ | 133 """ |
118 return None | 134 return None |
119 | 135 |
120 def _VerifyState(self, state): | 136 def _VerifyState(self, state): |
121 """Verifies that the current machine state matches a given state. | 137 """Verifies that the current machine state matches a given state. |
122 | 138 |
123 Args: | 139 Args: |
124 state: A state name. | 140 state: A state name. |
125 """ | 141 """ |
126 if not self._quiet: | 142 if not self._quiet: |
127 sys.stderr.write('Verifying state %s\n' % state) | 143 LogMessage('Verifying state %s' % state) |
128 try: | 144 try: |
129 self._verifier_runner.VerifyAll(self._config.states[state], | 145 self._verifier_runner.VerifyAll(self._config.states[state], |
130 self._variable_expander) | 146 self._variable_expander) |
131 except AssertionError as e: | 147 except AssertionError as e: |
132 # If an AssertionError occurs, we intercept it and add the state name | 148 # If an AssertionError occurs, we intercept it and add the state name |
133 # to the error message so that we know where the test fails. | 149 # to the error message so that we know where the test fails. |
134 raise AssertionError("In state '%s', %s" % (state, e)) | 150 raise AssertionError("In state '%s', %s" % (state, e)) |
135 | 151 |
136 | 152 |
137 def RunCommand(command, variable_expander): | 153 def RunCommand(command, variable_expander): |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 test_name = '%s/%s/%s' % (InstallerTest.__module__, | 331 test_name = '%s/%s/%s' % (InstallerTest.__module__, |
316 InstallerTest.__name__, | 332 InstallerTest.__name__, |
317 test['name']) | 333 test['name']) |
318 if not args.test or test_name in args.test: | 334 if not args.test or test_name in args.test: |
319 suite.addTest(InstallerTest(test['name'], test['traversal'], config, | 335 suite.addTest(InstallerTest(test['name'], test['traversal'], config, |
320 variable_expander, args.quiet)) | 336 variable_expander, args.quiet)) |
321 | 337 |
322 verbosity = 2 if not args.quiet else 1 | 338 verbosity = 2 if not args.quiet else 1 |
323 result = unittest.TextTestRunner(verbosity=verbosity).run(suite) | 339 result = unittest.TextTestRunner(verbosity=verbosity).run(suite) |
324 if is_component_build: | 340 if is_component_build: |
325 print ('Component build is currently unsupported by the mini_installer: ' | 341 sys.stderr.write('Component build is currently unsupported by the ' |
326 'http://crbug.com/377839') | 342 'mini_installer: http://crbug.com/377839\n') |
327 if args.write_full_results_to: | 343 if args.write_full_results_to: |
328 with open(args.write_full_results_to, 'w') as fp: | 344 with open(args.write_full_results_to, 'w') as fp: |
329 json.dump(_FullResults(suite, result, {}), fp, indent=2) | 345 json.dump(_FullResults(suite, result, {}), fp, indent=2) |
330 fp.write("\n") | 346 fp.write('\n') |
331 return 0 if result.wasSuccessful() else 1 | 347 return 0 if result.wasSuccessful() else 1 |
332 | 348 |
333 | 349 |
334 # TODO(dpranke): Find a way for this to be shared with the mojo and other tests. | 350 # TODO(dpranke): Find a way for this to be shared with the mojo and other tests. |
335 TEST_SEPARATOR = '.' | 351 TEST_SEPARATOR = '.' |
336 | 352 |
337 | 353 |
338 def _FullResults(suite, result, metadata): | 354 def _FullResults(suite, result, metadata): |
339 """Convert the unittest results to the Chromium JSON test result format. | 355 """Convert the unittest results to the Chromium JSON test result format. |
340 | 356 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 trie[path] = value | 409 trie[path] = value |
394 return | 410 return |
395 directory, rest = path.split(TEST_SEPARATOR, 1) | 411 directory, rest = path.split(TEST_SEPARATOR, 1) |
396 if directory not in trie: | 412 if directory not in trie: |
397 trie[directory] = {} | 413 trie[directory] = {} |
398 _AddPathToTrie(trie[directory], rest, value) | 414 _AddPathToTrie(trie[directory], rest, value) |
399 | 415 |
400 | 416 |
401 if __name__ == '__main__': | 417 if __name__ == '__main__': |
402 sys.exit(main()) | 418 sys.exit(main()) |
OLD | NEW |