1#!/usr/bin/env python 2# Copyright (c) 2012 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""Script for a testing an existing SDK. 7 8This script is normally run immediately after build_sdk.py. 9""" 10 11import optparse 12import os 13import subprocess 14import sys 15 16import buildbot_common 17import build_projects 18import build_sdk 19import build_version 20import parse_dsc 21 22SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 23SDK_SRC_DIR = os.path.dirname(SCRIPT_DIR) 24SDK_LIBRARY_DIR = os.path.join(SDK_SRC_DIR, 'libraries') 25SDK_DIR = os.path.dirname(SDK_SRC_DIR) 26SRC_DIR = os.path.dirname(SDK_DIR) 27OUT_DIR = os.path.join(SRC_DIR, 'out') 28 29sys.path.append(os.path.join(SDK_SRC_DIR, 'tools')) 30import getos 31 32def StepBuildExamples(pepperdir): 33 for config in ('Debug', 'Release'): 34 build_sdk.BuildStepMakeAll(pepperdir, 'getting_started', 35 'Build Getting Started (%s)' % config, 36 deps=False, config=config) 37 38 build_sdk.BuildStepMakeAll(pepperdir, 'examples', 39 'Build Examples (%s)' % config, 40 deps=False, config=config) 41 42 43def StepCopyTests(pepperdir, toolchains, build_experimental): 44 buildbot_common.BuildStep('Copy Tests') 45 46 # Update test libraries and test apps 47 filters = { 48 'DEST': ['tests'] 49 } 50 if not build_experimental: 51 filters['EXPERIMENTAL'] = False 52 53 tree = parse_dsc.LoadProjectTree(SDK_SRC_DIR, include=filters) 54 build_projects.UpdateHelpers(pepperdir, clobber=False) 55 build_projects.UpdateProjects(pepperdir, tree, clobber=False, 56 toolchains=toolchains) 57 58 59def StepBuildTests(pepperdir): 60 for config in ('Debug', 'Release'): 61 build_sdk.BuildStepMakeAll(pepperdir, 'tests', 62 'Build Tests (%s)' % config, 63 deps=False, config=config) 64 65 66def StepRunSelLdrTests(pepperdir, sanitizer): 67 filters = { 68 'SEL_LDR': True 69 } 70 71 tree = parse_dsc.LoadProjectTree(SDK_SRC_DIR, include=filters) 72 73 def RunTest(test, toolchain, config, arch=None): 74 args = ['STANDALONE=1', 'TOOLCHAIN=%s' % toolchain] 75 if arch is not None: 76 args.append('NACL_ARCH=%s' % arch) 77 deps = False 78 79 if sanitizer is not None: 80 # For sanitizer builds we pass extra argument for make, and do 81 # full clean build to make sure everything is rebuilt with the 82 # correct flags 83 deps = True 84 if sanitizer == 'valgrind': 85 args += ['RUN_UNDER=valgrind'] 86 else: 87 args += ['CC=clang', 'CXX=clang++', 88 'LDFLAGS=-pie -fsanitize=' + sanitizer, 89 'CFLAGS=-fPIC -fsanitize=' + sanitizer] 90 build_projects.BuildProjectsBranch(pepperdir, 'src', clean=False, 91 deps=deps, config=config, 92 args=args + ['clean']) 93 build_projects.BuildProjectsBranch(pepperdir, 'tests', clean=False, 94 deps=deps, config=config, 95 args=args + ['clean']) 96 97 build_projects.BuildProjectsBranch(pepperdir, test, clean=False, 98 deps=deps, config=config, 99 args=args + ['run']) 100 101 if getos.GetPlatform() == 'win': 102 # On win32 we only support running on the system 103 # arch 104 archs = (getos.GetSystemArch('win'),) 105 elif getos.GetPlatform() == 'mac': 106 # We only ship 32-bit version of sel_ldr on mac. 107 archs = ('x86_32',) 108 else: 109 # On linux we can run both 32 and 64-bit 110 archs = ('x86_64', 'x86_32') 111 112 for root, projects in tree.iteritems(): 113 for project in projects: 114 if sanitizer: 115 sanitizer_name = '[sanitizer=%s]' % sanitizer 116 else: 117 sanitizer_name = '' 118 title = 'standalone test%s: %s' % (sanitizer_name, 119 os.path.basename(project['NAME'])) 120 location = os.path.join(root, project['NAME']) 121 buildbot_common.BuildStep(title) 122 configs = ('Debug', 'Release') 123 124 # On linux we can run the standalone tests natively using the host 125 # compiler. 126 if getos.GetPlatform() == 'linux': 127 if sanitizer: 128 configs = ('Debug',) 129 for config in configs: 130 RunTest(location, 'linux', config) 131 132 if sanitizer: 133 continue 134 135 for toolchain in ('newlib', 'glibc'): 136 for arch in archs: 137 for config in configs: 138 RunTest(location, toolchain, config, arch) 139 140 141def StepRunBrowserTests(toolchains, experimental): 142 buildbot_common.BuildStep('Run Tests') 143 144 args = [ 145 sys.executable, 146 os.path.join(SCRIPT_DIR, 'test_projects.py'), 147 '--retry-times=3', 148 ] 149 150 if experimental: 151 args.append('-x') 152 for toolchain in toolchains: 153 args.extend(['-t', toolchain]) 154 155 try: 156 subprocess.check_call(args) 157 except subprocess.CalledProcessError: 158 buildbot_common.ErrorExit('Error running tests.') 159 160 161def main(args): 162 usage = '%prog [<options>] [<phase...>]' 163 parser = optparse.OptionParser(description=__doc__, usage=usage) 164 parser.add_option('--experimental', help='build experimental tests', 165 action='store_true') 166 parser.add_option('--sanitizer', 167 help='Run sanitizer (asan/tsan/valgrind) tests', 168 action='store_true') 169 parser.add_option('--verbose', '-v', help='Verbose output', 170 action='store_true') 171 172 if 'NACL_SDK_ROOT' in os.environ: 173 # We don't want the currently configured NACL_SDK_ROOT to have any effect 174 # of the build. 175 del os.environ['NACL_SDK_ROOT'] 176 177 # To setup bash completion for this command first install optcomplete 178 # and then add this line to your .bashrc: 179 # complete -F _optcomplete test_sdk.py 180 try: 181 import optcomplete 182 optcomplete.autocomplete(parser) 183 except ImportError: 184 pass 185 186 options, args = parser.parse_args(args[1:]) 187 188 pepper_ver = str(int(build_version.ChromeMajorVersion())) 189 pepperdir = os.path.join(OUT_DIR, 'pepper_' + pepper_ver) 190 toolchains = ['newlib', 'glibc', 'pnacl'] 191 toolchains.append(getos.GetPlatform()) 192 193 if options.verbose: 194 build_projects.verbose = True 195 196 phases = [ 197 ('build_examples', StepBuildExamples, pepperdir), 198 ('copy_tests', StepCopyTests, pepperdir, toolchains, options.experimental), 199 ('build_tests', StepBuildTests, pepperdir), 200 ('sel_ldr_tests', StepRunSelLdrTests, pepperdir, None), 201 ('browser_tests', StepRunBrowserTests, toolchains, options.experimental), 202 ] 203 204 if options.sanitizer: 205 if getos.GetPlatform() != 'linux': 206 buildbot_common.ErrorExit('sanitizer tests only run on linux.') 207 phases += [ 208 ('sel_ldr_tests_asan', StepRunSelLdrTests, pepperdir, 'address'), 209 ('sel_ldr_tests_tsan', StepRunSelLdrTests, pepperdir, 'thread'), 210 ('sel_ldr_tests_valgrind', StepRunSelLdrTests, pepperdir, 'valgrind') 211 ] 212 213 if args: 214 phase_names = [p[0] for p in phases] 215 for arg in args: 216 if arg not in phase_names: 217 msg = 'Invalid argument: %s\n' % arg 218 msg += 'Possible arguments:\n' 219 for name in phase_names: 220 msg += ' %s\n' % name 221 parser.error(msg.strip()) 222 223 for phase in phases: 224 phase_name = phase[0] 225 if args and phase_name not in args: 226 continue 227 phase_func = phase[1] 228 phase_args = phase[2:] 229 phase_func(*phase_args) 230 231 return 0 232 233 234if __name__ == '__main__': 235 try: 236 sys.exit(main(sys.argv)) 237 except KeyboardInterrupt: 238 buildbot_common.ErrorExit('test_sdk: interrupted') 239