(self)
| 49 | |
| 50 | @unittest.skipIf(support.check_bolt_optimized(), "fails on BOLT instrumented binaries") |
| 51 | def test_trampoline_works(self): |
| 52 | code = """if 1: |
| 53 | def foo(): |
| 54 | pass |
| 55 | |
| 56 | def bar(): |
| 57 | foo() |
| 58 | |
| 59 | def baz(): |
| 60 | bar() |
| 61 | |
| 62 | baz() |
| 63 | """ |
| 64 | with temp_dir() as script_dir: |
| 65 | script = make_script(script_dir, "perftest", code) |
| 66 | env = {**os.environ, "PYTHON_JIT": "0"} |
| 67 | with subprocess.Popen( |
| 68 | [sys.executable, "-Xperf", script], |
| 69 | text=True, |
| 70 | stderr=subprocess.PIPE, |
| 71 | stdout=subprocess.PIPE, |
| 72 | env=env, |
| 73 | ) as process: |
| 74 | stdout, stderr = process.communicate() |
| 75 | |
| 76 | self.assertEqual(stderr, "") |
| 77 | self.assertEqual(stdout, "") |
| 78 | |
| 79 | perf_file = pathlib.Path(f"/tmp/perf-{process.pid}.map") |
| 80 | self.assertTrue(perf_file.exists()) |
| 81 | perf_file_contents = perf_file.read_text() |
| 82 | perf_lines = perf_file_contents.splitlines() |
| 83 | expected_symbols = [ |
| 84 | f"py::foo:{script}", |
| 85 | f"py::bar:{script}", |
| 86 | f"py::baz:{script}", |
| 87 | ] |
| 88 | for expected_symbol in expected_symbols: |
| 89 | perf_line = next( |
| 90 | (line for line in perf_lines if expected_symbol in line), None |
| 91 | ) |
| 92 | self.assertIsNotNone( |
| 93 | perf_line, f"Could not find {expected_symbol} in perf file" |
| 94 | ) |
| 95 | perf_addr = perf_line.split(" ")[0] |
| 96 | self.assertNotStartsWith(perf_addr, "0x") |
| 97 | self.assertTrue( |
| 98 | set(perf_addr).issubset(string.hexdigits), |
| 99 | "Address should contain only hex characters", |
| 100 | ) |
| 101 | |
| 102 | @unittest.skipIf(support.check_bolt_optimized(), "fails on BOLT instrumented binaries") |
| 103 | def test_trampoline_works_with_forks(self): |
nothing calls this directly
no test coverage detected