1"""Test Python APIs for target (launch and attach), breakpoint, and process."""
2
3
4
5import os
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10import lldbsuite.test.lldbutil as lldbutil
11
12class HelloWorldTestCase(TestBase):
13    NO_DEBUG_INFO_TESTCASE = True
14    mydir = TestBase.compute_mydir(__file__)
15
16    def setUp(self):
17        # Call super's setUp().
18        TestBase.setUp(self)
19        # Find a couple of the line numbers within main.c.
20        self.line1 = line_number('main.c', '// Set break point at this line.')
21        self.line2 = line_number('main.c', '// Waiting to be attached...')
22
23    def tearDown(self):
24        # Destroy process before TestBase.tearDown()
25        self.dbg.GetSelectedTarget().GetProcess().Destroy()
26        # Call super's tearDown().
27        TestBase.tearDown(self)
28
29    @skipIfiOSSimulator
30    def test_with_process_launch_api(self):
31        """Create target, breakpoint, launch a process, and then kill it."""
32        # Get the full path to our executable to be attached/debugged.
33        exe = '%s_%d'%(self.getBuildArtifact(self.testMethodName), os.getpid())
34        d = {'EXE': exe}
35        self.build(dictionary=d)
36        self.setTearDownCleanup(dictionary=d)
37        target = self.dbg.CreateTarget(exe)
38
39        breakpoint = target.BreakpointCreateByLocation("main.c", self.line1)
40
41        # The default state after breakpoint creation should be enabled.
42        self.assertTrue(breakpoint.IsEnabled(),
43                        "Breakpoint should be enabled after creation")
44
45        breakpoint.SetEnabled(False)
46        self.assertTrue(not breakpoint.IsEnabled(),
47                        "Breakpoint.SetEnabled(False) works")
48
49        breakpoint.SetEnabled(True)
50        self.assertTrue(breakpoint.IsEnabled(),
51                        "Breakpoint.SetEnabled(True) works")
52
53        # rdar://problem/8364687
54        # SBTarget.Launch() issue (or is there some race condition)?
55
56        process = target.LaunchSimple(
57            None, None, self.get_process_working_directory())
58        # The following isn't needed anymore, rdar://8364687 is fixed.
59        #
60        # Apply some dances after LaunchProcess() in order to break at "main".
61        # It only works sometimes.
62        #self.breakAfterLaunch(process, "main")
63
64        process = target.GetProcess()
65        self.assertTrue(process, PROCESS_IS_VALID)
66
67        thread = lldbutil.get_stopped_thread(
68            process, lldb.eStopReasonBreakpoint)
69        self.assertIsNotNone(thread)
70
71        # The breakpoint should have a hit count of 1.
72        self.assertEqual(breakpoint.GetHitCount(), 1, BREAKPOINT_HIT_ONCE)
73
74    @skipIfiOSSimulator
75    @skipIfReproducer # File synchronization is not supported during replay.
76    def test_with_attach_to_process_with_id_api(self):
77        """Create target, spawn a process, and attach to it with process id."""
78        exe = '%s_%d'%(self.testMethodName, os.getpid())
79        d = {'EXE': exe}
80        self.build(dictionary=d)
81        self.setTearDownCleanup(dictionary=d)
82        target = self.dbg.CreateTarget(self.getBuildArtifact(exe))
83
84        # Spawn a new process
85        token = exe+'.token'
86        if not lldb.remote_platform:
87            token = self.getBuildArtifact(token)
88            if os.path.exists(token):
89                os.remove(token)
90        popen = self.spawnSubprocess(self.getBuildArtifact(exe), [token])
91        lldbutil.wait_for_file_on_target(self, token)
92
93        listener = lldb.SBListener("my.attach.listener")
94        error = lldb.SBError()
95        process = target.AttachToProcessWithID(listener, popen.pid, error)
96
97        self.assertTrue(error.Success() and process, PROCESS_IS_VALID)
98
99        # Let's check the stack traces of the attached process.
100        stacktraces = lldbutil.print_stacktraces(process, string_buffer=True)
101        self.expect(stacktraces, exe=False,
102                    substrs=['main.c:%d' % self.line2,
103                             '(int)argc=2'])
104
105    @skipIfiOSSimulator
106    @skipIfAsan # FIXME: Hangs indefinitely.
107    @skipIfReproducer # FIXME: Unexpected packet during (active) replay
108    def test_with_attach_to_process_with_name_api(self):
109        """Create target, spawn a process, and attach to it with process name."""
110        exe = '%s_%d'%(self.testMethodName, os.getpid())
111        d = {'EXE': exe}
112        self.build(dictionary=d)
113        self.setTearDownCleanup(dictionary=d)
114        target = self.dbg.CreateTarget(self.getBuildArtifact(exe))
115
116        # Spawn a new process.
117        token = exe+'.token'
118        if not lldb.remote_platform:
119            token = self.getBuildArtifact(token)
120            if os.path.exists(token):
121                os.remove(token)
122        popen = self.spawnSubprocess(self.getBuildArtifact(exe), [token])
123        lldbutil.wait_for_file_on_target(self, token)
124
125        listener = lldb.SBListener("my.attach.listener")
126        error = lldb.SBError()
127        # Pass 'False' since we don't want to wait for new instance of
128        # "hello_world" to be launched.
129        name = os.path.basename(exe)
130
131        # While we're at it, make sure that passing a None as the process name
132        # does not hang LLDB.
133        target.AttachToProcessWithName(listener, None, False, error)
134        # Also boundary condition test ConnectRemote(), too.
135        target.ConnectRemote(listener, None, None, error)
136
137        process = target.AttachToProcessWithName(listener, name, False, error)
138        self.assertSuccess(error)
139        self.assertTrue(process, PROCESS_IS_VALID)
140
141        # Verify that after attach, our selected target indeed matches name.
142        self.expect(
143            self.dbg.GetSelectedTarget().GetExecutable().GetFilename(),
144            exe=False,
145            startstr=name)
146
147        # Let's check the stack traces of the attached process.
148        stacktraces = lldbutil.print_stacktraces(process, string_buffer=True)
149        self.expect(stacktraces, exe=False,
150                    substrs=['main.c:%d' % self.line2,
151                             '(int)argc=2'])
152