- add sources.
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / page / page_test_runner.py
1 # Copyright (c) 2012 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 import os
5 import sys
6
7 from telemetry import test as test_module
8 from telemetry.core import browser_options
9 from telemetry.core import discover
10 from telemetry.page import page_test as page_test_module
11 from telemetry.page import page_runner
12 from telemetry.page import page_set
13
14 def Main(base_dir, page_set_filenames):
15   """Turns a PageTest into a command-line program.
16
17   Args:
18     base_dir: Path to directory containing tests and ProfileCreators.
19   """
20   runner = PageTestRunner()
21   sys.exit(runner.Run(base_dir, page_set_filenames))
22
23 class PageTestRunner(object):
24   def __init__(self):
25     self._parser = None
26     self._options = None
27     self._args = None
28
29   @property
30   def test_class(self):
31     return page_test_module.PageTest
32
33   @property
34   def test_class_name(self):
35     return 'test'
36
37   def Run(self, base_dir, page_set_filenames):
38     test, ps, expectations = self.ParseCommandLine(sys.argv, base_dir,
39         page_set_filenames)
40     results = page_runner.Run(test, ps, expectations, self._options)
41     results.PrintSummary()
42     return min(255, len(results.failures + results.errors))
43
44   def FindTestConstructors(self, base_dir):
45     # Look for both Tests and PageTests, but Tests get priority, because
46     test_constructors = discover.DiscoverClasses(
47         base_dir, base_dir, self.test_class)
48     test_constructors.update(discover.DiscoverClasses(
49         base_dir, base_dir, test_module.Test, index_by_class_name=True))
50     return test_constructors
51
52   def FindTestName(self, test_constructors, args):
53     """Find the test name in an arbitrary argument list.
54
55     We can't use the optparse parser, because the test may add its own
56     command-line options. If the user passed in any of those, the
57     optparse parsing will fail.
58
59     Returns:
60       test_name or None
61     """
62     test_name = None
63     for arg in [self.GetModernizedTestName(a) for a in args]:
64       if arg in test_constructors:
65         test_name = arg
66
67     return test_name
68
69   def GetModernizedTestName(self, arg):
70     """Sometimes tests change names but buildbots keep calling the old name.
71
72     If arg matches an old test name, return the new test name instead.
73     Otherwise, return the arg.
74     """
75     return arg
76
77   def GetPageSet(self, test, page_set_filenames):
78     ps = test.CreatePageSet(self._args, self._options)
79     if ps:
80       return ps
81
82     if len(self._args) < 2:
83       page_set_list = ',\n'.join(
84           sorted([os.path.relpath(f) for f in page_set_filenames]))
85       self.PrintParseError(
86           'No page set, file, or URL specified.\n'
87           'Available page sets:\n'
88           '%s' % page_set_list)
89
90     page_set_arg = self._args[1]
91
92     # We've been given a URL. Create a page set with just that URL.
93     if (page_set_arg.startswith('http://') or
94         page_set_arg.startswith('https://')):
95       self._options.allow_live_sites = True
96       return page_set.PageSet.FromDict({
97           'pages': [{'url': page_set_arg}]
98           }, os.path.dirname(__file__))
99
100     # We've been given a page set JSON. Load it.
101     if page_set_arg.endswith('.json'):
102       return page_set.PageSet.FromFile(page_set_arg)
103
104     # We've been given a file or directory. Create a page set containing it.
105     if os.path.exists(page_set_arg):
106       page_set_dict = {'pages': []}
107
108       def _AddFile(file_path):
109         page_set_dict['pages'].append({'url': 'file://' + file_path})
110
111       def _AddDir(dir_path):
112         for path in os.listdir(dir_path):
113           path = os.path.join(dir_path, path)
114           _AddPath(path)
115
116       def _AddPath(path):
117         if os.path.isdir(path):
118           _AddDir(path)
119         else:
120           _AddFile(path)
121
122       _AddPath(page_set_arg)
123       return page_set.PageSet.FromDict(page_set_dict, os.getcwd() + os.sep)
124
125     raise Exception('Did not understand "%s". Pass a page set, file or URL.' %
126                     page_set_arg)
127
128   def ParseCommandLine(self, args, base_dir, page_set_filenames):
129     self._options = browser_options.BrowserFinderOptions()
130     self._parser = self._options.CreateParser(
131         '%%prog [options] %s page_set' % self.test_class_name)
132
133     test_constructors = self.FindTestConstructors(base_dir)
134     test_name = self.FindTestName(test_constructors, args)
135     test = None
136     if test_name:
137       test = test_constructors[test_name]()
138       if isinstance(test, test_module.Test):
139         page_test = test.test()
140       else:
141         page_test = test
142       page_test.AddCommandLineOptions(self._parser)
143     page_runner.AddCommandLineOptions(self._parser)
144
145     _, self._args = self._parser.parse_args()
146
147     if len(self._args) < 1:
148       error_message = 'No %s specified.\nAvailable %ss:\n' % (
149           self.test_class_name, self.test_class_name)
150       test_list_string = ',\n'.join(sorted(test_constructors.keys()))
151       self.PrintParseError(error_message + test_list_string)
152
153     if not test:
154       error_message = 'No %s named %s.\nAvailable %ss:\n' % (
155           self.test_class_name, self._args[0], self.test_class_name)
156       test_list_string = ',\n'.join(sorted(test_constructors.keys()))
157       self.PrintParseError(error_message + test_list_string)
158
159     if isinstance(test, test_module.Test):
160       ps = test.CreatePageSet(self._options)
161       expectations = test.CreateExpectations(ps)
162     else:
163       ps = self.GetPageSet(test, page_set_filenames)
164       expectations = test.CreateExpectations(ps)
165
166     if len(self._args) > 2:
167       self.PrintParseError('Too many arguments.')
168
169     return page_test, ps, expectations
170
171   def PrintParseError(self, message):
172     self._parser.error(message)