• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
2# for details. All rights reserved. Use of this source code is governed by a
3# BSD-style license that can be found in the LICENSE file.
4
5# Different utility functions used accross scripts
6
7import hashlib
8import os
9import re
10import shutil
11import subprocess
12import sys
13import tempfile
14
15TOOLS_DIR = os.path.abspath(os.path.normpath(os.path.join(__file__, '..')))
16REPO_ROOT = os.path.realpath(os.path.join(TOOLS_DIR, '..'))
17MEMORY_USE_TMP_FILE = 'memory_use.tmp'
18DEX_SEGMENTS_JAR = os.path.join(REPO_ROOT, 'build', 'libs',
19    'dexsegments.jar')
20DEX_SEGMENTS_RESULT_PATTERN = re.compile('- ([^:]+): ([0-9]+)')
21
22def PrintCmd(s):
23  if type(s) is list:
24    s = ' '.join(s)
25  print 'Running: %s' % s
26  # I know this will hit os on windows eventually if we don't do this.
27  sys.stdout.flush()
28
29def IsWindows():
30  return os.name == 'nt'
31
32def DownloadFromGoogleCloudStorage(sha1_file, bucket='r8-deps'):
33  suffix = '.bat' if IsWindows() else ''
34  download_script = 'download_from_google_storage%s' % suffix
35  cmd = [download_script, '-n', '-b', bucket, '-u', '-s',
36         sha1_file]
37  PrintCmd(cmd)
38  subprocess.check_call(cmd)
39
40def get_sha1(filename):
41  sha1 = hashlib.sha1()
42  with open(filename, 'rb') as f:
43    while True:
44      chunk = f.read(1024*1024)
45      if not chunk:
46        break
47      sha1.update(chunk)
48  return sha1.hexdigest()
49
50def makedirs_if_needed(path):
51  try:
52    os.makedirs(path)
53  except OSError:
54    if not os.path.isdir(path):
55        raise
56
57def upload_html_to_cloud_storage(directory, destination):
58  # Upload and make the content encoding right for viewing directly
59  cmd = ['gsutil.py', 'cp', '-z', 'html', '-a',
60         'public-read', '-R', directory, destination]
61  PrintCmd(cmd)
62  subprocess.check_call(cmd)
63
64class TempDir(object):
65 def __init__(self, prefix=''):
66   self._temp_dir = None
67   self._prefix = prefix
68
69 def __enter__(self):
70   self._temp_dir = tempfile.mkdtemp(self._prefix)
71   return self._temp_dir
72
73 def __exit__(self, *_):
74   shutil.rmtree(self._temp_dir, ignore_errors=True)
75
76class ChangedWorkingDirectory(object):
77 def __init__(self, working_directory):
78   self._working_directory = working_directory
79
80 def __enter__(self):
81   self._old_cwd = os.getcwd()
82   print 'Enter directory = ', self._working_directory
83   os.chdir(self._working_directory)
84
85 def __exit__(self, *_):
86   print 'Enter directory = ', self._old_cwd
87   os.chdir(self._old_cwd)
88
89# Reading Android CTS test_result.xml
90
91class CtsModule(object):
92  def __init__(self, module_name):
93    self.name = module_name
94
95class CtsTestCase(object):
96  def __init__(self, test_case_name):
97    self.name = test_case_name
98
99class CtsTest(object):
100  def __init__(self, test_name, outcome):
101    self.name = test_name
102    self.outcome = outcome
103
104# Generator yielding CtsModule, CtsTestCase or CtsTest from
105# reading through a CTS test_result.xml file.
106def read_cts_test_result(file_xml):
107  re_module = re.compile('<Module name="([^"]*)"')
108  re_test_case = re.compile('<TestCase name="([^"]*)"')
109  re_test = re.compile('<Test result="(pass|fail)" name="([^"]*)"')
110  with open(file_xml) as f:
111    for line in f:
112      m = re_module.search(line)
113      if m:
114        yield CtsModule(m.groups()[0])
115        continue
116      m = re_test_case.search(line)
117      if m:
118        yield CtsTestCase(m.groups()[0])
119        continue
120      m = re_test.search(line)
121      if m:
122        outcome = m.groups()[0]
123        assert outcome in ['fail', 'pass']
124        yield CtsTest(m.groups()[1], outcome == 'pass')
125
126def grep_memoryuse(logfile):
127  re_vmhwm = re.compile('^VmHWM:[ \t]*([0-9]+)[ \t]*([a-zA-Z]*)')
128  result = None
129  with open(logfile) as f:
130    for line in f:
131      m = re_vmhwm.search(line)
132      if m:
133        groups = m.groups()
134        s = len(groups)
135        if s >= 1:
136          result = int(groups[0])
137          if s >= 2:
138            unit = groups[1]
139            if unit == 'kB':
140              result *= 1024
141            elif unit != '':
142              raise Exception('Unrecognized unit in memory usage log: {}'
143                  .format(unit))
144  if result is None:
145    raise Exception('No memory usage found in log: {}'.format(logfile))
146  return result
147
148# Return a dictionary: {segment_name -> segments_size}
149def getDexSegmentSizes(dex_files):
150  assert len(dex_files) > 0
151  cmd = ['java', '-jar', DEX_SEGMENTS_JAR]
152  cmd.extend(dex_files)
153  PrintCmd(cmd)
154  output = subprocess.check_output(cmd)
155
156  matches = DEX_SEGMENTS_RESULT_PATTERN.findall(output)
157
158  if matches is None or len(matches) == 0:
159    raise Exception('DexSegments failed to return any output for' \
160        ' these files: {}'.format(dex_files))
161
162  result = {}
163
164  for match in matches:
165    result[match[0]] = int(match[1])
166
167  return result
168
169def print_dexsegments(prefix, dex_files):
170  for segment_name, size in getDexSegmentSizes(dex_files).items():
171    print('{}-{}(CodeSize): {}'
172        .format(prefix, segment_name, size))
173