-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_run.py
More file actions
115 lines (86 loc) · 4.04 KB
/
Copy pathtest_run.py
File metadata and controls
115 lines (86 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
"""End-to-end tests for the profiler on the bundled example workload."""
from __future__ import annotations
import os
import pytest
from profile_diff.diff import compare
from profile_diff.profiler import build_run_fn, normalize_path, profile
@pytest.fixture
def fast_slow_env():
"""Restore PROFILE_DIFF_SLOW after each test."""
saved = os.environ.get("PROFILE_DIFF_SLOW")
yield
if saved is None:
os.environ.pop("PROFILE_DIFF_SLOW", None)
else:
os.environ["PROFILE_DIFF_SLOW"] = saved
def _profile_workload(label):
run_fn, target = build_run_fn(callable_ref="examples.workload:run_workload")
return profile(run_fn, label=label, target=target, top_n=30)
def test_run_produces_valid_report(fast_slow_env):
os.environ["PROFILE_DIFF_SLOW"] = "0"
report = _profile_workload("head")
assert report["schema_version"] == 1
assert report["label"] == "head"
assert "python_version" in report["metadata"]
assert report["metadata"]["target"].startswith("callable ")
assert report["total_time_s"] >= 0.0
assert report["functions"], "expected at least one function record"
rec = report["functions"][0]
assert set(rec) == {"key", "ncalls", "tottime", "cumtime"}
# Records are sorted by cumtime descending.
cumtimes = [f["cumtime"] for f in report["functions"]]
assert cumtimes == sorted(cumtimes, reverse=True)
# The workload's own function should appear in the profile.
assert any("run_workload" in f["key"] for f in report["functions"])
mem = report["memory"]
assert mem["peak_bytes"] > 0
assert isinstance(mem["top_allocations"], list)
def test_top_n_is_respected(fast_slow_env):
os.environ["PROFILE_DIFF_SLOW"] = "1"
run_fn, target = build_run_fn(callable_ref="examples.workload:run_workload")
report = profile(run_fn, label="x", target=target, top_n=5)
assert len(report["functions"]) <= 5
assert report["metadata"]["top_n"] == 5
def test_run_then_compare_shows_regression(fast_slow_env):
# Base = fast implementation, head = slow implementation -> regression.
os.environ["PROFILE_DIFF_SLOW"] = "0"
base = _profile_workload("base")
os.environ["PROFILE_DIFF_SLOW"] = "1"
head = _profile_workload("head")
result = compare(base, head, threshold_pct=5.0)
# The slow path must take strictly longer overall.
assert result.head_total_s > result.base_total_s
assert result.total_delta_s > 0
# The shared entry point (run_workload) should register as a regression,
# and the slow O(n^2) helper should surface as a regression or new hotspot.
reg_keys = {d.key for d in result.regressions}
new_keys = {d.key for d in result.new_hotspots}
assert any("run_workload" in k for k in reg_keys)
assert any("count_duplicate_pairs_slow" in k for k in reg_keys | new_keys)
assert result.has_regression is True
def test_run_then_compare_shows_improvement(fast_slow_env):
# Reverse direction: base = slow, head = fast -> improvement.
os.environ["PROFILE_DIFF_SLOW"] = "1"
base = _profile_workload("base")
os.environ["PROFILE_DIFF_SLOW"] = "0"
head = _profile_workload("head")
result = compare(base, head, threshold_pct=5.0)
assert result.total_delta_s < 0
imp_keys = {d.key for d in result.improvements}
assert any("run_workload" in k for k in imp_keys)
def test_script_target_runs(tmp_path):
script = tmp_path / "tiny.py"
script.write_text("x = sum(range(1000))\n")
run_fn, target = build_run_fn(script=str(script))
report = profile(run_fn, label="s", target=target)
assert target.startswith("script ")
assert report["functions"] # <module> etc. captured
def test_build_run_fn_requires_exactly_one_target():
with pytest.raises(ValueError):
build_run_fn() # none
with pytest.raises(ValueError):
build_run_fn(script="a.py", callable_ref="m:f") # two
def test_normalize_path_relativises_cwd_paths():
inside = os.path.join(os.getcwd(), "pkg", "mod.py")
assert normalize_path(inside) == "pkg/mod.py"
assert normalize_path("<string>") == "<string>"