199451b44SJordan Rupprecht"""
299451b44SJordan RupprechtTest process attach.
399451b44SJordan Rupprecht"""
499451b44SJordan Rupprecht
599451b44SJordan Rupprecht
699451b44SJordan Rupprecht
799451b44SJordan Rupprechtimport os
899451b44SJordan Rupprechtimport lldb
999451b44SJordan Rupprechtimport shutil
1099451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
1199451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
1299451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil
1399451b44SJordan Rupprecht
1499451b44SJordan Rupprechtexe_name = "ProcessAttach"  # Must match Makefile
1599451b44SJordan Rupprecht
1699451b44SJordan Rupprecht
1799451b44SJordan Rupprechtclass ProcessAttachTestCase(TestBase):
1899451b44SJordan Rupprecht
1999451b44SJordan Rupprecht    NO_DEBUG_INFO_TESTCASE = True
2099451b44SJordan Rupprecht
21dbfdb139SMichał Górny    def setUp(self):
22dbfdb139SMichał Górny        # Call super's setUp().
23dbfdb139SMichał Górny        TestBase.setUp(self)
24dbfdb139SMichał Górny        # Find the line number to break for main.c.
25dbfdb139SMichał Górny        self.line = line_number('main.cpp',
26dbfdb139SMichał Górny                                '// Waiting to be attached...')
27dbfdb139SMichał Górny
2899451b44SJordan Rupprecht    @skipIfiOSSimulator
2999451b44SJordan Rupprecht    def test_attach_to_process_by_id(self):
3099451b44SJordan Rupprecht        """Test attach by process id"""
3199451b44SJordan Rupprecht        self.build()
3299451b44SJordan Rupprecht        exe = self.getBuildArtifact(exe_name)
3399451b44SJordan Rupprecht
3499451b44SJordan Rupprecht        # Spawn a new process
3599451b44SJordan Rupprecht        popen = self.spawnSubprocess(exe)
3699451b44SJordan Rupprecht
3799451b44SJordan Rupprecht        self.runCmd("process attach -p " + str(popen.pid))
3899451b44SJordan Rupprecht
3999451b44SJordan Rupprecht        target = self.dbg.GetSelectedTarget()
4099451b44SJordan Rupprecht
4199451b44SJordan Rupprecht        process = target.GetProcess()
4299451b44SJordan Rupprecht        self.assertTrue(process, PROCESS_IS_VALID)
4399451b44SJordan Rupprecht
442303391dSJim Ingham    @skipIfiOSSimulator
452303391dSJim Ingham    def test_attach_to_process_by_id_autocontinue(self):
462303391dSJim Ingham        """Test attach by process id"""
472303391dSJim Ingham        self.build()
482303391dSJim Ingham        exe = self.getBuildArtifact(exe_name)
492303391dSJim Ingham
502303391dSJim Ingham        # Spawn a new process
512303391dSJim Ingham        popen = self.spawnSubprocess(exe)
522303391dSJim Ingham
532303391dSJim Ingham        self.runCmd("process attach -c -p " + str(popen.pid))
542303391dSJim Ingham
552303391dSJim Ingham        target = self.dbg.GetSelectedTarget()
562303391dSJim Ingham
572303391dSJim Ingham        process = target.GetProcess()
582303391dSJim Ingham        self.assertTrue(process, PROCESS_IS_VALID)
592303391dSJim Ingham        self.assertTrue(process.GetState(), lldb.eStateRunning)
602303391dSJim Ingham
6134714553SStella Stamenova    @skipIfWindows # This is flakey on Windows AND when it fails, it hangs: llvm.org/pr48806
6299451b44SJordan Rupprecht    def test_attach_to_process_from_different_dir_by_id(self):
6399451b44SJordan Rupprecht        """Test attach by process id"""
6499451b44SJordan Rupprecht        newdir = self.getBuildArtifact("newdir")
6599451b44SJordan Rupprecht        try:
6699451b44SJordan Rupprecht            os.mkdir(newdir)
6799451b44SJordan Rupprecht        except OSError as e:
6899451b44SJordan Rupprecht            if e.errno != os.errno.EEXIST:
6999451b44SJordan Rupprecht                raise
7099451b44SJordan Rupprecht        testdir = self.getBuildDir()
7199451b44SJordan Rupprecht        exe = os.path.join(newdir, 'proc_attach')
7299451b44SJordan Rupprecht        self.buildProgram('main.cpp', exe)
7399451b44SJordan Rupprecht        self.addTearDownHook(lambda: shutil.rmtree(newdir))
7499451b44SJordan Rupprecht
7599451b44SJordan Rupprecht        # Spawn a new process
7699451b44SJordan Rupprecht        popen = self.spawnSubprocess(exe)
7799451b44SJordan Rupprecht
7899451b44SJordan Rupprecht        os.chdir(newdir)
7999451b44SJordan Rupprecht        self.addTearDownHook(lambda: os.chdir(testdir))
8099451b44SJordan Rupprecht        self.runCmd("process attach -p " + str(popen.pid))
8199451b44SJordan Rupprecht
8299451b44SJordan Rupprecht        target = self.dbg.GetSelectedTarget()
8399451b44SJordan Rupprecht
8499451b44SJordan Rupprecht        process = target.GetProcess()
8599451b44SJordan Rupprecht        self.assertTrue(process, PROCESS_IS_VALID)
8699451b44SJordan Rupprecht
8799451b44SJordan Rupprecht    def test_attach_to_process_by_name(self):
8899451b44SJordan Rupprecht        """Test attach by process name"""
8999451b44SJordan Rupprecht        self.build()
9099451b44SJordan Rupprecht        exe = self.getBuildArtifact(exe_name)
9199451b44SJordan Rupprecht
9299451b44SJordan Rupprecht        # Spawn a new process
9399451b44SJordan Rupprecht        popen = self.spawnSubprocess(exe)
9499451b44SJordan Rupprecht
9599451b44SJordan Rupprecht        self.runCmd("process attach -n " + exe_name)
9699451b44SJordan Rupprecht
9799451b44SJordan Rupprecht        target = self.dbg.GetSelectedTarget()
9899451b44SJordan Rupprecht
9999451b44SJordan Rupprecht        process = target.GetProcess()
10099451b44SJordan Rupprecht        self.assertTrue(process, PROCESS_IS_VALID)
10199451b44SJordan Rupprecht
102*58917054SStella Stamenova    @skipIfWindows # This test is flaky on Windows
10399562332SMichał Górny    @expectedFailureNetBSD
104dbfdb139SMichał Górny    def test_attach_to_process_by_id_correct_executable_offset(self):
105dbfdb139SMichał Górny        """
106dbfdb139SMichał Górny        Test that after attaching to a process the executable offset
107dbfdb139SMichał Górny        is determined correctly on FreeBSD.  This is a regression test
108dbfdb139SMichał Górny        for dyld plugin getting the correct executable path,
109dbfdb139SMichał Górny        and therefore being able to identify it in the module list.
110dbfdb139SMichał Górny        """
111dbfdb139SMichał Górny
112dbfdb139SMichał Górny        self.build()
113dbfdb139SMichał Górny        exe = self.getBuildArtifact(exe_name)
114dbfdb139SMichał Górny
115dbfdb139SMichał Górny        # In order to reproduce, we must spawn using a relative path
116dbfdb139SMichał Górny        popen = self.spawnSubprocess(os.path.relpath(exe))
117dbfdb139SMichał Górny
118dbfdb139SMichał Górny        self.runCmd("process attach -p " + str(popen.pid))
119dbfdb139SMichał Górny
1200fd813cfSAdrian Prantl        # Make sure we did not attach too early.
121dbfdb139SMichał Górny        lldbutil.run_break_set_by_file_and_line(
122dbfdb139SMichał Górny            self, "main.cpp", self.line, num_expected_locations=1, loc_exact=False)
123dbfdb139SMichał Górny        self.runCmd("process continue")
12426ba774fSAdrian Prantl        self.expect("v g_val", substrs=["12345"])
125dbfdb139SMichał Górny
12699451b44SJordan Rupprecht    def tearDown(self):
12799451b44SJordan Rupprecht        # Destroy process before TestBase.tearDown()
12899451b44SJordan Rupprecht        self.dbg.GetSelectedTarget().GetProcess().Destroy()
12999451b44SJordan Rupprecht
13099451b44SJordan Rupprecht        # Call super's tearDown().
13199451b44SJordan Rupprecht        TestBase.tearDown(self)
132