• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
7import logging
8import optparse
9import os
10import shutil
11import sys
12import tempfile
13
14from telemetry.core import browser_options
15from telemetry.core import discover
16from telemetry.core import util
17from telemetry.page import page_runner
18from telemetry.page import profile_creator
19from telemetry.page import test_expectations
20
21
22def _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
39def GenerateProfiles(profile_creator_class, profile_creator_name, options):
40  """Generate a profile"""
41  expectations = test_expectations.TestExpectations()
42  test = profile_creator_class()
43
44  temp_output_directory = tempfile.mkdtemp()
45  options.output_profile_path = temp_output_directory
46
47  results = page_runner.Run(test, test.page_set, expectations, options)
48
49  if results.errors or results.failures:
50    logging.warning('Some pages failed.')
51    if results.errors or results.failures:
52      logging.warning('Failed pages:\n%s',
53                      '\n'.join(zip(*results.errors + results.failures)[0]))
54    return 1
55
56  # Everything is a-ok, move results to final destination.
57  generated_profiles_dir = os.path.abspath(options.output_dir)
58  if not os.path.exists(generated_profiles_dir):
59    os.makedirs(generated_profiles_dir)
60  out_path = os.path.join(generated_profiles_dir, profile_creator_name)
61  if os.path.exists(out_path):
62    shutil.rmtree(out_path)
63
64  # A profile may contain pseudo files like sockets which can't be copied
65  # around by bots.
66  def IsPseudoFile(directory, paths):
67    ignore_list = []
68    for path in paths:
69      full_path = os.path.join(directory, path)
70      if (not os.path.isfile(full_path) and
71          not os.path.isdir(full_path) and
72          not os.path.islink(full_path)):
73        logging.warning('Ignoring pseudo file: %s' % full_path)
74        ignore_list.append(path)
75    return ignore_list
76  shutil.copytree(temp_output_directory, out_path, ignore=IsPseudoFile)
77  shutil.rmtree(temp_output_directory)
78  sys.stderr.write("SUCCESS: Generated profile copied to: '%s'.\n" % out_path)
79
80  return 0
81
82
83def AddCommandLineArgs(parser):
84  page_runner.AddCommandLineArgs(parser)
85
86  profile_creators = _DiscoverProfileCreatorClasses().keys()
87  legal_profile_creators = '|'.join(profile_creators)
88  group = optparse.OptionGroup(parser, 'Profile generation options')
89  group.add_option('--profile-type-to-generate',
90      dest='profile_type_to_generate',
91      default=None,
92      help='Type of profile to generate. '
93           'Supported values: %s' % legal_profile_creators)
94  group.add_option('--output-dir',
95      dest='output_dir',
96      help='Generated profile is placed in this directory.')
97  parser.add_option_group(group)
98
99
100def ProcessCommandLineArgs(parser, args):
101  page_runner.ProcessCommandLineArgs(parser, args)
102
103  if not args.profile_type_to_generate:
104    parser.error("Must specify --profile-type-to-generate option.")
105
106  profile_creators = _DiscoverProfileCreatorClasses().keys()
107  if args.profile_type_to_generate not in profile_creators:
108    legal_profile_creators = '|'.join(profile_creators)
109    parser.error("Invalid profile type, legal values are: %s." %
110        legal_profile_creators)
111
112  if not args.browser_type:
113    parser.error("Must specify --browser option.")
114
115  if not args.output_dir:
116    parser.error("Must specify --output-dir option.")
117
118  if args.browser_options.dont_override_profile:
119    parser.error("Can't use existing profile when generating profile.")
120
121
122def Main():
123  options = browser_options.BrowserFinderOptions()
124  parser = options.CreateParser(
125      "%%prog <--profile-type-to-generate=...> <--browser=...>"
126      " <--output-directory>")
127  AddCommandLineArgs(parser)
128  _, _ = parser.parse_args()
129  ProcessCommandLineArgs(parser, options)
130
131  # Generate profile.
132  profile_creators = _DiscoverProfileCreatorClasses()
133  profile_creator_class = profile_creators[options.profile_type_to_generate]
134  return GenerateProfiles(profile_creator_class,
135      options.profile_type_to_generate, options)
136