[compiler-rt] r201394 - [asan] Android test runner for ASan lit tests.

Evgeniy Stepanov eugeni.stepanov at gmail.com
Fri Feb 14 01:22:10 PST 2014


Author: eugenis
Date: Fri Feb 14 03:22:10 2014
New Revision: 201394

URL: http://llvm.org/viewvc/llvm-project?rev=201394&view=rev
Log:
[asan] Android test runner for ASan lit tests.

This change replaces 32- and 64- bit config.in-s with a single config template
that is used to generate both 32 and 64 bits configs as well as the new
arm-android config. Arm-android config is special because it can run tests on
a remote device over adb (android debug bridge). 

We replace %clang with a script that run the compiler, upload the result to
the device, and replaces it with another script. The second script runs the
binary on the device and delivers stdout/stderr/exitcode back.

Added:
    compiler-rt/trunk/lib/asan/lit_tests/GenericConfig/
    compiler-rt/trunk/lib/asan/lit_tests/GenericConfig/lit.site.cfg.in
    compiler-rt/trunk/lib/asan/lit_tests/android_commands/
    compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_common.py   (with props)
    compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_compile.py   (with props)
    compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_run.py   (with props)
Removed:
    compiler-rt/trunk/lib/asan/lit_tests/32bitConfig/
    compiler-rt/trunk/lib/asan/lit_tests/64bitConfig/
Modified:
    compiler-rt/trunk/CMakeLists.txt
    compiler-rt/trunk/lib/asan/lit_tests/CMakeLists.txt
    compiler-rt/trunk/lib/asan/lit_tests/lit.cfg
    compiler-rt/trunk/lib/lit.common.configured.in

Modified: compiler-rt/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/CMakeLists.txt?rev=201394&r1=201393&r2=201394&view=diff
==============================================================================
--- compiler-rt/trunk/CMakeLists.txt (original)
+++ compiler-rt/trunk/CMakeLists.txt Fri Feb 14 03:22:10 2014
@@ -99,21 +99,25 @@ macro(test_target_arch arch)
   endif()
 endmacro()
 
-if("${LLVM_NATIVE_ARCH}" STREQUAL "X86")
-  if (NOT MSVC)
-    test_target_arch(x86_64 ${TARGET_64_BIT_CFLAGS})
-  endif()
-  test_target_arch(i386 ${TARGET_32_BIT_CFLAGS})
-elseif("${LLVM_NATIVE_ARCH}" STREQUAL "PowerPC")
-  test_target_arch(powerpc64 ${TARGET_64_BIT_CFLAGS})
-elseif("${LLVM_NATIVE_ARCH}" STREQUAL "ARM")
-  test_target_arch(arm "")
+if(ANDROID_COMMON_FLAGS)
+  test_target_arch(arm_android "${ANDROID_COMMON_FLAGS}")
+else()
+  if("${LLVM_NATIVE_ARCH}" STREQUAL "X86")
+    if (NOT MSVC)
+      test_target_arch(x86_64 ${TARGET_64_BIT_CFLAGS})
+    endif()
+    test_target_arch(i386 ${TARGET_32_BIT_CFLAGS})
+  elseif("${LLVM_NATIVE_ARCH}" STREQUAL "PowerPC")
+    test_target_arch(powerpc64 ${TARGET_64_BIT_CFLAGS})
+  elseif("${LLVM_NATIVE_ARCH}" STREQUAL "ARM")
+    test_target_arch(arm "")
+  endif()
 endif()
 
 # We only support running instrumented tests when we're not cross compiling
