Skip to content

Commit 6b62652

Browse files
furkanonderambv
authored andcommitted
[3.11] pythongh-104280: Add test cases for DTrace probes (pythonGH-107125)
(cherry picked from commit a1c737b) Co-authored-by: Furkan Onder <[email protected]>
1 parent aa5f2b1 commit 6b62652

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

Lib/test/test_dtrace.py

+82
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import re
44
import subprocess
55
import sys
6+
import sysconfig
67
import types
78
import unittest
89

@@ -173,6 +174,87 @@ class SystemTapOptimizedTests(TraceTests, unittest.TestCase):
173174
backend = SystemTapBackend()
174175
optimize_python = 2
175176

177+
class CheckDtraceProbes(unittest.TestCase):
178+
@classmethod
179+
def setUpClass(cls):
180+
if sysconfig.get_config_var('WITH_DTRACE'):
181+
readelf_major_version, readelf_minor_version = cls.get_readelf_version()
182+
if support.verbose:
183+
print(f"readelf version: {readelf_major_version}.{readelf_minor_version}")
184+
else:
185+
raise unittest.SkipTest("CPython must be configured with the --with-dtrace option.")
186+
187+
188+
@staticmethod
189+
def get_readelf_version():
190+
try:
191+
cmd = ["readelf", "--version"]
192+
proc = subprocess.Popen(
193+
cmd,
194+
stdout=subprocess.PIPE,
195+
stderr=subprocess.PIPE,
196+
universal_newlines=True,
197+
)
198+
with proc:
199+
version, stderr = proc.communicate()
200+
201+
if proc.returncode:
202+
raise Exception(
203+
f"Command {' '.join(cmd)!r} failed "
204+
f"with exit code {proc.returncode}: "
205+
f"stdout={version!r} stderr={stderr!r}"
206+
)
207+
except OSError:
208+
raise unittest.SkipTest("Couldn't find readelf on the path")
209+
210+
# Regex to parse:
211+
# 'GNU readelf (GNU Binutils) 2.40.0\n' -> 2.40
212+
match = re.search(r"^(?:GNU) readelf.*?\b(\d+)\.(\d+)", version)
213+
if match is None:
214+
raise unittest.SkipTest(f"Unable to parse readelf version: {version}")
215+
216+
return int(match.group(1)), int(match.group(2))
217+
218+
def get_readelf_output(self):
219+
command = ["readelf", "-n", sys.executable]
220+
stdout, _ = subprocess.Popen(
221+
command,
222+
stdout=subprocess.PIPE,
223+
stderr=subprocess.STDOUT,
224+
universal_newlines=True,
225+
).communicate()
226+
return stdout
227+
228+
def test_check_probes(self):
229+
readelf_output = self.get_readelf_output()
230+
231+
available_probe_names = [
232+
"Name: import__find__load__done",
233+
"Name: import__find__load__start",
234+
"Name: audit",
235+
"Name: gc__start",
236+
"Name: gc__done",
237+
]
238+
239+
for probe_name in available_probe_names:
240+
with self.subTest(probe_name=probe_name):
241+
self.assertIn(probe_name, readelf_output)
242+
243+
@unittest.expectedFailure
244+
def test_missing_probes(self):
245+
readelf_output = self.get_readelf_output()
246+
247+
# Missing probes will be added in the future.
248+
missing_probe_names = [
249+
"Name: function__entry",
250+
"Name: function__return",
251+
"Name: line",
252+
]
253+
254+
for probe_name in missing_probe_names:
255+
with self.subTest(probe_name=probe_name):
256+
self.assertIn(probe_name, readelf_output)
257+
176258

177259
if __name__ == '__main__':
178260
unittest.main()

0 commit comments

Comments
 (0)