|
11 | 11 | IntelPowerGadget, |
12 | 12 | IntelRAPL, |
13 | 13 | is_powergadget_available, |
| 14 | + is_psutil_available, |
14 | 15 | ) |
15 | 16 | from codecarbon.core.units import Energy, Power, Time |
16 | 17 | from codecarbon.core.util import count_physical_cpus |
17 | 18 | from codecarbon.external.hardware import CPU |
18 | 19 | from codecarbon.input import DataSource |
19 | 20 |
|
20 | 21 |
|
| 22 | +class TestCPU(unittest.TestCase): |
| 23 | + @mock.patch("psutil.cpu_times") |
| 24 | + def test_is_psutil_available_with_nice(self, mock_cpu_times): |
| 25 | + # Create a mock with 'nice' attribute |
| 26 | + mock_times = mock.Mock() |
| 27 | + mock_times.nice = 0.1 |
| 28 | + mock_cpu_times.return_value = mock_times |
| 29 | + self.assertTrue(is_psutil_available()) |
| 30 | + |
| 31 | + @mock.patch("psutil.cpu_times") |
| 32 | + def test_is_psutil_available_with_small_nice(self, mock_cpu_times): |
| 33 | + # Test when nice attribute is too small |
| 34 | + mock_times = mock.Mock() |
| 35 | + mock_times.nice = 0.00001 |
| 36 | + mock_cpu_times.return_value = mock_times |
| 37 | + self.assertFalse(is_psutil_available()) |
| 38 | + |
| 39 | + @mock.patch("psutil.cpu_times") |
| 40 | + def test_is_psutil_available_without_nice(self, mock_cpu_times): |
| 41 | + # Create a mock without 'nice' attribute (like Windows) |
| 42 | + mock_times = mock.Mock(spec=[]) # Empty spec = no attributes |
| 43 | + mock_cpu_times.return_value = mock_times |
| 44 | + with mock.patch("psutil.cpu_percent") as mock_cpu_percent: |
| 45 | + self.assertTrue(is_psutil_available()) |
| 46 | + mock_cpu_percent.assert_called_once_with(interval=0.0, percpu=False) |
| 47 | + |
| 48 | + @mock.patch("psutil.cpu_times", side_effect=Exception("Test error")) |
| 49 | + def test_is_psutil_not_available_on_exception(self, mock_cpu_times): |
| 50 | + self.assertFalse(is_psutil_available()) |
| 51 | + |
| 52 | + |
21 | 53 | class TestIntelPowerGadget(unittest.TestCase): |
22 | 54 | @pytest.mark.integ_test |
23 | 55 | def test_intel_power_gadget(self): |
@@ -306,10 +338,37 @@ def test_get_matching_cpu(self): |
306 | 338 | class TestPhysicalCPU(unittest.TestCase): |
307 | 339 | def test_count_physical_cpus_windows(self): |
308 | 340 | with mock.patch("platform.system", return_value="Windows"): |
309 | | - with mock.patch.dict(os.environ, {"NUMBER_OF_PROCESSORS": "4"}): |
| 341 | + |
| 342 | + with mock.patch( |
| 343 | + "subprocess.run", return_value=mock.Mock(returncode=0, stdout="4") |
| 344 | + ): |
310 | 345 | assert count_physical_cpus() == 4 |
311 | 346 |
|
312 | | - with mock.patch.dict(os.environ, {}, clear=True): |
| 347 | + with mock.patch( |
| 348 | + "subprocess.run", return_value=mock.Mock(returncode=0, stdout="") |
| 349 | + ): |
| 350 | + assert count_physical_cpus() == 1 |
| 351 | + |
| 352 | + def test_count_physical_cpus_windows_with_error(self): |
| 353 | + with mock.patch("platform.system", return_value="Windows"): |
| 354 | + # Test CalledProcessError |
| 355 | + with mock.patch( |
| 356 | + "subprocess.run", |
| 357 | + side_effect=subprocess.CalledProcessError(1, "powershell"), |
| 358 | + ): |
| 359 | + assert count_physical_cpus() == 1 |
| 360 | + |
| 361 | + # Test TimeoutExpired |
| 362 | + with mock.patch( |
| 363 | + "subprocess.run", |
| 364 | + side_effect=subprocess.TimeoutExpired("powershell", 10), |
| 365 | + ): |
| 366 | + assert count_physical_cpus() == 1 |
| 367 | + |
| 368 | + # Test ValueError when converting invalid output |
| 369 | + with mock.patch( |
| 370 | + "subprocess.run", return_value=mock.Mock(returncode=0, stdout="invalid") |
| 371 | + ): |
313 | 372 | assert count_physical_cpus() == 1 |
314 | 373 |
|
315 | 374 | def test_count_physical_cpus_linux(self): |
|
0 commit comments