-# and target a unix-like system. On Android we define the rules for building
-# unit tests, but don't execute them.
-if("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND UNIX AND NOT ANDROID)
+# and target a unix-like system. We can run tests on Android even when we are
+# cross-compiling.
+if(("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND UNIX) OR ANDROID)
   option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" ON)
 else()
   option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" OFF)
@@ -230,12 +234,15 @@ filter_available_targets(SANITIZER_COMMO
 
 add_subdirectory(include)
 
-set(SANITIZER_COMMON_LIT_TEST_DEPS
-  clang clang-headers FileCheck count not llvm-nm llvm-symbolizer
-  compiler-rt-headers)
-# Check code style when running lit tests for sanitizers.
-if(UNIX)
-  list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS SanitizerLintCheck)
+# When ANDROID, we build tests with the host compiler (i.e. CMAKE_C_COMPILER),
+# and run tests with tools from the host toolchain.
+if (NOT ANDROID)
+  set(SANITIZER_COMMON_LIT_TEST_DEPS
+    clang clang-headers FileCheck count not llvm-nm llvm-symbolizer
+    compiler-rt-headers)
+  if(UNIX)
+    list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS SanitizerLintCheck)
+  endif()
 endif()
 
 add_subdirectory(lib)

Modified: compiler-rt/trunk/lib/asan/lit_tests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/CMakeLists.txt?rev=201394&r1=201393&r2=201394&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/asan/lit_tests/CMakeLists.txt Fri Feb 14 03:22:10 2014
@@ -1,36 +1,59 @@
 set(ASAN_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..)
 set(ASAN_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/..)
 
-configure_lit_site_cfg(
-  ${CMAKE_CURRENT_SOURCE_DIR}/64bitConfig/lit.site.cfg.in
-  ${CMAKE_CURRENT_BINARY_DIR}/64bitConfig/lit.site.cfg
-  )
-
-configure_lit_site_cfg(
-  ${CMAKE_CURRENT_SOURCE_DIR}/32bitConfig/lit.site.cfg.in
-  ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig/lit.site.cfg
-  )
-
-configure_lit_site_cfg(
-  ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in
-  ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg
-  )
-
 if(COMPILER_RT_CAN_EXECUTE_TESTS)
   set(ASAN_TESTSUITES)
-  if(CAN_TARGET_i386)
-    list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig)
+
+  if(CAN_TARGET_arm_android)
+    # This is only true if we are cross-compiling.
+    # Build all tests with host compiler and use host tools.
+    set(ASAN_TEST_TARGET_CC ${CMAKE_C_COMPILER})
+    get_filename_component(ASAN_TEST_LLVM_TOOLS_DIR ${CMAKE_C_COMPILER} PATH)
+    set(ASAN_TEST_CONFIG_SUFFIX "-arm-android")
+    set(ASAN_TEST_BITS "32")
+    get_target_flags_for_arch(arm_android ASAN_TEST_TARGET_CFLAGS)
+    configure_lit_site_cfg(
+      ${CMAKE_CURRENT_SOURCE_DIR}/GenericConfig/lit.site.cfg.in
+      ${CMAKE_CURRENT_BINARY_DIR}/ARMAndroidConfig/lit.site.cfg
+      )
+    list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/ARMAndroidConfig)
   endif()
+  
   if(CAN_TARGET_x86_64 OR CAN_TARGET_powerpc64)
+    set(ASAN_TEST_CONFIG_SUFFIX "64")
+    set(ASAN_TEST_BITS "64")
+    set(ASAN_TEST_TARGET_CFLAGS ${TARGET_64_BIT_CFLAGS})
+    configure_lit_site_cfg(
+      ${CMAKE_CURRENT_SOURCE_DIR}/GenericConfig/lit.site.cfg.in
+      ${CMAKE_CURRENT_BINARY_DIR}/64bitConfig/lit.site.cfg
+      )
     list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/64bitConfig)
   endif()
+  
+  if(CAN_TARGET_i386)
+    set(ASAN_TEST_CONFIG_SUFFIX "32")
+    set(ASAN_TEST_BITS "32")
+    set(ASAN_TEST_TARGET_CFLAGS ${TARGET_32_BIT_CFLAGS})
+    configure_lit_site_cfg(
+      ${CMAKE_CURRENT_SOURCE_DIR}/GenericConfig/lit.site.cfg.in
+      ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig/lit.site.cfg
+      )
+    list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig)
+  endif()
+  
+  configure_lit_site_cfg(
+    ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in
+    ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg
+    )
+  
   # Run ASan tests only if we're sure we may produce working binaries.
   set(ASAN_TEST_DEPS
     ${SANITIZER_COMMON_LIT_TEST_DEPS}
     asan_runtime_libraries)
   set(ASAN_TEST_PARAMS
     asan_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg)
