summaryrefslogtreecommitdiffstats
path: root/testing/mozbase/mozpower/tests/test_mozpower.py
diff options
context:
space:
mode:
Diffstat (limited to 'testing/mozbase/mozpower/tests/test_mozpower.py')
-rw-r--r--testing/mozbase/mozpower/tests/test_mozpower.py255
1 files changed, 255 insertions, 0 deletions
diff --git a/testing/mozbase/mozpower/tests/test_mozpower.py b/testing/mozbase/mozpower/tests/test_mozpower.py
new file mode 100644
index 0000000000..fd513e836b
--- /dev/null
+++ b/testing/mozbase/mozpower/tests/test_mozpower.py
@@ -0,0 +1,255 @@
+#!/usr/bin/env python
+
+import subprocess
+import sys
+from unittest import mock
+
+import mozunit
+import pytest
+from mozpower import MozPower
+from mozpower.mozpower import MissingProcessorInfoError, OsCpuComboMissingError
+
+
+def test_mozpower_android_init_failure():
+ """Tests that the MozPower object fails when the android
+ flag is set. Remove this test once android is implemented.
+ """
+ with pytest.raises(NotImplementedError):
+ MozPower(android=True)
+
+
+def test_mozpower_oscpu_combo_missing_error():
+ """Tests that the error OsCpuComboMissingError is raised
+ when we can't find a OS, and CPU combination (and, therefore, cannot
+ find a power measurer).
+ """
+ with mock.patch.object(
+ MozPower, "_get_os", return_value="Not-An-OS"
+ ) as _, mock.patch.object(
+ MozPower, "_get_processor_info", return_value="Not-A-Processor"
+ ) as _:
+ with pytest.raises(OsCpuComboMissingError):
+ MozPower()
+
+
+def test_mozpower_processor_info_missing_error():
+ """Tests that the error MissingProcessorInfoError is raised
+ when failures occur during processor information parsing.
+ """
+ # The builtins module name differs between python 2 and 3
+ builtins_name = "__builtin__"
+ if sys.version_info[0] == 3:
+ builtins_name = "builtins"
+
+ def os_side_effect_true(*args, **kwargs):
+ """Used as a passing side effect for os.path.exists calls."""
+ return True
+
+ def os_side_effect_false(*args, **kwargs):
+ """Used as a failing side effect for os.path.exists calls."""
+ return False
+
+ def subprocess_side_effect_fail(*args, **kwargs):
+ """Used to mock a failure in subprocess.check_output calls."""
+ raise subprocess.CalledProcessError(1, "Testing failure")
+
+ # Test failures in macos processor information parsing
+ with mock.patch.object(MozPower, "_get_os", return_value="Darwin") as _:
+
+ with mock.patch("os.path.exists") as os_mock:
+ os_mock.side_effect = os_side_effect_false
+
+ # Check that we fail properly if the processor
+ # information file doesn't exist.
+ with pytest.raises(MissingProcessorInfoError):
+ MozPower()
+
+ # Check that we fail properly when an error occurs
+ # in the subprocess call.
+ os_mock.side_effect = os_side_effect_true
+ with mock.patch("subprocess.check_output") as subprocess_mock:
+ subprocess_mock.side_effect = subprocess_side_effect_fail
+ with pytest.raises(MissingProcessorInfoError):
+ MozPower()
+
+ # Test failures in linux processor information parsing
+ with mock.patch.object(MozPower, "_get_os", return_value="Linux") as _:
+
+ with mock.patch("os.path.exists") as os_mock:
+ os_mock.side_effect = os_side_effect_false
+
+ # Check that we fail properly if the processor
+ # information file doesn't exist.
+ with pytest.raises(MissingProcessorInfoError):
+ MozPower()
+
+ # Check that we fail properly when the model cannot be found
+ # with by searching for 'model name'.
+ os_mock.side_effect = os_side_effect_true
+ with mock.patch(
+ "%s.open" % builtins_name, mock.mock_open(read_data="")
+ ) as _:
+ with pytest.raises(MissingProcessorInfoError):
+ MozPower()
+
+
+def test_mozpower_oscpu_combo(mozpower_obj):
+ """Tests that the correct class is instantiated for a given
+ OS and CPU combination (MacIntelPower in this case).
+ """
+ assert mozpower_obj.measurer.__class__.__name__ == "MacIntelPower"
+ assert (
+ mozpower_obj.measurer._os == "darwin" and mozpower_obj.measurer._cpu == "intel"
+ )
+
+
+def test_mozpower_measuring(mozpower_obj):
+ """Tests that measurers are properly called with each method."""
+ with mock.patch(
+ "mozpower.macintelpower.MacIntelPower.initialize_power_measurements"
+ ) as _, mock.patch(
+ "mozpower.macintelpower.MacIntelPower.finalize_power_measurements"
+ ) as _, mock.patch(
+ "mozpower.macintelpower.MacIntelPower.get_perfherder_data"
+ ) as _:
+ mozpower_obj.initialize_power_measurements()
+ mozpower_obj.measurer.initialize_power_measurements.assert_called()
+
+ mozpower_obj.finalize_power_measurements()
+ mozpower_obj.measurer.finalize_power_measurements.assert_called()
+
+ mozpower_obj.get_perfherder_data()
+ mozpower_obj.measurer.get_perfherder_data.assert_called()
+
+
+def test_mozpower_measuring_with_no_measurer(mozpower_obj):
+ """Tests that no errors occur when the measurer is None, and the
+ initialize, finalize, and get_perfherder_data functions are called.
+ """
+ with mock.patch(
+ "mozpower.macintelpower.MacIntelPower.initialize_power_measurements"
+ ) as _, mock.patch(
+ "mozpower.macintelpower.MacIntelPower.finalize_power_measurements"
+ ) as _, mock.patch(
+ "mozpower.macintelpower.MacIntelPower.get_perfherder_data"
+ ) as _:
+ measurer = mozpower_obj.measurer
+ mozpower_obj.measurer = None
+
+ mozpower_obj.initialize_power_measurements()
+ assert not measurer.initialize_power_measurements.called
+
+ mozpower_obj.finalize_power_measurements()
+ assert not measurer.finalize_power_measurements.called
+
+ mozpower_obj.get_perfherder_data()
+ assert not measurer.get_perfherder_data.called
+
+ mozpower_obj.get_full_perfherder_data("mozpower")
+ assert not measurer.get_perfherder_data.called
+
+
+def test_mozpower_get_full_perfherder_data(mozpower_obj):
+ """Tests that the full perfherder data blob is properly
+ produced given a partial perfherder data blob with correct
+ entries.
+ """
+ partial_perfherder = {
+ "utilization": {
+ "type": "power",
+ "test": "mozpower",
+ "unit": "%",
+ "values": {"cpu": 50, "gpu": 0},
+ },
+ "power-usage": {
+ "type": "power",
+ "test": "mozpower",
+ "unit": "mWh",
+ "values": {"cpu": 2.0, "dram": 0.1, "gpu": 4.0},
+ },
+ "frequency-cpu": {
+ "type": "power",
+ "test": "mozpower",
+ "unit": "MHz",
+ "values": {
+ "cpu-favg": 2.0,
+ "cpu-fmax": 5.0,
+ "cpu-fmin": 0.0,
+ },
+ },
+ "frequency-gpu": {
+ "type": "power",
+ "test": "mozpower",
+ "unit": "MHz",
+ "values": {"gpu-favg": 3.0, "gpu-fmax": 6.0, "gpu-fmin": 0.0},
+ },
+ }
+ utilization_vals = [0, 50]
+ power_usage_vals = [2.0, 0.1, 4.0]
+ frequency_cpu_vals = [2.0, 5.0, 0.0]
+ frequency_gpu_vals = [3.0, 6.0, 0.0]
+
+ with mock.patch("mozpower.macintelpower.MacIntelPower.get_perfherder_data") as gpd:
+ gpd.return_value = partial_perfherder
+
+ full_perfherder = mozpower_obj.get_full_perfherder_data("mozpower")
+ assert full_perfherder["framework"]["name"] == "mozpower"
+ assert len(full_perfherder["suites"]) == 4
+
+ # Check that each of the two suites were created correctly.
+ suites = full_perfherder["suites"]
+ for suite in suites:
+ assert "subtests" in suite
+
+ assert suite["type"] == "power"
+ assert suite["alertThreshold"] == 2.0
+ assert suite["lowerIsBetter"]
+
+ all_vals = []
+ for subtest in suite["subtests"]:
+ assert "value" in subtest
+
+ # Check that the subtest names were created correctly
+ if "utilization" in suite["name"]:
+ assert "utilization" in subtest["name"]
+ elif "power-usage" in suite["name"]:
+ assert "power-usage" in subtest["name"]
+ elif "frequency-cpu" in suite["name"]:
+ assert "frequency-cpu" in subtest["name"]
+ elif "frequency-gpu" in suite["name"]:
+ assert "frequency-gpu" in subtest["name"]
+ else:
+ assert False, "Unknown subtest name %s" % subtest["name"]
+
+ all_vals.append(subtest["value"])
+
+ if "utilization" in suite["name"]:
+ assert len(all_vals) == 2
+ assert suite["unit"] == "%"
+ assert suite["name"] == "mozpower-utilization"
+ assert not list(set(all_vals) - set(utilization_vals))
+ assert suite["value"] == float(25)
+ elif "power-usage" in suite["name"]:
+ assert len(all_vals) == 3
+ assert suite["unit"] == "mWh"
+ assert suite["name"] == "mozpower-power-usage"
+ assert not list(set(all_vals) - set(power_usage_vals))
+ assert suite["value"] == float(6.1)
+ elif "frequency-cpu" in suite["name"]:
+ assert len(all_vals) == 3
+ assert suite["unit"] == "MHz"
+ assert suite["name"] == "mozpower-frequency-cpu"
+ assert not list(set(all_vals) - set(frequency_cpu_vals))
+ assert suite["value"] == float(2.0)
+ elif "frequency-gpu" in suite["name"]:
+ assert len(all_vals) == 3
+ assert suite["unit"] == "MHz"
+ assert suite["name"] == "mozpower-frequency-gpu"
+ assert not list(set(all_vals) - set(frequency_gpu_vals))
+ assert suite["value"] == float(3.0)
+ else:
+ assert False, "Unknown suite name %s" % suite["name"]
+
+
+if __name__ == "__main__":
+ mozunit.main()