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