tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_mozpower.py (9505B)


      1 #!/usr/bin/env python
      2 
      3 import subprocess
      4 from unittest import mock
      5 
      6 import mozunit
      7 import pytest
      8 from mozpower import MozPower
      9 from mozpower.mozpower import MissingProcessorInfoError, OsCpuComboMissingError
     10 
     11 
     12 def test_mozpower_android_init_failure():
     13    """Tests that the MozPower object fails when the android
     14    flag is set. Remove this test once android is implemented.
     15    """
     16    with pytest.raises(NotImplementedError):
     17        MozPower(android=True)
     18 
     19 
     20 def test_mozpower_oscpu_combo_missing_error():
     21    """Tests that the error OsCpuComboMissingError is raised
     22    when we can't find a OS, and CPU combination (and, therefore, cannot
     23    find a power measurer).
     24    """
     25    with mock.patch.object(
     26        MozPower, "_get_os", return_value="Not-An-OS"
     27    ) as _, mock.patch.object(
     28        MozPower, "_get_processor_info", return_value="Not-A-Processor"
     29    ) as _:
     30        with pytest.raises(OsCpuComboMissingError):
     31            MozPower()
     32 
     33 
     34 def test_mozpower_processor_info_missing_error():
     35    """Tests that the error MissingProcessorInfoError is raised
     36    when failures occur during processor information parsing.
     37    """
     38    builtins_name = "builtins"
     39 
     40    def os_side_effect_true(*args, **kwargs):
     41        """Used as a passing side effect for os.path.exists calls."""
     42        return True
     43 
     44    def os_side_effect_false(*args, **kwargs):
     45        """Used as a failing side effect for os.path.exists calls."""
     46        return False
     47 
     48    def subprocess_side_effect_fail(*args, **kwargs):
     49        """Used to mock a failure in subprocess.check_output calls."""
     50        raise subprocess.CalledProcessError(1, "Testing failure")
     51 
     52    # Test failures in macos processor information parsing
     53    with mock.patch.object(MozPower, "_get_os", return_value="Darwin") as _:
     54        with mock.patch("os.path.exists") as os_mock:
     55            os_mock.side_effect = os_side_effect_false
     56 
     57            # Check that we fail properly if the processor
     58            # information file doesn't exist.
     59            with pytest.raises(MissingProcessorInfoError):
     60                MozPower()
     61 
     62            # Check that we fail properly when an error occurs
     63            # in the subprocess call.
     64            os_mock.side_effect = os_side_effect_true
     65            with mock.patch("subprocess.check_output") as subprocess_mock:
     66                subprocess_mock.side_effect = subprocess_side_effect_fail
     67                with pytest.raises(MissingProcessorInfoError):
     68                    MozPower()
     69 
     70    # Test failures in linux processor information parsing
     71    with mock.patch.object(MozPower, "_get_os", return_value="Linux") as _:
     72        with mock.patch("os.path.exists") as os_mock:
     73            os_mock.side_effect = os_side_effect_false
     74 
     75            # Check that we fail properly if the processor
     76            # information file doesn't exist.
     77            with pytest.raises(MissingProcessorInfoError):
     78                MozPower()
     79 
     80            # Check that we fail properly when the model cannot be found
     81            # with by searching for 'model name'.
     82            os_mock.side_effect = os_side_effect_true
     83            with mock.patch(
     84                "%s.open" % builtins_name, mock.mock_open(read_data="")
     85            ) as _:
     86                with pytest.raises(MissingProcessorInfoError):
     87                    MozPower()
     88 
     89 
     90 def test_mozpower_oscpu_combo(mozpower_obj):
     91    """Tests that the correct class is instantiated for a given
     92    OS and CPU combination (MacIntelPower in this case).
     93    """
     94    assert mozpower_obj.measurer.__class__.__name__ == "MacIntelPower"
     95    assert (
     96        mozpower_obj.measurer._os == "darwin" and mozpower_obj.measurer._cpu == "intel"
     97    )
     98 
     99 
    100 def test_mozpower_measuring(mozpower_obj):
    101    """Tests that measurers are properly called with each method."""
    102    with mock.patch(
    103        "mozpower.macintelpower.MacIntelPower.initialize_power_measurements"
    104    ) as _, mock.patch(
    105        "mozpower.macintelpower.MacIntelPower.finalize_power_measurements"
    106    ) as _, mock.patch("mozpower.macintelpower.MacIntelPower.get_perfherder_data") as _:
    107        mozpower_obj.initialize_power_measurements()
    108        mozpower_obj.measurer.initialize_power_measurements.assert_called()
    109 
    110        mozpower_obj.finalize_power_measurements()
    111        mozpower_obj.measurer.finalize_power_measurements.assert_called()
    112 
    113        mozpower_obj.get_perfherder_data()
    114        mozpower_obj.measurer.get_perfherder_data.assert_called()
    115 
    116 
    117 def test_mozpower_measuring_with_no_measurer(mozpower_obj):
    118    """Tests that no errors occur when the measurer is None, and the
    119    initialize, finalize, and get_perfherder_data functions are called.
    120    """
    121    with mock.patch(
    122        "mozpower.macintelpower.MacIntelPower.initialize_power_measurements"
    123    ) as _, mock.patch(
    124        "mozpower.macintelpower.MacIntelPower.finalize_power_measurements"
    125    ) as _, mock.patch("mozpower.macintelpower.MacIntelPower.get_perfherder_data") as _:
    126        measurer = mozpower_obj.measurer
    127        mozpower_obj.measurer = None
    128 
    129        mozpower_obj.initialize_power_measurements()
    130        assert not measurer.initialize_power_measurements.called
    131 
    132        mozpower_obj.finalize_power_measurements()
    133        assert not measurer.finalize_power_measurements.called
    134 
    135        mozpower_obj.get_perfherder_data()
    136        assert not measurer.get_perfherder_data.called
    137 
    138        mozpower_obj.get_full_perfherder_data("mozpower")
    139        assert not measurer.get_perfherder_data.called
    140 
    141 
    142 def test_mozpower_get_full_perfherder_data(mozpower_obj):
    143    """Tests that the full perfherder data blob is properly
    144    produced given a partial perfherder data blob with correct
    145    entries.
    146    """
    147    partial_perfherder = {
    148        "utilization": {
    149            "type": "power",
    150            "test": "mozpower",
    151            "unit": "%",
    152            "values": {"cpu": 50, "gpu": 0},
    153        },
    154        "power-usage": {
    155            "type": "power",
    156            "test": "mozpower",
    157            "unit": "mWh",
    158            "values": {"cpu": 2.0, "dram": 0.1, "gpu": 4.0},
    159        },
    160        "frequency-cpu": {
    161            "type": "power",
    162            "test": "mozpower",
    163            "unit": "MHz",
    164            "values": {
    165                "cpu-favg": 2.0,
    166                "cpu-fmax": 5.0,
    167                "cpu-fmin": 0.0,
    168            },
    169        },
    170        "frequency-gpu": {
    171            "type": "power",
    172            "test": "mozpower",
    173            "unit": "MHz",
    174            "values": {"gpu-favg": 3.0, "gpu-fmax": 6.0, "gpu-fmin": 0.0},
    175        },
    176    }
    177    utilization_vals = [0, 50]
    178    power_usage_vals = [2.0, 0.1, 4.0]
    179    frequency_cpu_vals = [2.0, 5.0, 0.0]
    180    frequency_gpu_vals = [3.0, 6.0, 0.0]
    181 
    182    with mock.patch("mozpower.macintelpower.MacIntelPower.get_perfherder_data") as gpd:
    183        gpd.return_value = partial_perfherder
    184 
    185        full_perfherder = mozpower_obj.get_full_perfherder_data("mozpower")
    186        assert full_perfherder["framework"]["name"] == "mozpower"
    187        assert len(full_perfherder["suites"]) == 4
    188 
    189        # Check that each of the two suites were created correctly.
    190        suites = full_perfherder["suites"]
    191        for suite in suites:
    192            assert "subtests" in suite
    193 
    194            assert suite["type"] == "power"
    195            assert suite["alertThreshold"] == 2.0
    196            assert suite["lowerIsBetter"]
    197 
    198            all_vals = []
    199            for subtest in suite["subtests"]:
    200                assert "value" in subtest
    201 
    202                # Check that the subtest names were created correctly
    203                if "utilization" in suite["name"]:
    204                    assert "utilization" in subtest["name"]
    205                elif "power-usage" in suite["name"]:
    206                    assert "power-usage" in subtest["name"]
    207                elif "frequency-cpu" in suite["name"]:
    208                    assert "frequency-cpu" in subtest["name"]
    209                elif "frequency-gpu" in suite["name"]:
    210                    assert "frequency-gpu" in subtest["name"]
    211                else:
    212                    assert False, "Unknown subtest name %s" % subtest["name"]
    213 
    214                all_vals.append(subtest["value"])
    215 
    216            if "utilization" in suite["name"]:
    217                assert len(all_vals) == 2
    218                assert suite["unit"] == "%"
    219                assert suite["name"] == "mozpower-utilization"
    220                assert not list(set(all_vals) - set(utilization_vals))
    221                assert suite["value"] == float(25)
    222            elif "power-usage" in suite["name"]:
    223                assert len(all_vals) == 3
    224                assert suite["unit"] == "mWh"
    225                assert suite["name"] == "mozpower-power-usage"
    226                assert not list(set(all_vals) - set(power_usage_vals))
    227                assert suite["value"] == 6.1
    228            elif "frequency-cpu" in suite["name"]:
    229                assert len(all_vals) == 3
    230                assert suite["unit"] == "MHz"
    231                assert suite["name"] == "mozpower-frequency-cpu"
    232                assert not list(set(all_vals) - set(frequency_cpu_vals))
    233                assert suite["value"] == 2.0
    234            elif "frequency-gpu" in suite["name"]:
    235                assert len(all_vals) == 3
    236                assert suite["unit"] == "MHz"
    237                assert suite["name"] == "mozpower-frequency-gpu"
    238                assert not list(set(all_vals) - set(frequency_gpu_vals))
    239                assert suite["value"] == 3.0
    240            else:
    241                assert False, "Unknown suite name %s" % suite["name"]
    242 
    243 
    244 if __name__ == "__main__":
    245    mozunit.main()