-  if(LLVM_INCLUDE_TESTS)
+  # FIXME: support unit test in the android test runner
+  if(LLVM_INCLUDE_TESTS AND NOT CAN_TARGET_arm_android)
     list(APPEND ASAN_TEST_DEPS AsanUnitTests)
     list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit)
   endif()

Added: compiler-rt/trunk/lib/asan/lit_tests/GenericConfig/lit.site.cfg.in
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/GenericConfig/lit.site.cfg.in?rev=201394&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/GenericConfig/lit.site.cfg.in (added)
+++ compiler-rt/trunk/lib/asan/lit_tests/GenericConfig/lit.site.cfg.in Fri Feb 14 03:22:10 2014
@@ -0,0 +1,17 @@
+## Autogenerated by LLVM/Clang configuration.
+# Do not edit!
+
+# Tool-specific config options.
+config.name_suffix = "@ASAN_TEST_CONFIG_SUFFIX@"
+config.asan_source_dir = "@ASAN_SOURCE_DIR@"
+config.target_cflags = "@ASAN_TEST_TARGET_CFLAGS@"
+config.clang = "@ASAN_TEST_TARGET_CC@"
+config.llvm_tools_dir = "@ASAN_TEST_LLVM_TOOLS_DIR@"
+config.bits = "@ASAN_TEST_BITS@"
+config.android = "@CAN_TARGET_arm_android@"
+
+# Load common config for all compiler-rt lit tests.
+lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/lib/lit.common.configured")
+
+# Load tool-specific config that would do the real work.
+lit_config.load_config(config, "@ASAN_SOURCE_DIR@/lit_tests/lit.cfg")

Added: compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_common.py
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_common.py?rev=201394&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_common.py (added)
+++ compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_common.py Fri Feb 14 03:22:10 2014
@@ -0,0 +1,29 @@
+import os, subprocess, tempfile
+import time
+
+ANDROID_TMPDIR = '/data/local/tmp/Output'
+ADB = os.environ.get('ADB', 'adb')
+
+verbose = False
+if os.environ.get('ANDROID_RUN_VERBOSE') == '1':
+    verbose = True
+
+def adb(args):
+    if verbose:
+        print args
+    devnull = open(os.devnull, 'w')
+    return subprocess.call([ADB] + args, stdout=devnull, stderr=subprocess.STDOUT)
+
+def pull_from_device(path):
+    tmp = tempfile.mktemp()
+    adb(['pull', path, tmp])
+    text = open(tmp, 'r').read()
+    os.unlink(tmp)
+    return text
+
+def push_to_device(path):
+    # Workaround for https://code.google.com/p/android/issues/detail?id=65857
+    dst_path = os.path.join(ANDROID_TMPDIR, os.path.basename(path))
+    tmp_path = dst_path + '.push'
+    adb(['push', path, tmp_path])
+    adb(['shell', 'cp "%s" "%s" 2>&1' % (tmp_path, dst_path)])

Propchange: compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_common.py
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_compile.py
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_compile.py?rev=201394&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_compile.py (added)
+++ compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_compile.py Fri Feb 14 03:22:10 2014
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+
+import os, sys, subprocess
+from android_common import *
+
+
+here = os.path.abspath(os.path.dirname(sys.argv[0]))
+android_run = os.path.join(here, 'android_run.py')
+
+output = None
+output_type = 'executable'
+
+args = sys.argv[1:]
+while args:
+    arg = args.pop(0)
+    if arg == '-shared':
+        output_type = 'shared'
+    elif arg == '-c':
+        output_type = 'object'
+    elif arg == '-o':
+        output = args.pop(0)
+
+if output == None:
+    print "No output file name!"
+    sys.exit(1)
+
+ret = subprocess.call(sys.argv[1:])
+if ret != 0:
+    sys.exit(ret)
+
+if output_type in ['executable', 'shared']:
+    push_to_device(output)
+
+if output_type == 'executable':
+    os.rename(output, output + '.real')
+    os.symlink(android_run, output)

