Currently, it is unclear if a test that is skipped is either:
- Unsupported because it will never run (macosx tests should not run on
Windows).
- Skipped because it's supposed to work but does not yet.
`@expectedFailure` is not always an option because a test might be
timing out and waiting 600s for it to fail is not acceptable.
This patch introduces 2 new decorators to differentiate those tests:
- `@requireX` meaning the tests require X to run (e.g `@requireDarwin`).
- `@requireNotX` meaning the tests requires anything but `X` to run (e.g
`@requireNotDarwin`).
In the tests results summary, this introduces a new category: `skipped`
tests:
- `@requireX` -> `UNSUPPORTED`
- `@skipIfX` -> `SKIPPED`
Here is how they can and cannot be stacked:
This will never run:
```py3
@requireDarwin
@requireWindows
def test():
...
```
This will not run on Linux, because `@requireWindows` is not satisfied.
```py3
@requireNotDarwin
@requireWindows
def test():
...
```
For "require Darwin or Windows", you need:
```py3
@requirePlatform(["darwin", "windows"])
def test():
...
```
For "require Darwin on ARM64 or Windows on ARM64", you need:
```py3
@requireARM64
@requirePlatform(["darwin", "windows"])
def test():
...
```
This patch also converts the tests in
`lldb/tests/API/{macosx,linux,windows}` to use these decorators. Patches
to convert the rest of the tests will follow.
117 lines
4.3 KiB
Python
117 lines
4.3 KiB
Python
"""Test stepping and setting breakpoints in indirect and re-exported symbols."""
|
|
|
|
|
|
import lldb
|
|
from lldbsuite.test.decorators import *
|
|
from lldbsuite.test.lldbtest import *
|
|
from lldbsuite.test import lldbutil
|
|
|
|
|
|
class TestIndirectFunctions(TestBase):
|
|
def setUp(self):
|
|
# Call super's setUp().
|
|
TestBase.setUp(self)
|
|
# Find the line numbers that we will step to in main:
|
|
self.main_source = "main.c"
|
|
|
|
@requireDarwin
|
|
@add_test_categories(["pyapi"])
|
|
@skipIf(bugnumber="rdar://120796553")
|
|
def test_with_python_api(self):
|
|
"""Test stepping and setting breakpoints in indirect and re-exported symbols."""
|
|
self.build()
|
|
exe = self.getBuildArtifact("a.out")
|
|
|
|
target = self.dbg.CreateTarget(exe)
|
|
self.assertTrue(target, VALID_TARGET)
|
|
|
|
lib1 = self.getBuildArtifact("libindirect.dylib")
|
|
lib2 = self.getBuildArtifact("libreexport.dylib")
|
|
self.registerSharedLibrariesWithTarget(target, [lib1, lib2])
|
|
|
|
self.main_source_spec = lldb.SBFileSpec(self.main_source)
|
|
|
|
break1 = target.BreakpointCreateBySourceRegex(
|
|
"Set breakpoint here to step in indirect.", self.main_source_spec
|
|
)
|
|
self.assertTrue(break1, VALID_BREAKPOINT)
|
|
|
|
break2 = target.BreakpointCreateBySourceRegex(
|
|
"Set breakpoint here to step in reexported.", self.main_source_spec
|
|
)
|
|
self.assertTrue(break2, VALID_BREAKPOINT)
|
|
|
|
# Now launch the process, and do not stop at entry point.
|
|
process = target.LaunchSimple(None, None, self.get_process_working_directory())
|
|
|
|
self.assertTrue(process, PROCESS_IS_VALID)
|
|
|
|
# The stop reason of the thread should be breakpoint.
|
|
threads = lldbutil.get_threads_stopped_at_breakpoint(process, break1)
|
|
if len(threads) != 1:
|
|
self.fail("Failed to stop at breakpoint 1.")
|
|
|
|
thread = threads[0]
|
|
|
|
# Now do a step-into, and we should end up in the hidden target of this
|
|
# indirect function.
|
|
thread.StepInto()
|
|
curr_function = thread.GetFrameAtIndex(0).GetFunctionName()
|
|
self.assertEqual(
|
|
curr_function,
|
|
"call_through_indirect_hidden",
|
|
"Stepped into indirect symbols.",
|
|
)
|
|
|
|
# Now set a breakpoint using the indirect symbol name, and make sure we
|
|
# get to that:
|
|
break_indirect = target.BreakpointCreateByName("call_through_indirect")
|
|
self.assertTrue(break_indirect, VALID_BREAKPOINT)
|
|
|
|
# Now continue should take us to the second call through the indirect
|
|
# symbol:
|
|
|
|
threads = lldbutil.continue_to_breakpoint(process, break_indirect)
|
|
self.assertEqual(len(threads), 1, "Stopped at breakpoint in indirect function.")
|
|
curr_function = thread.GetFrameAtIndex(0).GetFunctionName()
|
|
self.assertEqual(
|
|
curr_function,
|
|
"call_through_indirect_hidden",
|
|
"Stepped into indirect symbols.",
|
|
)
|
|
|
|
# Delete this breakpoint so it won't get in the way:
|
|
target.BreakpointDelete(break_indirect.GetID())
|
|
|
|
# Now continue to the site of the first re-exported function call in
|
|
# main:
|
|
threads = lldbutil.continue_to_breakpoint(process, break2)
|
|
|
|
# This is stepping Into through a re-exported symbol to an indirect
|
|
# symbol:
|
|
thread.StepInto()
|
|
curr_function = thread.GetFrameAtIndex(0).GetFunctionName()
|
|
self.assertEqual(
|
|
curr_function,
|
|
"call_through_indirect_hidden",
|
|
"Stepped into indirect symbols.",
|
|
)
|
|
|
|
# And the last bit is to set a breakpoint on the re-exported symbol and
|
|
# make sure we are again in out target function.
|
|
break_reexported = target.BreakpointCreateByName("reexport_to_indirect")
|
|
self.assertEqual(break_reexported.GetNumLocations(), 1, VALID_BREAKPOINT)
|
|
|
|
# Now continue should take us to the second call through the indirect
|
|
# symbol:
|
|
|
|
threads = lldbutil.continue_to_breakpoint(process, break_reexported)
|
|
self.assertEqual(
|
|
len(threads), 1, "Stopped at breakpoint in reexported function target."
|
|
)
|
|
curr_function = thread.GetFrameAtIndex(0).GetFunctionName()
|
|
self.assertEqual(
|
|
curr_function,
|
|
"call_through_indirect_hidden",
|
|
"Stepped into indirect symbols.",
|
|
)
|