| Index: tools/telemetry/telemetry/test_runner.py
|
| diff --git a/tools/telemetry/telemetry/test_runner.py b/tools/telemetry/telemetry/test_runner.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b4732842aaf4dd3f3d28b8fc84534f5b1c0dcde2
|
| --- /dev/null
|
| +++ b/tools/telemetry/telemetry/test_runner.py
|
| @@ -0,0 +1,166 @@
|
| +# Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +"""Parses the command line, discovers the appropriate tests, and runs them.
|
| +
|
| +Handles test configuration, but all the logic for
|
| +actually running the test is in Test and PageRunner."""
|
| +
|
| +import copy
|
| +import inspect
|
| +import json
|
| +import optparse
|
| +import os
|
| +import sys
|
| +
|
| +from telemetry import test
|
| +from telemetry.core import browser_options
|
| +from telemetry.core import discover
|
| +
|
| +
|
| +class Command(object):
|
| + usage = ''
|
| +
|
| + @property
|
| + def name(self):
|
| + return self.__class__.__name__.lower()
|
| +
|
| + @property
|
| + def description(self):
|
| + return self.__doc__
|
| +
|
| + def CreateParser(self):
|
| + return optparse.OptionParser('%%prog %s %s' % (self.name, self.usage))
|
| +
|
| + def AddParserOptions(self, parser):
|
| + pass
|
| +
|
| + def ValidateCommandLine(self, parser, options, args):
|
| + pass
|
| +
|
| + def Run(self, options, args):
|
| + raise NotImplementedError()
|
| +
|
| +
|
| +class Help(Command):
|
| + """Display help information"""
|
| +
|
| + def Run(self, options, args):
|
| + print >> sys.stderr, ('usage: %s <command> [<args>]' % _GetScriptName())
|
| + print >> sys.stderr, 'Available commands are:'
|
| + for command in COMMANDS:
|
| + print >> sys.stderr, ' %-10s %s' % (command.name, command.description)
|
| + return 0
|
| +
|
| +
|
| +class List(Command):
|
| + """Lists the available tests"""
|
| +
|
| + def AddParserOptions(self, parser):
|
| + parser.add_option('-j', '--json', action='store_true')
|
| +
|
| + def Run(self, options, args):
|
| + if options.json:
|
| + test_list = []
|
| + for test_name, test_class in sorted(_GetTests().items()):
|
| + test_list.append({
|
| + 'name': test_name,
|
| + 'description': test_class.__doc__,
|
| + 'enabled': test_class.enabled,
|
| + 'options': test_class.options,
|
| + })
|
| + print >> sys.stderr, json.dumps(test_list)
|
| + else:
|
| + print >> sys.stderr, 'Available tests are:'
|
| + for test_name, test_class in sorted(_GetTests().items()):
|
| + print >> sys.stderr, ' %-20s %s' % (test_name,
|
| + test_class.__doc__.splitlines()[0])
|
| + return 0
|
| +
|
| +
|
| +class Run(Command):
|
| + """Run one or more tests"""
|
| +
|
| + usage = 'test_name [...] [<args>]'
|
| +
|
| + def CreateParser(self):
|
| + options = browser_options.BrowserOptions()
|
| + parser = options.CreateParser('%%prog %s %s' % (self.name, self.usage))
|
| + return parser
|
| +
|
| + def ValidateCommandLine(self, parser, options, args):
|
| + if not args:
|
| + parser.error('Must provide at least one test name')
|
| + for test_name in args:
|
| + if test_name not in _GetTests():
|
| + parser.error('No test named "%s"' % test_name)
|
| +
|
| + def Run(self, options, args):
|
| + total_failures = 0
|
| + for test_name in args:
|
| + test_failures = _GetTests()[test_name]().Run(copy.copy(options))
|
| + total_failures += test_failures
|
| +
|
| + return min(255, total_failures)
|
| +
|
| +
|
| +COMMANDS = [cls() for _, cls in inspect.getmembers(sys.modules[__name__])
|
| + if inspect.isclass(cls)
|
| + and cls is not Command and issubclass(cls, Command)]
|
| +
|
| +
|
| +def _GetScriptName():
|
| + return os.path.basename(sys.argv[0])
|
| +
|
| +
|
| +def _GetBaseDir():
|
| + main_module = sys.modules['__main__']
|
| + if hasattr(main_module, '__file__'):
|
| + return os.path.dirname(main_module.__file__)
|
| + else:
|
| + return os.getcwd()
|
| +
|
| +
|
| +def _GetTests():
|
| + # Lazy load and cache results.
|
| + if not hasattr(_GetTests, 'tests'):
|
| + base_dir = _GetBaseDir()
|
| + _GetTests.tests = discover.DiscoverClasses(base_dir, base_dir, test.Test,
|
| + index_by_class_name=True)
|
| + return _GetTests.tests
|
| +
|
| +
|
| +def Main():
|
| + # Get the command name from the command line.
|
| + if len(sys.argv) > 1 and sys.argv[1] == '--help':
|
| + sys.argv[1] = 'help'
|
| +
|
| + command_name = 'run'
|
| + for arg in sys.argv[1:]:
|
| + if not arg.startswith('-'):
|
| + command_name = arg
|
| + break
|
| +
|
| + # Validate and interpret the command name.
|
| + commands = [command for command in COMMANDS
|
| + if command.name.startswith(command_name)]
|
| + if len(commands) > 1:
|
| + print >> sys.stderr, ('"%s" is not a %s command. Did you mean one of these?'
|
| + % (command_name, _GetScriptName()))
|
| + for command in commands:
|
| + print >> sys.stderr, ' %-10s %s' % (command.name, command.description)
|
| + return 1
|
| + if commands:
|
| + command = commands[0]
|
| + else:
|
| + command = Run()
|
| +
|
| + # Parse and run the command.
|
| + parser = command.CreateParser()
|
| + command.AddParserOptions(parser)
|
| + options, args = parser.parse_args()
|
| + if commands:
|
| + args = args[1:]
|
| + command.ValidateCommandLine(parser, options, args)
|
| + return command.Run(options, args)
|
|
|