Propchange: compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_compile.py
------------------------------------------------------------------------------
    svn:eol-style = LF

Propchange: compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_compile.py
------------------------------------------------------------------------------
    svn:executable = *

Added: compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_run.py
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_run.py?rev=201394&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_run.py (added)
+++ compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_run.py Fri Feb 14 03:22:10 2014
@@ -0,0 +1,34 @@
+#!/usr/bin/python
+
+import os, sys, subprocess, tempfile
+from android_common import *
+
+ANDROID_TMPDIR = '/data/local/tmp/Output'
+
+here = os.path.abspath(os.path.dirname(sys.argv[0]))
+device_binary = os.path.join(ANDROID_TMPDIR, os.path.basename(sys.argv[0]))
+
+def build_env():
+    args = []
+    # Android linker ignores RPATH. Set LD_LIBRARY_PATH to Output dir.
+    args.append('LD_LIBRARY_PATH=%s:%s' %
+                (ANDROID_TMPDIR, os.environ.get('LD_LIBRARY_PATH', '')))
+    for (key, value) in os.environ.items():
+        if key in ['ASAN_OPTIONS']:
+            args.append('%s="%s"' % (key, value))
+    return ' '.join(args)
+
+device_env = build_env()
+device_args = ' '.join(sys.argv[1:]) # FIXME: escape?
+device_stdout = device_binary + '.stdout'
+device_stderr = device_binary + '.stderr'
+device_exitcode = device_binary + '.exitcode'
+ret = adb(['shell', 'cd %s && %s %s %s >%s 2>%s ; echo $? >%s' %
+           (ANDROID_TMPDIR, device_env, device_binary, device_args,
+            device_stdout, device_stderr, device_exitcode)])
+if ret != 0:
+    sys.exit(ret)
+
+sys.stdout.write(pull_from_device(device_stdout))
+sys.stderr.write(pull_from_device(device_stderr))
+sys.exit(int(pull_from_device(device_exitcode)))

Propchange: compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_run.py
------------------------------------------------------------------------------
    svn:eol-style = LF

Propchange: compiler-rt/trunk/lib/asan/lit_tests/android_commands/android_run.py
------------------------------------------------------------------------------
    svn:executable = *

Modified: compiler-rt/trunk/lib/asan/lit_tests/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/lit.cfg?rev=201394&r1=201393&r2=201394&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/lit.cfg (original)
+++ compiler-rt/trunk/lib/asan/lit_tests/lit.cfg Fri Feb 14 03:22:10 2014
@@ -14,7 +14,7 @@ def get_required_attr(config, attr_name)
   return attr_value
 
 # Setup config name.
-config.name = 'AddressSanitizer' + config.bits
+config.name = 'AddressSanitizer' + config.name_suffix
 
 # Setup source root.
 config.test_source_root = os.path.dirname(__file__)
@@ -53,23 +53,32 @@ if llvm_src_root is None:
 
 # Setup default compiler flags used with -fsanitize=address option.
 # FIXME: Review the set of required flags and check if it can be reduced.
-bits_cflag = " -m" + config.bits
+target_cflags = " " + config.target_cflags
 clang_asan_cflags = (" -fsanitize=address"
                    + " -mno-omit-leaf-frame-pointer"
                    + " -fno-omit-frame-pointer"
                    + " -fno-optimize-sibling-calls"
                    + " -g"
-                   + bits_cflag)
+                   + target_cflags)
 clang_asan_cxxflags = " --driver-mode=g++" + clang_asan_cflags
