| 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 |