- add sources.
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / page / profile_generator.py
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
3 # found in the LICENSE file.
4
5 """Handles generating profiles and transferring them to/from mobile devices."""
6
7 import logging
8 import optparse
9 import os
10 import shutil
11 import sys
12 import tempfile
13
14 from telemetry.core import browser_options
15 from telemetry.core import discover
16 from telemetry.core import util
17 from telemetry.page import page_runner
18 from telemetry.page import profile_creator
19 from telemetry.page import test_expectations
20
21
22 def _DiscoverProfileCreatorClasses():
23   profile_creators_dir = os.path.abspath(os.path.join(util.GetBaseDir(),
24       os.pardir, 'perf', 'profile_creators'))
25   base_dir = os.path.abspath(os.path.join(profile_creators_dir, os.pardir))
26
27   profile_creators_unfiltered = discover.DiscoverClasses(
28       profile_creators_dir, base_dir, profile_creator.ProfileCreator)
29
30   # Remove '_creator' suffix from keys.
31   profile_creators = {}
32   for test_name, test_class in profile_creators_unfiltered.iteritems():
33     assert test_name.endswith('_creator')
34     test_name = test_name[:-len('_creator')]
35     profile_creators[test_name] = test_class
36   return profile_creators
37
38 def GenerateProfiles(profile_creator_class, profile_creator_name, options):
39   """Generate a profile"""
40   expectations = test_expectations.TestExpectations()
41   test = profile_creator_class()
42
43   temp_output_directory = tempfile.mkdtemp()
44   options.output_profile_path = temp_output_directory
45
46   results = page_runner.Run(test, test.page_set, expectations, options)
47
48   if results.errors or results.failures:
49     logging.warning('Some pages failed.')
50     if results.errors or results.failures:
51       logging.warning('Failed pages:\n%s',
52                       '\n'.join(zip(*results.errors + results.failures)[0]))
53     return 1
54
55   # Everything is a-ok, move results to final destination.
56   generated_profiles_dir = os.path.abspath(options.output_dir)
57   if not os.path.exists(generated_profiles_dir):
58     os.makedirs(generated_profiles_dir)
59   out_path = os.path.join(generated_profiles_dir, profile_creator_name)
60   if os.path.exists(out_path):
61     shutil.rmtree(out_path)
62
63   # A profile may contain pseudo files like sockets which can't be copied
64   # around by bots.
65   def IsPseudoFile(directory, paths):
66     ignore_list = []
67     for path in paths:
68       full_path = os.path.join(directory, path)
69       if (not os.path.isfile(full_path) and
70           not os.path.isdir(full_path) and
71           not os.path.islink(full_path)):
72         logging.warning('Ignoring pseudo file: %s' % full_path)
73         ignore_list.append(path)
74     return ignore_list
75   shutil.copytree(temp_output_directory, out_path, ignore=IsPseudoFile)
76   shutil.rmtree(temp_output_directory)
77   sys.stderr.write("SUCCESS: Generated profile copied to: '%s'.\n" % out_path)
78
79   return 0
80
81 def Main():
82   profile_creators = _DiscoverProfileCreatorClasses()
83   legal_profile_creators = '|'.join(profile_creators.keys())
84
85   options = browser_options.BrowserFinderOptions()
86   parser = options.CreateParser(
87       "%%prog <--profile-type-to-generate=...> <--browser=...>"
88       " <--output-directory>")
89   page_runner.AddCommandLineOptions(parser)
90
91   group = optparse.OptionGroup(parser, 'Profile generation options')
92   group.add_option('--profile-type-to-generate',
93       dest='profile_type_to_generate',
94       default=None,
95       help='Type of profile to generate. '
96            'Supported values: %s' % legal_profile_creators)
97   group.add_option('--output-dir',
98       dest='output_dir',
99       help='Generated profile is placed in this directory.')
100   parser.add_option_group(group)
101
102   _, _ = parser.parse_args()
103
104   # Sanity check arguments.
105   if not options.profile_type_to_generate:
106     raise Exception("Must specify --profile-type-to-generate option.")
107
108   if options.profile_type_to_generate not in profile_creators.keys():
109     raise Exception("Invalid profile type, legal values are: %s." %
110         legal_profile_creators)
111
112   if not options.browser_type:
113     raise Exception("Must specify --browser option.")
114
115   if not options.output_dir:
116     raise Exception("Must specify --output-dir option.")
117
118   if options.browser_options.dont_override_profile:
119     raise Exception("Can't use existing profile when generating profile.")
120
121   # Generate profile.
122   profile_creator_class = profile_creators[options.profile_type_to_generate]
123   return GenerateProfiles(profile_creator_class,
124       options.profile_type_to_generate, options)