1#!/usr/bin/env python
2#
3# Copyright 2016 Google Inc.
4#
5# Use of this source code is governed by a BSD-style license that can be
6# found in the LICENSE file.
7
8
9import os
10import subprocess
11import sys
12
13from flavor import android_flavor
14from flavor import chromeos_flavor
15from flavor import cmake_flavor
16from flavor import coverage_flavor
17from flavor import default_flavor
18from flavor import ios_flavor
19from flavor import valgrind_flavor
20from flavor import xsan_flavor
21
22
23CONFIG_COVERAGE = 'Coverage'
24CONFIG_DEBUG = 'Debug'
25CONFIG_RELEASE = 'Release'
26VALID_CONFIGS = (CONFIG_COVERAGE, CONFIG_DEBUG, CONFIG_RELEASE)
27
28GM_ACTUAL_FILENAME = 'actual-results.json'
29GM_EXPECTATIONS_FILENAME = 'expected-results.json'
30GM_IGNORE_TESTS_FILENAME = 'ignored-tests.txt'
31
32GS_GM_BUCKET = 'chromium-skia-gm'
33GS_SUMMARIES_BUCKET = 'chromium-skia-gm-summaries'
34
35SKIA_REPO = 'https://skia.googlesource.com/skia.git'
36INFRA_REPO = 'https://skia.googlesource.com/buildbot.git'
37
38SERVICE_ACCOUNT_FILE = 'service-account-skia.json'
39SERVICE_ACCOUNT_INTERNAL_FILE = 'service-account-skia-internal.json'
40
41
42def is_android(bot_cfg):
43  """Determine whether the given bot is an Android bot."""
44  return ('Android' in bot_cfg.get('extra_config', '') or
45          bot_cfg.get('os') == 'Android')
46
47def is_chromeos(bot_cfg):
48  return ('CrOS' in bot_cfg.get('extra_config', '') or
49          bot_cfg.get('os') == 'ChromeOS')
50
51def is_cmake(bot_cfg):
52  return 'CMake' in bot_cfg.get('extra_config', '')
53
54def is_ios(bot_cfg):
55  return ('iOS' in bot_cfg.get('extra_config', '') or
56          bot_cfg.get('os') == 'iOS')
57
58
59def is_valgrind(bot_cfg):
60  return 'Valgrind' in bot_cfg.get('extra_config', '')
61
62
63def is_xsan(bot_cfg):
64  return (bot_cfg.get('extra_config') == 'ASAN' or
65          bot_cfg.get('extra_config') == 'MSAN' or
66          bot_cfg.get('extra_config') == 'TSAN')
67
68
69class BotInfo(object):
70  def __init__(self, bot_name, slave_name, out_dir):
71    """Initialize the bot, given its name.
72
73    Assumes that CWD is the directory containing this file.
74    """
75    self.name = bot_name
76    self.slave_name = slave_name
77    self.skia_dir = os.path.abspath(os.path.join(
78        os.path.dirname(os.path.realpath(__file__)),
79        os.pardir, os.pardir))
80    os.chdir(self.skia_dir)
81    self.build_dir = os.path.abspath(os.path.join(self.skia_dir, os.pardir))
82    self.out_dir = out_dir
83    self.spec = self.get_bot_spec(bot_name)
84    self.configuration = self.spec['configuration']
85    self.default_env = {
86      'SKIA_OUT': self.out_dir,
87      'BUILDTYPE': self.configuration,
88      'PATH': os.environ['PATH'],
89    }
90    self.default_env.update(self.spec['env'])
91    self.build_targets = [str(t) for t in self.spec['build_targets']]
92    self.bot_cfg = self.spec['builder_cfg']
93    self.is_trybot = self.bot_cfg['is_trybot']
94    self.upload_dm_results = self.spec['upload_dm_results']
95    self.upload_perf_results = self.spec['upload_perf_results']
96    self.dm_flags = self.spec['dm_flags']
97    self.nanobench_flags = self.spec['nanobench_flags']
98    self._ccache = None
99    self._checked_for_ccache = False
100    self.flavor = self.get_flavor(self.bot_cfg)
101
102  @property
103  def ccache(self):
104    if not self._checked_for_ccache:
105      self._checked_for_ccache = True
106      if sys.platform != 'win32':
107        try:
108          result = subprocess.check_output(['which', 'ccache'])
109          self._ccache = result.rstrip()
110        except subprocess.CalledProcessError:
111          pass
112
113    return self._ccache
114
115  def get_bot_spec(self, bot_name):
116    """Retrieve the bot spec for this bot."""
117    sys.path.append(self.skia_dir)
118    from tools import buildbot_spec
119    return buildbot_spec.get_builder_spec(bot_name)
120
121  def get_flavor(self, bot_cfg):
122    """Return a flavor utils object specific to the given bot."""
123    if is_android(bot_cfg):
124      return android_flavor.AndroidFlavorUtils(self)
125    elif is_chromeos(bot_cfg):
126      return chromeos_flavor.ChromeOSFlavorUtils(self)
127    elif is_cmake(bot_cfg):
128      return cmake_flavor.CMakeFlavorUtils(self)
129    elif is_ios(bot_cfg):
130      return ios_flavor.iOSFlavorUtils(self)
131    elif is_valgrind(bot_cfg):
132      return valgrind_flavor.ValgrindFlavorUtils(self)
133    elif is_xsan(bot_cfg):
134      return xsan_flavor.XSanFlavorUtils(self)
135    elif bot_cfg.get('configuration') == CONFIG_COVERAGE:
136      return coverage_flavor.CoverageFlavorUtils(self)
137    else:
138      return default_flavor.DefaultFlavorUtils(self)
139
140  def run(self, cmd, env=None, cwd=None):
141    _env = {}
142    _env.update(self.default_env)
143    _env.update(env or {})
144    cwd = cwd or self.skia_dir
145    print '============'
146    print 'CMD: %s' % cmd
147    print 'CWD: %s' % cwd
148    print 'ENV: %s' % _env
149    print '============'
150    subprocess.check_call(cmd, env=_env, cwd=cwd)
151