CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
184 lines
7.1 KiB
Python
184 lines
7.1 KiB
Python
# Copyright (c) Advanced Micro Devices, Inc.
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
from unittest.mock import Mock
|
|
|
|
from common import patch_console
|
|
|
|
from pc_sampling.pc_sampling_profile import PCSamplingProfile
|
|
|
|
MODULE = "pc_sampling.pc_sampling_profile"
|
|
|
|
|
|
class MockArgs:
|
|
def __init__(self, **kwargs):
|
|
for key, value in kwargs.items():
|
|
setattr(self, key, value)
|
|
|
|
|
|
def _make_pc_sampling_profile(profiler="rocprofiler-sdk", filter_blocks=("21",)):
|
|
"""Build a PCSamplingProfile runner; options are supplied per launch."""
|
|
return PCSamplingProfile(
|
|
args=MockArgs(filter_blocks=list(filter_blocks)),
|
|
profiler=profiler,
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# sdk backend launch
|
|
# ---------------------------------------------------------------------------
|
|
def test_sdk_forwards_options_env_and_runs_app_cmd(monkeypatch):
|
|
"""sdk launch overlays the options env, pops APP_CMD, and runs it."""
|
|
options = {
|
|
"APP_CMD": "my_app --arg",
|
|
"LD_PRELOAD": "/sdk/tool.so",
|
|
"ROCPROF_PC_SAMPLING_METHOD": "host_trap",
|
|
}
|
|
|
|
mock_capture = Mock(return_value=(True, "Success output"))
|
|
monkeypatch.setattr(f"{MODULE}.capture_subprocess_output", mock_capture)
|
|
mock_error = patch_console(monkeypatch, MODULE, "debug", "error")["error"]
|
|
|
|
_make_pc_sampling_profile()._launch(options)
|
|
|
|
assert mock_capture.call_args.args[0] == "my_app --arg"
|
|
called_env = mock_capture.call_args.kwargs.get("new_env", {})
|
|
assert called_env["LD_PRELOAD"] == "/sdk/tool.so"
|
|
assert called_env["ROCPROF_PC_SAMPLING_METHOD"] == "host_trap"
|
|
mock_error.assert_not_called()
|
|
|
|
|
|
def test_sdk_missing_app_cmd_errors(monkeypatch):
|
|
"""sdk non-live-attach without APP_CMD errors before launching."""
|
|
mock_capture = Mock()
|
|
monkeypatch.setattr(f"{MODULE}.capture_subprocess_output", mock_capture)
|
|
mock_error = patch_console(monkeypatch, MODULE, "debug", "error")["error"]
|
|
|
|
_make_pc_sampling_profile()._launch({"LD_PRELOAD": "x"})
|
|
|
|
assert mock_error.called
|
|
assert "APP_CMD" in mock_error.call_args.args[0]
|
|
mock_capture.assert_not_called()
|
|
|
|
|
|
def test_sdk_subprocess_failure_errors(monkeypatch):
|
|
"""A failed subprocess reports the standard PC sampling failure."""
|
|
mock_capture = Mock(return_value=(False, "Error output"))
|
|
monkeypatch.setattr(f"{MODULE}.capture_subprocess_output", mock_capture)
|
|
mock_error = patch_console(monkeypatch, MODULE, "debug", "error")["error"]
|
|
|
|
_make_pc_sampling_profile()._launch({"APP_CMD": "my_app"})
|
|
|
|
assert mock_error.called
|
|
assert "PC sampling failed." in mock_error.call_args.args[0]
|
|
|
|
|
|
def test_sdk_env_log_excludes_user_env(monkeypatch):
|
|
"""The debug env log records the overlaid vars but never the user's env."""
|
|
monkeypatch.setenv("LEAK_CANARY_TOKEN", "SHOULD_NOT_APPEAR")
|
|
mock_capture = Mock(return_value=(True, "Success output"))
|
|
monkeypatch.setattr(f"{MODULE}.capture_subprocess_output", mock_capture)
|
|
_mocks = patch_console(monkeypatch, MODULE, "debug", "error")
|
|
mock_debug, mock_error = _mocks["debug"], _mocks["error"]
|
|
|
|
_make_pc_sampling_profile()._launch({
|
|
"APP_CMD": "my_app",
|
|
"ROCPROF_PC_SAMPLING_METHOD": "host_trap",
|
|
})
|
|
|
|
logs = [str(call.args[0]) for call in mock_debug.call_args_list]
|
|
env_log_lines = [m for m in logs if "env vars" in m]
|
|
assert env_log_lines
|
|
assert any("ROCPROF_PC_SAMPLING_METHOD" in m for m in env_log_lines)
|
|
assert not any("SHOULD_NOT_APPEAR" in m for m in logs)
|
|
mock_error.assert_not_called()
|
|
|
|
|
|
def test_sdk_live_attach_performs_attach_detach(monkeypatch):
|
|
"""sdk live-attach calls perform_attach_detach and returns before launching."""
|
|
options = {
|
|
"ROCPROF_ATTACH_PID": "1234",
|
|
"ROCPROF_ATTACH_OUTPUT_GENERATION_SYNC": "1",
|
|
}
|
|
|
|
mock_capture = Mock()
|
|
mock_attach = Mock()
|
|
monkeypatch.setattr(f"{MODULE}.capture_subprocess_output", mock_capture)
|
|
monkeypatch.setattr(f"{MODULE}.perform_attach_detach", mock_attach)
|
|
mock_error = patch_console(monkeypatch, MODULE, "debug", "error")["error"]
|
|
|
|
_make_pc_sampling_profile()._launch(options)
|
|
|
|
mock_attach.assert_called_once()
|
|
new_env, attach_options = mock_attach.call_args.args
|
|
assert new_env["ROCPROF_ATTACH_OUTPUT_GENERATION_SYNC"] == "1"
|
|
assert attach_options["ROCPROF_ATTACH_OUTPUT_GENERATION_SYNC"] == "1"
|
|
mock_capture.assert_not_called()
|
|
mock_error.assert_not_called()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# v3 backend launch
|
|
# ---------------------------------------------------------------------------
|
|
def test_v3_runs_rocprof_command(monkeypatch):
|
|
"""v3 launch runs the rocprof CLI with the supplied flag list."""
|
|
monkeypatch.setattr("utils.utils_common._rocprof_cmd", "rocprof_cli_tool")
|
|
options = ["--kernel-trace", "--", "./myapp", "arg1"]
|
|
|
|
mock_capture = Mock(return_value=(True, "Success"))
|
|
monkeypatch.setattr(f"{MODULE}.capture_subprocess_output", mock_capture)
|
|
mock_error = patch_console(monkeypatch, MODULE, "debug", "error")["error"]
|
|
|
|
_make_pc_sampling_profile(profiler="rocprofv3")._launch(options)
|
|
|
|
assert mock_capture.call_args.args[0] == [
|
|
"rocprof_cli_tool",
|
|
"--kernel-trace",
|
|
"--",
|
|
"./myapp",
|
|
"arg1",
|
|
]
|
|
mock_error.assert_not_called()
|
|
|
|
|
|
def test_v3_subprocess_failure_errors(monkeypatch):
|
|
"""A failed v3 subprocess reports the standard PC sampling failure."""
|
|
monkeypatch.setattr("utils.utils_common._rocprof_cmd", "rocprof_cli_tool")
|
|
mock_capture = Mock(return_value=(False, "Error"))
|
|
monkeypatch.setattr(f"{MODULE}.capture_subprocess_output", mock_capture)
|
|
mock_error = patch_console(monkeypatch, MODULE, "debug", "error")["error"]
|
|
|
|
profiler = _make_pc_sampling_profile(profiler="rocprofv3")
|
|
profiler._launch(["--kernel-trace", "--", "x"])
|
|
|
|
assert mock_error.called
|
|
assert "PC sampling failed." in mock_error.call_args.args[0]
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# misc
|
|
# ---------------------------------------------------------------------------
|
|
def test_is_requested():
|
|
for blocks in (["21"], ["pc_sampling"], ["2", "21"]):
|
|
assert _make_pc_sampling_profile(filter_blocks=blocks).is_requested() is True
|
|
assert _make_pc_sampling_profile(filter_blocks=["2"]).is_requested() is False
|
|
|
|
|
|
def test_run_launches_and_logs(monkeypatch):
|
|
"""run() launches the subprocess and emits the run header and a timing debug."""
|
|
mock_capture = Mock(return_value=(True, ""))
|
|
mock_log = Mock()
|
|
monkeypatch.setattr(f"{MODULE}.capture_subprocess_output", mock_capture)
|
|
monkeypatch.setattr(f"{MODULE}.console_log", mock_log)
|
|
_mocks = patch_console(monkeypatch, MODULE, "debug", "error")
|
|
mock_debug, mock_error = _mocks["debug"], _mocks["error"]
|
|
|
|
_make_pc_sampling_profile().run({"APP_CMD": "my_app"}, prior_run_count=0)
|
|
|
|
assert mock_capture.called
|
|
mock_error.assert_not_called()
|
|
mock_log.assert_any_call("[Run 1/1][PC sampling profile run]")
|
|
assert any(
|
|
call.args and call.args[0] == "profiling" for call in mock_debug.call_args_list
|
|
)
|