mirror-llvm-project/lldb/test/API/macosx/nslog/TestDarwinNSLogOutput.py
Charles Zablit 67a20745d6
[lldb] Introduce the require decorator (#212753)
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.
2026-08-01 18:03:29 +02:00

159 lines
5.6 KiB
Python

"""
Test DarwinLog "source include debug-level" functionality provided by the
StructuredDataDarwinLog plugin.
These tests are currently only supported when running against Darwin
targets.
"""
import lldb
import platform
import re
import sys
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbtest_config
class DarwinNSLogOutputTestCase(TestBase):
SHARED_BUILD_TESTCASE = False
NO_DEBUG_INFO_TESTCASE = True
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
self.child = None
self.child_prompt = "(lldb) "
self.strict_sources = False
# Source filename.
self.source = "main.m"
# Output filename.
self.exe_name = self.getBuildArtifact("a.out")
self.d = {"OBJC_SOURCES": self.source, "EXE": self.exe_name}
# Locate breakpoint.
self.line = line_number(self.source, "// break here")
def tearDown(self):
# Shut down the process if it's still running.
if self.child:
self.runCmd("process kill")
self.expect_prompt()
self.runCmd("quit")
# Let parent clean up
super(DarwinNSLogOutputTestCase, self).tearDown()
def run_lldb_to_breakpoint(self, exe, source_file, line, settings_commands=None):
# Set self.child_prompt, which is "(lldb) ".
prompt = self.child_prompt
# So that the child gets torn down after the test.
import pexpect
self.child = pexpect.spawn(
"%s %s %s" % (lldbtest_config.lldbExec, self.lldbOption, exe),
encoding="utf-8",
)
child = self.child
# Turn on logging for what the child sends back.
if self.TraceOn():
child.logfile_read = sys.stdout
# Disable showing of source lines at our breakpoint.
# This is necessary for the logging tests, because the very
# text we want to match for output from the running inferior
# will show up in the source as well. We don't want the source
# output to erroneously make a match with our expected output.
self.runCmd("settings set stop-line-count-before 0")
self.expect_prompt()
self.runCmd("settings set stop-line-count-after 0")
self.expect_prompt()
# Run any test-specific settings commands now.
if settings_commands is not None:
for setting_command in settings_commands:
self.runCmd(setting_command)
self.expect_prompt()
# Set the breakpoint, and run to it.
child.sendline("breakpoint set -f %s -l %d" % (source_file, line))
child.expect_exact(prompt)
child.sendline("run")
child.expect_exact(prompt)
# Ensure we stopped at a breakpoint.
self.runCmd("thread list")
self.expect(re.compile(r"stop reason = .*breakpoint"))
def runCmd(self, cmd):
if self.child:
self.child.sendline(cmd)
def expect_prompt(self, exactly=True):
self.expect(self.child_prompt, exactly=exactly)
def expect(self, pattern, exactly=False, *args, **kwargs):
if exactly:
return self.child.expect_exact(pattern, *args, **kwargs)
return self.child.expect(pattern, *args, **kwargs)
def do_test(self, expect_regexes=None, settings_commands=None):
"""Run a test."""
self.build(dictionary=self.d)
self.setTearDownCleanup(dictionary=self.d)
exe = self.getBuildArtifact(self.exe_name)
self.run_lldb_to_breakpoint(
exe, self.source, self.line, settings_commands=settings_commands
)
self.expect_prompt()
# Now go.
self.runCmd("process continue")
self.expect(expect_regexes)
@skipIfAsan # avoid dealing with pexpect timeout flakyness on bots
@skipIf(oslist=["linux"], archs=["arm$", "aarch64"])
@requireDarwin
@skipIfRemote # this test is currently written using lldb commands & assumes running on local system
def test_nslog_output_is_displayed(self):
"""Test that NSLog() output shows up in the command-line debugger."""
self.do_test(
expect_regexes=[
re.compile(r"(This is a message from NSLog)"),
re.compile(r"Process \d+ exited with status"),
]
)
self.assertIsNotNone(self.child.match)
self.assertGreater(len(self.child.match.groups()), 0)
self.assertEqual("This is a message from NSLog", self.child.match.group(1))
@skipIfAsan # avoid dealing with pexpect timeout flakyness on bots
@skipIf(oslist=["linux"], archs=["arm$", "aarch64"])
@requireDarwin
@skipIfRemote # this test is currently written using lldb commands & assumes running on local system
def test_nslog_output_is_suppressed_with_env_var(self):
"""Test that NSLog() output does not show up with the ignore env var."""
# This test will only work properly on macOS 10.12+. Skip it on earlier versions.
# This will require some tweaking on iOS.
match = re.match(r"^\d+\.(\d+)", platform.mac_ver()[0])
if match is None or int(match.group(1)) < 12:
self.skipTest("requires macOS 10.12 or higher")
self.do_test(
expect_regexes=[
re.compile(r"(This is a message from NSLog)"),
re.compile(r"Process \d+ exited with status"),
],
settings_commands=[
"settings set target.env-vars " '"IDE_DISABLED_OS_ACTIVITY_DT_MODE=1"'
],
)
self.assertIsNotNone(self.child.match)
self.assertEqual(len(self.child.match.groups()), 0)