Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

#!/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()