from pathlib import Path from unittest import mock from unittest.mock import mock_open, patch import pytest from speccpu import SPEC, check_bench_dir, find_build from speccpu.x264 import recompile_mc_src class TestFindBuild: def test_find_build_success(self, tmpdir): # Create a mock directory structure with a build directory build_parent = Path(tmpdir) build_dir = build_parent / "build_2023" build_dir.mkdir() # Test that find_build correctly identifies the build directory found_dir = find_build(build_parent) assert found_dir == build_dir def test_find_build_multiple_dirs(self, tmpdir): # Create multiple build directories build_parent = Path(tmpdir) build_dir1 = build_parent / "build_2022" build_dir2 = build_parent / "build_2023" build_dir1.mkdir() build_dir2.mkdir() # Should find the alphabetically first one found_dir = find_build(build_parent) assert found_dir == build_dir1 def test_find_build_no_dir(self, tmpdir): # Test the error case when no build directory exists build_parent = Path(tmpdir) with pytest.raises(RuntimeError): find_build(build_parent) class TestSPEC: def test_init(self): spec_dir = Path("/path/to/spec") spec = SPEC(spec_dir) assert spec.dir == spec_dir def test_config_dir(self): spec_dir = Path("/path/to/spec") spec = SPEC(spec_dir) assert spec.config_dir == spec_dir / "config" def test_env(self): spec_dir = Path("/path/to/spec") spec = SPEC(spec_dir) with mock.patch("speccpu.create_spec_env") as mock_create_env: spec.env() mock_create_env.assert_called_once_with(spec_dir) def test_mkcmd_runcpu_default(self): spec = SPEC(Path("/path/to/spec")) cmd = spec.mkcmd_runcpu("myconfig", ["benchmark1", "benchmark2"]) assert cmd == [ "runcpu", "--setprocgroup", "-i", "ref", "-c", "myconfig", "benchmark1", "benchmark2", ] def test_mkcmd_runcpu_no_procgroup(self): spec = SPEC(Path("/path/to/spec")) cmd = spec.mkcmd_runcpu("myconfig", ["benchmark1"], setprocgroup=False) assert "--setprocgroup" not in cmd def test_mkcmd_runcpu_with_output_dir(self): spec = SPEC(Path("/path/to/spec")) output_dir = Path("/output/dir") cmd = spec.mkcmd_runcpu("myconfig", ["benchmark1"], output_root=output_dir) assert "--output_root" in cmd assert str(output_dir) in cmd def test_mkcmd_runcpu_build_type_default(self): """Test that mkcmd_runcpu doesn't add build flags with default build type.""" spec = SPEC(Path("/path/to/spec")) cmd = spec.mkcmd_runcpu( "myconfig", ["benchmark1"], build_type=SPEC.BuildType.Default ) assert "--nobuild" not in cmd assert "--rebuild" not in cmd def test_mkcmd_runcpu_build_type_nobuild(self): """Test that mkcmd_runcpu adds --nobuild flag with Nobuild build type.""" spec = SPEC(Path("/path/to/spec")) cmd = spec.mkcmd_runcpu( "myconfig", ["benchmark1"], build_type=SPEC.BuildType.Nobuild ) assert "--nobuild" in cmd assert "--rebuild" not in cmd def test_mkcmd_runcpu_build_type_rebuild(self): """Test that mkcmd_runcpu adds --rebuild flag with Rebuild build type.""" spec = SPEC(Path("/path/to/spec")) cmd = spec.mkcmd_runcpu( "myconfig", ["benchmark1"], build_type=SPEC.BuildType.Rebuild ) assert "--rebuild" in cmd assert "--nobuild" not in cmd class TestCheckBenchDir: def test_valid_bench_dir(self, tmpdir): """Test that check_bench_dir returns True for a valid benchmark directory.""" bench_dir = Path(tmpdir) # Create the required subdirectories (bench_dir / "build").mkdir() (bench_dir / "exe").mkdir() (bench_dir / "run").mkdir() # Add some extra files/directories to make sure they don't affect the result (bench_dir / "other_dir").mkdir() (bench_dir / "file.txt").write_text("test") assert check_bench_dir(bench_dir) is True def test_invalid_bench_dir_missing_build(self, tmpdir): """Test that check_bench_dir returns False when 'build' directory is missing.""" bench_dir = Path(tmpdir) # Create only exe and run directories (bench_dir / "exe").mkdir() (bench_dir / "run").mkdir() assert check_bench_dir(bench_dir) is False def test_invalid_bench_dir_missing_exe(self, tmpdir): """Test that check_bench_dir returns False when 'exe' directory is missing.""" bench_dir = Path(tmpdir) # Create only build and run directories (bench_dir / "build").mkdir() (bench_dir / "run").mkdir() assert check_bench_dir(bench_dir) is False def test_invalid_bench_dir_missing_run(self, tmpdir): """Test that check_bench_dir returns False when 'run' directory is missing.""" bench_dir = Path(tmpdir) # Create only build and exe directories (bench_dir / "build").mkdir() (bench_dir / "exe").mkdir() assert check_bench_dir(bench_dir) is False def test_empty_dir(self, tmpdir): """Test that check_bench_dir returns False for an empty directory.""" bench_dir = Path(tmpdir) assert check_bench_dir(bench_dir) is False def test_invalid_dir_case_sensitive(self, tmpdir): """Test that check_bench_dir is case-sensitive.""" bench_dir = Path(tmpdir) # Create directories with different case (bench_dir / "Build").mkdir() (bench_dir / "EXE").mkdir() (bench_dir / "RUN").mkdir() assert check_bench_dir(bench_dir) is False @pytest.fixture def mock_build_path(): return Path("/mock/build/path") @pytest.fixture def mock_spec_env(): return {"CC": "gcc", "CFLAGS": "-O2"} @pytest.fixture def mock_mc_path(mock_build_path): return Path("/mock/build/path/x264_src/common/mc.c") def test_recompile_mc_src(mock_build_path, mock_spec_env, mock_mc_path): test_mc_src = "test source code" with ( patch("speccpu.x264.get_mc_path", return_value=mock_mc_path) as mock_get_path, patch("builtins.open", mock_open()) as mock_file, patch("speccpu.x264.recompile_mc") as mock_recompile, patch.object(Path, "exists", return_value=True), patch.object(Path, "is_file", return_value=True), ): # Configure recompile_mc mock to return a path mock_exe_path = Path("/mock/build/path/x264_s") mock_recompile.return_value = mock_exe_path # Call the function under test result = recompile_mc_src(test_mc_src, mock_build_path, mock_spec_env) # Verify the function behavior mock_get_path.assert_called_once_with(mock_build_path) mock_file.assert_called_once_with(mock_mc_path, "w") mock_file().write.assert_called_once_with(test_mc_src) mock_recompile.assert_called_once_with( mock_mc_path, mock_build_path, mock_spec_env ) def test_recompile_mc_src_file_not_exists(mock_build_path, mock_spec_env, mock_mc_path): test_mc_src = "test source code" with ( patch("speccpu.x264.get_mc_path", return_value=mock_mc_path), patch.object(Path, "exists", return_value=False), ): # Test that the function raises an assertion error when file doesn't exist with pytest.raises(AssertionError): recompile_mc_src(test_mc_src, mock_build_path, mock_spec_env) def test_recompile_mc_src_exe_not_exists(mock_build_path, mock_spec_env, mock_mc_path): test_mc_src = "test source code" with ( patch("speccpu.x264.get_mc_path", return_value=mock_mc_path) as mock_get_path, patch("builtins.open", mock_open()) as mock_file, patch("speccpu.x264.recompile_mc") as mock_recompile, patch.object(Path, "exists", side_effect=[True, False]), patch.object(Path, "is_file", return_value=True), ): # Configure recompile_mc mock to return a path mock_exe_path = Path("/mock/build/path/x264_s") mock_recompile.return_value = mock_exe_path # Test that the function raises an assertion error when exe doesn't exist with pytest.raises(AssertionError): recompile_mc_src(test_mc_src, mock_build_path, mock_spec_env) def test_recompile_mc_src_exe_not_file(mock_build_path, mock_spec_env, mock_mc_path): test_mc_src = "test source code" with ( patch("speccpu.x264.get_mc_path", return_value=mock_mc_path) as mock_get_path, patch("builtins.open", mock_open()) as mock_file, patch("speccpu.x264.recompile_mc") as mock_recompile, patch.object(Path, "exists", return_value=True), patch.object(Path, "is_file", return_value=False), ): # Configure recompile_mc mock to return a path mock_exe_path = Path("/mock/build/path/x264_s") mock_recompile.return_value = mock_exe_path # Test that the function raises an assertion error when exe is not a file with pytest.raises(AssertionError): recompile_mc_src(test_mc_src, mock_build_path, mock_spec_env)