Adding the @skipIfAddressSanitizerUnsupported decorator, which detects whether 
the compiler supports "-fsanitize=address", and skips the marked tests if not. 
Getting rid of the stupid "findBuiltClang" logic, in favor of just using the 
same compiler that you use for the rest of the tests.

Related to http://reviews.llvm.org/D6205. I also updated the ASan test cases to 
react more properly to the "stop reason = exec", which is probably a OS X only 
thing, on Linux where ASan is a static library, the relaunch doesn't happen. 
Doug, could you try this patch on Ubuntu, if it resolves the test failure you 
were seeing?

http://reviews.llvm.org/D6272

Files:
  functionalities/asan/Makefile
  functionalities/asan/TestMemoryHistory.py
  functionalities/asan/TestReportData.py
  lldbtest.py
Index: functionalities/asan/Makefile
===================================================================
--- functionalities/asan/Makefile
+++ functionalities/asan/Makefile
@@ -1,6 +1,5 @@
 LEVEL = ../../make
 
 C_SOURCES := main.c
-CFLAGS := $(CFLAGS) -fsanitize=address -g
 
 include $(LEVEL)/Makefile.rules
Index: functionalities/asan/TestMemoryHistory.py
===================================================================
--- functionalities/asan/TestMemoryHistory.py
+++ functionalities/asan/TestMemoryHistory.py
@@ -12,24 +12,20 @@
 
     mydir = TestBase.compute_mydir(__file__)
 
-    # The default compiler ("clang") may not support Address Sanitizer or it
-    # may not have the debugging API which was recently added, so we're calling
-    # self.useBuiltClang() to use clang from the llvm-build directory instead
-
     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     @skipIfRemote
+    @skipIfAddressSanitizerUnsupported
     @dsym_test
     def test_with_dsym (self):
-        compiler = self.findBuiltClang ()
-        self.buildDsym (None, compiler)
+        self.buildDsym (None, None, {"CFLAGS": "-fsanitize=address -g"})
         self.asan_tests ()
 
     @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default
     @skipIfRemote
+    @skipIfAddressSanitizerUnsupported
     @dwarf_test
     def test_with_dwarf (self):
-        compiler = self.findBuiltClang ()
-        self.buildDwarf (None, compiler)
+        self.buildDwarf (None, None, {"CFLAGS": "-fsanitize=address -g"})
         self.asan_tests ()
 
     def setUp(self):
@@ -53,11 +49,14 @@
 
         self.runCmd("run")
 
-        # ASan will relaunch the process to insert its library.
-        self.expect("thread list", "Process should be stopped due to exec.",
-            substrs = ['stopped', 'stop reason = exec'])
-
-        self.runCmd("continue")
+        process = self.dbg.GetSelectedTarget().process
+        thread = process.GetSelectedThread()
+        stop_reason = thread.GetStopReason()
+        if stop_reason == lldb.eStopReasonExec:
+            # On OS X, ASan will relaunch the process to insert its library.
+            self.expect("thread list", "Process should be stopped due to exec.",
+                substrs = ['stopped', 'stop reason = exec'])
+            self.runCmd("continue")
 
         # the stop reason of the thread should be breakpoint.
         self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
@@ -74,7 +73,6 @@
                 'Memory deallocated at', 'a.out`f2', 'main.c:%d' % self.line_free])
 
         # do the same using SB API
-        process = self.dbg.GetSelectedTarget().process
         val = process.GetSelectedThread().GetSelectedFrame().EvaluateExpression("pointer")
         addr = val.GetValueAsUnsigned()
         threads = process.GetHistoryThreads(addr);
Index: functionalities/asan/TestReportData.py
===================================================================
--- functionalities/asan/TestReportData.py
+++ functionalities/asan/TestReportData.py
@@ -13,24 +13,20 @@
 
     mydir = TestBase.compute_mydir(__file__)
 
-    # The default compiler ("clang") may not support Address Sanitizer or it
-    # may not have the debugging API which was recently added, so we're calling
-    # self.useBuiltClang() to use clang from the llvm-build directory instead
-
     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     @skipIfRemote
+    @skipIfAddressSanitizerUnsupported
     @dsym_test
     def test_with_dsym (self):
-        compiler = self.findBuiltClang ()
-        self.buildDsym (None, compiler)
+        self.buildDsym (None, None, {"CFLAGS": "-fsanitize=address -g"})
         self.asan_tests ()
 
     @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default
     @skipIfRemote
+    @skipIfAddressSanitizerUnsupported
     @dwarf_test
     def test_with_dwarf (self):
-        compiler = self.findBuiltClang ()
-        self.buildDwarf (None, compiler)
+        self.buildDwarf (None, None, {"CFLAGS": "-fsanitize=address -g"})
         self.asan_tests ()
 
     def setUp(self):
