Currently most of the test files have a separate dwarf and a separate dsym test with almost identical content (only the build step is different). With adding dwo symbol file handling to the test suit it would increase this to a 3-way duplication. The purpose of this change is to eliminate this redundancy with generating 2 test case (one dwarf and one dsym) for each test function specified (dwo handling will be added at a later commit). Main design goals: * There should be no boilerplate code in each test file to support the multiple debug info in most of the tests (custom scenarios are acceptable in special cases) so adding a new test case is easier and we can't miss one of the debug info type. * In case of a test failure, the debug symbols used during the test run have to be cleanly visible from the output of dotest.py to make debugging easier both from build bot logs and from local test runs * Each test case should have a unique, fully qualified name so we can run exactly 1 test with "-f <test-case>.<test-function>" syntax * Test output should be grouped based on test files the same way as it happens now (displaying dwarf/dsym results separately isn't preferable) Proposed solution (main logic in lldbtest.py, rest of them are test cases fixed up for the new style): * Have only 1 test fuction in the test files what will run for all debug info separately and this test function should call just "self.build(...)" to build an inferior with the right debug info * When a class is created by python (the class object, not the class instance), we will generate a new test method for each debug info format in the test class with the name "<test-function>_<debug-info>" and remove the original test method. This way unittest2 see multiple test methods (1 for each debug info, pretty much as of now) and will handle the test selection and the failure reporting correctly (the debug info will be visible from the end of the test name) * Add new annotation @no_debug_info_test to disable the generation of multiple tests for each debug info format when the test don't have an inferior Differential revision: http://reviews.llvm.org/D13028 llvm-svn: 248883
125 lines
4.6 KiB
Python
125 lines
4.6 KiB
Python
"""
|
|
Test thread creation after process attach.
|
|
"""
|
|
|
|
import os, time
|
|
import unittest2
|
|
import lldb
|
|
from lldbtest import *
|
|
import lldbutil
|
|
|
|
class CreateAfterAttachTestCase(TestBase):
|
|
|
|
mydir = TestBase.compute_mydir(__file__)
|
|
|
|
@skipIfFreeBSD # Hangs. May be the same as Linux issue llvm.org/pr16229 but
|
|
# not yet investigated. Revisit once required functionality
|
|
# is implemented for FreeBSD.
|
|
@skipIfWindows # Occasionally hangs on Windows, may be same as other issues.
|
|
def test_create_after_attach_with_popen(self):
|
|
"""Test thread creation after process attach."""
|
|
self.build(dictionary=self.getBuildFlags(use_cpp11=False))
|
|
self.create_after_attach(use_fork=False)
|
|
|
|
@skipIfFreeBSD # Hangs. Revisit once required functionality is implemented
|
|
# for FreeBSD.
|
|
@skipIfRemote
|
|
@skipIfWindows # Windows doesn't have fork.
|
|
@expectedFlakeyLinux("llvm.org/pr16229") # 1/100 dosep, build 3546, clang-3.5 x84_64
|
|
def test_create_after_attach_with_fork(self):
|
|
"""Test thread creation after process attach."""
|
|
self.build(dictionary=self.getBuildFlags(use_cpp11=False))
|
|
self.create_after_attach(use_fork=True)
|
|
|
|
def setUp(self):
|
|
# Call super's setUp().
|
|
TestBase.setUp(self)
|
|
# Find the line numbers for our breakpoints.
|
|
self.break_1 = line_number('main.cpp', '// Set first breakpoint here')
|
|
self.break_2 = line_number('main.cpp', '// Set second breakpoint here')
|
|
self.break_3 = line_number('main.cpp', '// Set third breakpoint here')
|
|
|
|
def create_after_attach(self, use_fork):
|
|
"""Test thread creation after process attach."""
|
|
|
|
exe = os.path.join(os.getcwd(), "a.out")
|
|
|
|
# Spawn a new process
|
|
if use_fork:
|
|
pid = self.forkSubprocess(exe)
|
|
else:
|
|
popen = self.spawnSubprocess(exe)
|
|
pid = popen.pid
|
|
self.addTearDownHook(self.cleanupSubprocesses)
|
|
|
|
# Attach to the spawned process
|
|
self.runCmd("process attach -p " + str(pid))
|
|
|
|
target = self.dbg.GetSelectedTarget()
|
|
|
|
process = target.GetProcess()
|
|
self.assertTrue(process, PROCESS_IS_VALID)
|
|
|
|
# This should create a breakpoint in the main thread.
|
|
lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_1, num_expected_locations=1)
|
|
|
|
# This should create a breakpoint in the second child thread.
|
|
lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_2, num_expected_locations=1)
|
|
|
|
# This should create a breakpoint in the first child thread.
|
|
lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_3, num_expected_locations=1)
|
|
|
|
# Note: With std::thread, we cannot rely on particular thread numbers. Using
|
|
# std::thread may cause the program to spin up a thread pool (and it does on
|
|
# Windows), so the thread numbers are non-deterministic.
|
|
|
|
# Run to the first breakpoint
|
|
self.runCmd("continue")
|
|
|
|
# The stop reason of the thread should be breakpoint.
|
|
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
|
substrs = ['stopped',
|
|
'* thread #',
|
|
'main',
|
|
'stop reason = breakpoint'])
|
|
|
|
# Change a variable to escape the loop
|
|
self.runCmd("expression main_thread_continue = 1")
|
|
|
|
# Run to the second breakpoint
|
|
self.runCmd("continue")
|
|
|
|
# The stop reason of the thread should be breakpoint.
|
|
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
|
substrs = ['stopped',
|
|
'* thread #',
|
|
'thread_2_func',
|
|
'stop reason = breakpoint'])
|
|
|
|
# Change a variable to escape the loop
|
|
self.runCmd("expression child_thread_continue = 1")
|
|
|
|
# Run to the third breakpoint
|
|
self.runCmd("continue")
|
|
|
|
# The stop reason of the thread should be breakpoint.
|
|
# Thread 3 may or may not have already exited.
|
|
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
|
substrs = ['stopped',
|
|
'* thread #',
|
|
'thread_1_func',
|
|
'stop reason = breakpoint'])
|
|
|
|
# Run to completion
|
|
self.runCmd("continue")
|
|
|
|
# At this point, the inferior process should have exited.
|
|
self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
import atexit
|
|
lldb.SBDebugger.Initialize()
|
|
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
|
unittest2.main()
|