summary refs log tree commit diff
path: root/build_test.py
diff options
context:
space:
mode:
authorZach Reizner <zachr@google.com>2017-08-30 17:08:59 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-09-01 12:39:19 -0700
commit451dd3bdabaae658346a6f5fa247f3f69da19322 (patch)
treec3c5c164a135517cd1430efcd8c172f05262c234 /build_test.py
parent3cbded2c51574bfdefe8d26a9c6ff235c7330b59 (diff)
downloadcrosvm-451dd3bdabaae658346a6f5fa247f3f69da19322.tar
crosvm-451dd3bdabaae658346a6f5fa247f3f69da19322.tar.gz
crosvm-451dd3bdabaae658346a6f5fa247f3f69da19322.tar.bz2
crosvm-451dd3bdabaae658346a6f5fa247f3f69da19322.tar.lz
crosvm-451dd3bdabaae658346a6f5fa247f3f69da19322.tar.xz
crosvm-451dd3bdabaae658346a6f5fa247f3f69da19322.tar.zst
crosvm-451dd3bdabaae658346a6f5fa247f3f69da19322.zip
add build_test script to automate crosvm test running
TEST=./build_test && cros lint build_test.py
BUG=None

Change-Id: I11de92ab1c854264b762c3bb2e3ebda9d3f4b007
Reviewed-on: https://chromium-review.googlesource.com/644409
Commit-Ready: Zach Reizner <zachr@chromium.org>
Tested-by: Zach Reizner <zachr@chromium.org>
Reviewed-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'build_test.py')
-rwxr-xr-xbuild_test.py168
1 files changed, 168 insertions, 0 deletions
diff --git a/build_test.py b/build_test.py
new file mode 100755
index 0000000..4064db1
--- /dev/null
+++ b/build_test.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python3
+
+"""Builds crosvm in debug/release mode on all supported target architectures.
+
+A sysroot for each target architectures is required. The defaults are all
+generic boards' sysroots, but they can be changed with the ARM_SYSROOT,
+AARCH64_SYSROOT, X86_64_SYSROOT environment variables.
+
+To test changes more quickly, set the NOCLEAN environment variable. This
+prevents the target directories from being removed before building and testing.
+"""
+
+from __future__ import print_function
+import multiprocessing.pool
+import os
+import shutil
+import subprocess
+import sys
+
+NOCLEAN = os.getenv('NOCLEAN') is not None
+
+ARM_TRIPLE = os.getenv('ARM_TRIPLE', 'armv7a-cros-linux-gnueabi')
+AARCH64_TRIPLE = os.getenv('AARCH64_TRIPLE', 'aarch64-cros-linux-gnu')
+X86_64_TRIPLE = os.getenv('X86_64_TRIPLE', 'x86_64-cros-linux-gnu')
+
+ARM_SYSROOT = os.getenv('ARM_SYSROOT', '/build/arm-generic')
+AARCH64_SYSROOT = os.getenv('AARCH64_SYSROOT', '/build/arm64-generic')
+X86_64_SYSROOT = os.getenv('X86_64_SYSROOT', '/build/amd64-generic')
+
+BUILD_TEST_CASES = [
+    #(sysroot path, target triple, debug/release, should test?)
+    (ARM_SYSROOT, ARM_TRIPLE, "debug", False),
+    (ARM_SYSROOT, ARM_TRIPLE, "release", False),
+    (AARCH64_SYSROOT, AARCH64_TRIPLE, "debug", False),
+    (AARCH64_SYSROOT, AARCH64_TRIPLE, "release", False),
+    (X86_64_SYSROOT, X86_64_TRIPLE, "debug", False),
+    (X86_64_SYSROOT, X86_64_TRIPLE, "release", False),
+    (X86_64_SYSROOT, X86_64_TRIPLE, "debug", True),
+    (X86_64_SYSROOT, X86_64_TRIPLE, "release", True),
+]
+
+TEST_MODULES_PARALLEL = [
+    'crosvm',
+    'data_model',
+    'kernel_loader',
+    'kvm',
+    'kvm_sys',
+    'net_sys',
+    'sys_util',
+    'syscall_defines',
+    'virtio_sys',
+    'x86_64',
+]
+
+TEST_MODULES_SERIAL = ['io_jail']
+
+# Bright green
+PASS_COLOR = '\033[1;32m'
+# Bright red
+FAIL_COLOR = '\033[1;31m'
+# Default color
+END_COLOR = '\033[0m'
+
+def get_target_path(triple, kind, test_it):
+  target_path = '/tmp/%s_%s' % (triple, kind)
+  if test_it:
+    target_path += '_test'
+  return target_path
+
+
+def build_target(triple, is_release, env):
+  args = ['cargo', 'build', '--target=%s' % triple]
+
+  if is_release:
+    args.append('--release')
+
+  return subprocess.Popen(args, env=env).wait() == 0
+
+def test_target_modules(triple, is_release, env, modules, parallel):
+  args = ['cargo', 'test', '--target=%s' % triple]
+
+  if is_release:
+    args.append('--release')
+
+  if not parallel:
+    env = env.copy()
+    env['RUST_TEST_THREADS'] = '1'
+
+  for mod in modules:
+    args.append('-p')
+    args.append(mod)
+
+  return subprocess.Popen(args, env=env).wait() == 0
+
+
+def test_target(triple, is_release, env):
+  return (
+      test_target_modules(
+          triple, is_release, env, TEST_MODULES_PARALLEL, True) and
+      test_target_modules(
+          triple, is_release, env, TEST_MODULES_SERIAL, False)
+  )
+
+
+def check_build(sysroot, triple, kind, test_it):
+  if not os.path.isdir(sysroot):
+    return 'sysroot missing'
+
+  target_path = get_target_path(triple, kind, test_it)
+
+  if not NOCLEAN:
+    shutil.rmtree(target_path, True)
+
+  is_release = kind == 'release'
+
+  env = os.environ.copy()
+  env['TARGET_CC'] = '%s-clang'%triple
+  env['SYSROOT'] = sysroot
+  env['CARGO_TARGET_DIR'] = target_path
+
+  if test_it:
+    if not test_target(triple, is_release, env):
+      return 'test error'
+  else:
+    if not build_target(triple, is_release, env):
+      return 'build error'
+
+  return 'pass'
+
+
+def get_stripped_size(triple):
+  target_path = get_target_path(triple, 'release', False)
+  bin_path = os.path.join(target_path, triple, 'release', 'crosvm')
+  proc = subprocess.Popen(['%s-strip' % triple, bin_path])
+
+  if proc.wait() != 0:
+    return 'failed'
+
+  return '%dKiB' % (os.path.getsize(bin_path) / 1024)
+
+
+def main():
+  os.chdir(os.path.dirname(sys.argv[0]))
+  pool = multiprocessing.pool.Pool()
+  results = pool.starmap(check_build, BUILD_TEST_CASES, 1)
+
+  print('---')
+  print('build test summary:')
+  for test_case, result in zip(BUILD_TEST_CASES, results):
+    _, triple, kind, test_it = test_case
+    title = '%s_%s' % (triple.split('-')[0], kind)
+    if test_it:
+      title += "_test"
+
+    result_color = FAIL_COLOR
+    if result == 'pass':
+      result_color = PASS_COLOR
+
+    display_size = ''
+    if result == 'pass' and kind == 'release' and not test_it:
+      display_size = get_stripped_size(triple) + ' stripped binary'
+
+    print('%20s: %s%15s%s %s' %
+          (title, result_color, result, END_COLOR, display_size))
+
+
+if __name__ == '__main__':
+  main()