@@ -45,11 +41,23 @@
     def asan_tests (self):
         exe = os.path.join (os.getcwd(), "a.out")
         self.expect("file " + exe, patterns = [ "Current executable set to .*a.out" ])
+
+        self.runCmd("breakpoint set -f main.c -l %d" % self.line_breakpoint)
+
         self.runCmd("run")
 
-        # ASan will relaunch the process to insert its library.
-        self.expect("thread list", "Process should be stopped due to exec.",
-            substrs = ['stopped', 'stop reason = exec'])
+        process = self.dbg.GetSelectedTarget().process
+        thread = process.GetSelectedThread()
+        stop_reason = thread.GetStopReason()
+        if stop_reason == lldb.eStopReasonExec:
+            # On OS X, ASan will relaunch the process to insert its library.
+            self.expect("thread list", "Process should be stopped due to exec.",
+                substrs = ['stopped', 'stop reason = exec'])
+            self.runCmd("continue")
+
+        # the stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+            substrs = ['stopped', 'stop reason = breakpoint'])
 
         # no extended info when we have no ASan report
         thread = self.dbg.GetSelectedTarget().process.GetSelectedThread()
Index: lldbtest.py
===================================================================
--- lldbtest.py
+++ lldbtest.py
@@ -669,6 +669,22 @@
             func(*args, **kwargs)
     return wrapper
 
+def skipIfAddressSanitizerUnsupported(func):
+    """
+    Decorate the item to skip tests that should skipped when the compiler we're using doesn't
+    support compiling with AddressSanitizer.
+    """
+    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
+        raise Exception("@skipIfAddressSanitizerUnsupported can only be used to decorate a test method")
+    @wraps(func)
+    def wrapper(*args, **kwargs):
+        from unittest2 import case
+        self = args[0]
+        if not self.compilerSupportsAddressSanitizer():
+            self.skipTest("skipping because compiler doesn't support AddressSanitizer")
+        else:
+            func(*args, **kwargs)
+    return wrapper
 
 class Base(unittest2.TestCase):
     """
@@ -864,6 +880,8 @@
         # See HideStdout(self).
         self.sys_stdout_hidden = False
 
+        self.cachedCompilerSupportsAddressSanitizer = None
+
         # set environment variable names for finding shared libraries
         if sys.platform.startswith("darwin"):
             self.dylibPath = 'DYLD_LIBRARY_PATH'
@@ -1363,22 +1381,6 @@
         if not module.buildDwarf(self, architecture, compiler, dictionary, clean):
             raise Exception("Don't know how to build binary with dwarf")
 
-    def findBuiltClang(self):
-        """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler)."""
-        paths_to_try = [
-          "llvm-build/Release+Asserts/x86_64/Release+Asserts/bin/clang",
-          "llvm-build/Debug+Asserts/x86_64/Debug+Asserts/bin/clang",
-          "llvm-build/Release/x86_64/Release/bin/clang",
-          "llvm-build/Debug/x86_64/Debug/bin/clang",
-        ]
-        lldb_root_path = os.path.join(os.path.dirname(__file__), "..")
-        for p in paths_to_try:
-            path = os.path.join(lldb_root_path, p)
-            if os.path.exists(path):
-                return path
-        
-        return os.environ["CC"]
-
     def getBuildFlags(self, use_cpp11=True, use_libcxx=False, use_libstdcxx=False, use_pthreads=True):
         """ Returns a dictionary (which can be provided to build* functions above) which
             contains OS-specific build flags.
@@ -1443,6 +1445,33 @@
         else:
             return ['libc++.1.dylib','libc++abi.dylib']
 
+    def compilerSupportsAddressSanitizer(self):
+        if self.cachedCompilerSupportsAddressSanitizer != None:
+            return self.cachedCompilerSupportsAddressSanitizer
+
+        self.cachedCompilerSupportsAddressSanitizer = False
+
+        # Save old working directory.
+        oldcwd = os.getcwd()
+
+        os.chdir(os.path.dirname(__file__) + "/functionalities/asan")
+
+        # This should always work
+        self.buildDefault();
+
+        # This will fail if the compiler doesn't have AddressSanitizer
+        try:
+            self.buildDefault (None, None, {"CFLAGS": "-fsanitize=address"})
+            self.cachedCompilerSupportsAddressSanitizer = True
+        except CalledProcessError:
+            pass
+
+        # Clean up
+        self.cleanup();
+        os.chdir(oldcwd)
+
+        return self.cachedCompilerSupportsAddressSanitizer
+
 class TestBase(Base):
     """
     This abstract base class is meant to be subclassed.  It provides default
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to