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