150
|
1 """
|
|
2 Test DarwinLog "source include debug-level" functionality provided by the
|
|
3 StructuredDataDarwinLog plugin.
|
|
4
|
|
5 These tests are currently only supported when running against Darwin
|
|
6 targets.
|
|
7 """
|
|
8
|
|
9
|
|
10 import lldb
|
|
11 import platform
|
|
12 import re
|
|
13
|
|
14 from lldbsuite.test.decorators import *
|
|
15 from lldbsuite.test.lldbtest import *
|
|
16 from lldbsuite.test import lldbtest_config
|
|
17
|
|
18
|
|
19 class DarwinNSLogOutputTestCase(TestBase):
|
|
20 NO_DEBUG_INFO_TESTCASE = True
|
|
21 mydir = TestBase.compute_mydir(__file__)
|
|
22
|
|
23 @skipUnlessDarwin
|
|
24 @skipIfRemote # this test is currently written using lldb commands & assumes running on local system
|
|
25
|
|
26 def setUp(self):
|
|
27 # Call super's setUp().
|
|
28 TestBase.setUp(self)
|
|
29 self.child = None
|
|
30 self.child_prompt = '(lldb) '
|
|
31 self.strict_sources = False
|
|
32
|
|
33 # Source filename.
|
|
34 self.source = 'main.m'
|
|
35
|
|
36 # Output filename.
|
|
37 self.exe_name = self.getBuildArtifact("a.out")
|
|
38 self.d = {'OBJC_SOURCES': self.source, 'EXE': self.exe_name}
|
|
39
|
|
40 # Locate breakpoint.
|
|
41 self.line = line_number(self.source, '// break here')
|
|
42
|
|
43 def tearDown(self):
|
|
44 # Shut down the process if it's still running.
|
|
45 if self.child:
|
|
46 self.runCmd('process kill')
|
|
47 self.expect_prompt()
|
|
48 self.runCmd('quit')
|
|
49
|
|
50 # Let parent clean up
|
|
51 super(DarwinNSLogOutputTestCase, self).tearDown()
|
|
52
|
|
53 def run_lldb_to_breakpoint(self, exe, source_file, line,
|
|
54 settings_commands=None):
|
|
55 # Set self.child_prompt, which is "(lldb) ".
|
|
56 prompt = self.child_prompt
|
|
57
|
|
58 # So that the child gets torn down after the test.
|
|
59 import pexpect
|
|
60 import sys
|
|
61 if sys.version_info.major == 3:
|
|
62 self.child = pexpect.spawnu('%s %s %s' % (lldbtest_config.lldbExec,
|
|
63 self.lldbOption, exe))
|
|
64 else:
|
|
65 self.child = pexpect.spawn('%s %s %s' % (lldbtest_config.lldbExec,
|
|
66 self.lldbOption, exe))
|
|
67 child = self.child
|
|
68
|
|
69 # Turn on logging for what the child sends back.
|
|
70 if self.TraceOn():
|
|
71 child.logfile_read = sys.stdout
|
|
72
|
|
73 # Disable showing of source lines at our breakpoint.
|
|
74 # This is necessary for the logging tests, because the very
|
|
75 # text we want to match for output from the running inferior
|
|
76 # will show up in the source as well. We don't want the source
|
|
77 # output to erroneously make a match with our expected output.
|
|
78 self.runCmd("settings set stop-line-count-before 0")
|
|
79 self.expect_prompt()
|
|
80 self.runCmd("settings set stop-line-count-after 0")
|
|
81 self.expect_prompt()
|
|
82
|
|
83 # Run any test-specific settings commands now.
|
|
84 if settings_commands is not None:
|
|
85 for setting_command in settings_commands:
|
|
86 self.runCmd(setting_command)
|
|
87 self.expect_prompt()
|
|
88
|
|
89 # Set the breakpoint, and run to it.
|
|
90 child.sendline('breakpoint set -f %s -l %d' % (source_file, line))
|
|
91 child.expect_exact(prompt)
|
|
92 child.sendline('run')
|
|
93 child.expect_exact(prompt)
|
|
94
|
|
95 # Ensure we stopped at a breakpoint.
|
|
96 self.runCmd("thread list")
|
|
97 self.expect(re.compile(r"stop reason = .*breakpoint"))
|
|
98
|
|
99 def runCmd(self, cmd):
|
|
100 if self.child:
|
|
101 self.child.sendline(cmd)
|
|
102
|
|
103 def expect_prompt(self, exactly=True):
|
|
104 self.expect(self.child_prompt, exactly=exactly)
|
|
105
|
|
106 def expect(self, pattern, exactly=False, *args, **kwargs):
|
|
107 if exactly:
|
|
108 return self.child.expect_exact(pattern, *args, **kwargs)
|
|
109 return self.child.expect(pattern, *args, **kwargs)
|
|
110
|
|
111 def do_test(self, expect_regexes=None, settings_commands=None):
|
|
112 """ Run a test. """
|
|
113 self.build(dictionary=self.d)
|
|
114 self.setTearDownCleanup(dictionary=self.d)
|
|
115
|
|
116 exe = self.getBuildArtifact(self.exe_name)
|
|
117 self.run_lldb_to_breakpoint(exe, self.source, self.line,
|
|
118 settings_commands=settings_commands)
|
|
119 self.expect_prompt()
|
|
120
|
|
121 # Now go.
|
|
122 self.runCmd("process continue")
|
|
123 self.expect(expect_regexes)
|
|
124
|
|
125 def test_nslog_output_is_displayed(self):
|
|
126 """Test that NSLog() output shows up in the command-line debugger."""
|
|
127 self.do_test(expect_regexes=[
|
|
128 re.compile(r"(This is a message from NSLog)"),
|
|
129 re.compile(r"Process \d+ exited with status")
|
|
130 ])
|
|
131 self.assertIsNotNone(self.child.match)
|
|
132 self.assertGreater(len(self.child.match.groups()), 0)
|
|
133 self.assertEqual(
|
|
134 "This is a message from NSLog",
|
|
135 self.child.match.group(1))
|
|
136
|
|
137 def test_nslog_output_is_suppressed_with_env_var(self):
|
|
138 """Test that NSLog() output does not show up with the ignore env var."""
|
|
139 # This test will only work properly on macOS 10.12+. Skip it on earlier versions.
|
|
140 # This will require some tweaking on iOS.
|
|
141 match = re.match(r"^\d+\.(\d+)", platform.mac_ver()[0])
|
|
142 if match is None or int(match.group(1)) < 12:
|
|
143 self.skipTest("requires macOS 10.12 or higher")
|
|
144
|
|
145 self.do_test(
|
|
146 expect_regexes=[
|
|
147 re.compile(r"(This is a message from NSLog)"),
|
|
148 re.compile(r"Process \d+ exited with status")
|
|
149 ],
|
|
150 settings_commands=[
|
|
151 "settings set target.env-vars "
|
|
152 "\"IDE_DISABLED_OS_ACTIVITY_DT_MODE=1\""
|
|
153 ])
|
|
154 self.assertIsNotNone(self.child.match)
|
|
155 self.assertEqual(len(self.child.match.groups()), 0)
|