1"""
2Test process attach.
3"""
4
5
6
7import os
8import lldb
9import shutil
10from lldbsuite.test.decorators import *
11from lldbsuite.test.lldbtest import *
12from lldbsuite.test import lldbutil
13
14exe_name = "ProcessAttach"  # Must match Makefile
15
16
17class ProcessAttachTestCase(TestBase):
18
19    mydir = TestBase.compute_mydir(__file__)
20
21    NO_DEBUG_INFO_TESTCASE = True
22
23    def setUp(self):
24        # Call super's setUp().
25        TestBase.setUp(self)
26        # Find the line number to break for main.c.
27        self.line = line_number('main.cpp',
28                                '// Waiting to be attached...')
29
30    @skipIfiOSSimulator
31    def test_attach_to_process_by_id(self):
32        """Test attach by process id"""
33        self.build()
34        exe = self.getBuildArtifact(exe_name)
35
36        # Spawn a new process
37        popen = self.spawnSubprocess(exe)
38
39        self.runCmd("process attach -p " + str(popen.pid))
40
41        target = self.dbg.GetSelectedTarget()
42
43        process = target.GetProcess()
44        self.assertTrue(process, PROCESS_IS_VALID)
45
46    @skipIfiOSSimulator
47    def test_attach_to_process_by_id_autocontinue(self):
48        """Test attach by process id"""
49        self.build()
50        exe = self.getBuildArtifact(exe_name)
51
52        # Spawn a new process
53        popen = self.spawnSubprocess(exe)
54
55        self.runCmd("process attach -c -p " + str(popen.pid))
56
57        target = self.dbg.GetSelectedTarget()
58
59        process = target.GetProcess()
60        self.assertTrue(process, PROCESS_IS_VALID)
61        self.assertTrue(process.GetState(), lldb.eStateRunning)
62
63    @skipIfWindows # This is flakey on Windows AND when it fails, it hangs: llvm.org/pr48806
64    def test_attach_to_process_from_different_dir_by_id(self):
65        """Test attach by process id"""
66        newdir = self.getBuildArtifact("newdir")
67        try:
68            os.mkdir(newdir)
69        except OSError as e:
70            if e.errno != os.errno.EEXIST:
71                raise
72        testdir = self.getBuildDir()
73        exe = os.path.join(newdir, 'proc_attach')
74        self.buildProgram('main.cpp', exe)
75        self.addTearDownHook(lambda: shutil.rmtree(newdir))
76
77        # Spawn a new process
78        popen = self.spawnSubprocess(exe)
79
80        os.chdir(newdir)
81        self.addTearDownHook(lambda: os.chdir(testdir))
82        self.runCmd("process attach -p " + str(popen.pid))
83
84        target = self.dbg.GetSelectedTarget()
85
86        process = target.GetProcess()
87        self.assertTrue(process, PROCESS_IS_VALID)
88
89    def test_attach_to_process_by_name(self):
90        """Test attach by process name"""
91        self.build()
92        exe = self.getBuildArtifact(exe_name)
93
94        # Spawn a new process
95        popen = self.spawnSubprocess(exe)
96
97        self.runCmd("process attach -n " + exe_name)
98
99        target = self.dbg.GetSelectedTarget()
100
101        process = target.GetProcess()
102        self.assertTrue(process, PROCESS_IS_VALID)
103
104    @skipIfWindows # This test is flaky on Windows
105    @expectedFailureNetBSD
106    def test_attach_to_process_by_id_correct_executable_offset(self):
107        """
108        Test that after attaching to a process the executable offset
109        is determined correctly on FreeBSD.  This is a regression test
110        for dyld plugin getting the correct executable path,
111        and therefore being able to identify it in the module list.
112        """
113
114        self.build()
115        exe = self.getBuildArtifact(exe_name)
116
117        # In order to reproduce, we must spawn using a relative path
118        popen = self.spawnSubprocess(os.path.relpath(exe))
119
120        self.runCmd("process attach -p " + str(popen.pid))
121
122        # Make sure we did not attach too early.
123        lldbutil.run_break_set_by_file_and_line(
124            self, "main.cpp", self.line, num_expected_locations=1, loc_exact=False)
125        self.runCmd("process continue")
126        self.expect("v g_val", substrs=["12345"])
127
128    def tearDown(self):
129        # Destroy process before TestBase.tearDown()
130        self.dbg.GetSelectedTarget().GetProcess().Destroy()
131
132        # Call super's tearDown().
133        TestBase.tearDown(self)
134