-config.substitutions.append( ("%clang ", " " + config.clang + bits_cflag + " "))
-config.substitutions.append( ("%clangxx ", (" " + config.clang +
+
+if config.android == "TRUE":
+  config.available_features.add('android')
+  clang_wrapper = os.path.join(config.asan_source_dir, "lit_tests",
+                               "android_commands", "android_compile.py") + " "
+else:
+  clang_wrapper = ""
+
+config.substitutions.append( ("%clang ", " " + clang_wrapper + config.clang + target_cflags + " "))
+config.substitutions.append( ("%clangxx ", (" " + clang_wrapper + config.clang +
                                             " --driver-mode=g++" +
-                                            bits_cflag + " ")) )
-config.substitutions.append( ("%clang_asan ", (" " + config.clang + " " +
+                                            target_cflags + " ")) )
+config.substitutions.append( ("%clang_asan ", (" " + clang_wrapper + config.clang + " " +
                                               clang_asan_cflags + " ")) )
-config.substitutions.append( ("%clangxx_asan ", (" " + config.clang + " " +
+config.substitutions.append( ("%clangxx_asan ", (" " + clang_wrapper + config.clang + " " +
                                                 clang_asan_cxxflags + " ")) )
 
+
 # Setup path to asan_symbolize.py script.
 asan_source_dir = get_required_attr(config, "asan_source_dir")
 asan_symbolize = os.path.join(asan_source_dir, "scripts", "asan_symbolize.py")

Modified: compiler-rt/trunk/lib/lit.common.configured.in
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lit.common.configured.in?rev=201394&r1=201393&r2=201394&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lit.common.configured.in (original)
+++ compiler-rt/trunk/lib/lit.common.configured.in Fri Feb 14 03:22:10 2014
@@ -1,19 +1,24 @@
 ## Autogenerated by LLVM/Clang configuration.
 # Do not edit!
 
+# Set attribute value if it is unset.
+def set_default(attr, value):
+  if not getattr(config, attr, None):
+    setattr(config, attr, value)
+    
 # Generic config options for all compiler-rt lit tests.
-config.target_triple = "@TARGET_TRIPLE@"
-config.host_arch = "@HOST_ARCH@"
-config.host_os = "@HOST_OS@"
-config.llvm_build_mode = "@LLVM_BUILD_MODE@"
-config.llvm_src_root = "@LLVM_SOURCE_DIR@"
-config.llvm_obj_root = "@LLVM_BINARY_DIR@"
-config.compiler_rt_src_root = "@COMPILER_RT_SOURCE_DIR@"
-config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
-config.clang = "@LLVM_BINARY_DIR@/bin/clang"
-config.compiler_rt_arch = "@COMPILER_RT_SUPPORTED_ARCH@"
-config.python_executable = "@PYTHON_EXECUTABLE@"
-config.compiler_rt_debug = @COMPILER_RT_DEBUG_PYBOOL@
+set_default("target_triple", "@TARGET_TRIPLE@")
+set_default("host_arch", "@HOST_ARCH@")
+set_default("host_os", "@HOST_OS@")
+set_default("llvm_build_mode", "@LLVM_BUILD_MODE@")
+set_default("llvm_src_root", "@LLVM_SOURCE_DIR@")
+set_default("llvm_obj_root", "@LLVM_BINARY_DIR@")
+set_default("compiler_rt_src_root", "@COMPILER_RT_SOURCE_DIR@")
+set_default("llvm_tools_dir", "@LLVM_TOOLS_DIR@")
+set_default("clang", "@LLVM_BINARY_DIR@/bin/clang")
+set_default("compiler_rt_arch", "@COMPILER_RT_SUPPORTED_ARCH@")
+set_default("python_executable", "@PYTHON_EXECUTABLE@")
+set_default("compiler_rt_debug", @COMPILER_RT_DEBUG_PYBOOL@)
 
 # LLVM tools dir can be passed in lit parameters, so try to
 # apply substitution.





More information about the llvm-commits mailing list