diff options
Diffstat (limited to 'tests/unit/utils')
-rw-r--r-- | tests/unit/utils/test_qtutils.py | 6 | ||||
-rw-r--r-- | tests/unit/utils/test_version.py | 91 | ||||
-rw-r--r-- | tests/unit/utils/usertypes/test_timer.py | 63 |
3 files changed, 145 insertions, 15 deletions
diff --git a/tests/unit/utils/test_qtutils.py b/tests/unit/utils/test_qtutils.py index c7af3162c..0a3afa416 100644 --- a/tests/unit/utils/test_qtutils.py +++ b/tests/unit/utils/test_qtutils.py @@ -758,8 +758,10 @@ class TestPyQIODevice: # pylint: enable=no-member,useless-suppression else: pytest.skip("Needs os.SEEK_HOLE or os.SEEK_DATA available.") + pyqiodev.open(QIODevice.OpenModeFlag.ReadOnly) with pytest.raises(io.UnsupportedOperation): + # pylint: disable=possibly-used-before-assignment pyqiodev.seek(0, whence) @pytest.mark.flaky @@ -1116,13 +1118,13 @@ class TestQObjRepr: assert qtutils.qobj_repr(obj) == expected def test_class_name(self): - obj = QTimer() + obj = QTimer() # misc: ignore hidden = sip.cast(obj, QObject) expected = f"<{self._py_repr(hidden)}, className='QTimer'>" assert qtutils.qobj_repr(hidden) == expected def test_both(self): - obj = QTimer() + obj = QTimer() # misc: ignore obj.setObjectName("Pomodoro") hidden = sip.cast(obj, QObject) expected = f"<{self._py_repr(hidden)}, objectName='Pomodoro', className='QTimer'>" diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py index 38134b40e..5d2863100 100644 --- a/tests/unit/utils/test_version.py +++ b/tests/unit/utils/test_version.py @@ -899,21 +899,45 @@ class TestWebEngineVersions: webengine=utils.VersionNumber(5, 15, 2), chromium=None, source='UA'), - "QtWebEngine 5.15.2", + ( + "QtWebEngine 5.15.2\n" + " (source: UA)" + ), ), ( version.WebEngineVersions( webengine=utils.VersionNumber(5, 15, 2), chromium='87.0.4280.144', source='UA'), - "QtWebEngine 5.15.2, based on Chromium 87.0.4280.144", + ( + "QtWebEngine 5.15.2\n" + " based on Chromium 87.0.4280.144\n" + " (source: UA)" + ), ), ( version.WebEngineVersions( webengine=utils.VersionNumber(5, 15, 2), chromium='87.0.4280.144', source='faked'), - "QtWebEngine 5.15.2, based on Chromium 87.0.4280.144 (from faked)", + ( + "QtWebEngine 5.15.2\n" + " based on Chromium 87.0.4280.144\n" + " (source: faked)" + ), + ), + ( + version.WebEngineVersions( + webengine=utils.VersionNumber(5, 15, 2), + chromium='87.0.4280.144', + chromium_security='9000.1', + source='faked'), + ( + "QtWebEngine 5.15.2\n" + " based on Chromium 87.0.4280.144\n" + " with security patches up to 9000.1 (plus any distribution patches)\n" + " (source: faked)" + ), ), ]) def test_str(self, version, expected): @@ -950,6 +974,7 @@ class TestWebEngineVersions: expected = version.WebEngineVersions( webengine=utils.VersionNumber(5, 15, 2), chromium='83.0.4103.122', + chromium_security='86.0.4240.183', source='UA', ) assert version.WebEngineVersions.from_ua(ua) == expected @@ -959,21 +984,27 @@ class TestWebEngineVersions: expected = version.WebEngineVersions( webengine=utils.VersionNumber(5, 15, 2), chromium='83.0.4103.122', + chromium_security='86.0.4240.183', source='ELF', ) assert version.WebEngineVersions.from_elf(elf_version) == expected - @pytest.mark.parametrize('pyqt_version, chromium_version', [ - ('5.15.2', '83.0.4103.122'), - ('5.15.3', '87.0.4280.144'), - ('5.15.4', '87.0.4280.144'), - ('5.15.5', '87.0.4280.144'), - ('6.2.0', '90.0.4430.228'), - ('6.3.0', '94.0.4606.126'), + @pytest.mark.parametrize('pyqt_version, chromium_version, security_version', [ + ('5.15.2', '83.0.4103.122', '86.0.4240.183'), + ('5.15.3', '87.0.4280.144', '88.0.4324.150'), + ('5.15.4', '87.0.4280.144', None), + ('5.15.5', '87.0.4280.144', None), + ('5.15.6', '87.0.4280.144', None), + ('5.15.7', '87.0.4280.144', '94.0.4606.61'), + ('6.2.0', '90.0.4430.228', '93.0.4577.63'), + ('6.2.99', '90.0.4430.228', None), + ('6.3.0', '94.0.4606.126', '99.0.4844.84'), + ('6.99.0', None, None), ]) - def test_from_pyqt(self, freezer, pyqt_version, chromium_version): - if freezer and pyqt_version in ['5.15.3', '5.15.4', '5.15.5']: + def test_from_pyqt(self, freezer, pyqt_version, chromium_version, security_version): + if freezer and utils.VersionNumber(5, 15, 3) <= utils.VersionNumber.parse(pyqt_version) < utils.VersionNumber(6): chromium_version = '83.0.4103.122' + security_version = '86.0.4240.183' expected_pyqt_version = '5.15.2' else: expected_pyqt_version = pyqt_version @@ -981,6 +1012,7 @@ class TestWebEngineVersions: expected = version.WebEngineVersions( webengine=utils.VersionNumber.parse(expected_pyqt_version), chromium=chromium_version, + chromium_security=security_version, source='PyQt', ) assert version.WebEngineVersions.from_pyqt(pyqt_version) == expected @@ -1024,6 +1056,39 @@ class TestWebEngineVersions: assert inferred == real + def test_real_chromium_security_version(self, qapp): + """Check the API for reading the chromium security patch version.""" + try: + from qutebrowser.qt.webenginecore import ( + qWebEngineChromiumVersion, + qWebEngineChromiumSecurityPatchVersion, + ) + except ImportError: + pytest.skip("Requires QtWebEngine 6.3+") + + base = utils.VersionNumber.parse(qWebEngineChromiumVersion()) + security = utils.VersionNumber.parse(qWebEngineChromiumSecurityPatchVersion()) + assert security >= base + + def test_chromium_security_version_dict(self, qapp): + """Check if we infer the QtWebEngine security version properly. + + Note this test mostly tests that our overview in version.py (also + intended for human readers) is accurate. The code we call here is never + going to be called in real-life situations, as the API is available. + """ + try: + from qutebrowser.qt.webenginecore import ( + qWebEngineVersion, + qWebEngineChromiumSecurityPatchVersion, + ) + except ImportError: + pytest.skip("Requires QtWebEngine 6.3+") + + inferred = version.WebEngineVersions.from_webengine( + qWebEngineVersion(), source="API") + assert inferred.chromium_security == qWebEngineChromiumSecurityPatchVersion() + class FakeQSslSocket: @@ -1294,7 +1359,7 @@ def test_version_info(params, stubs, monkeypatch, config_stub): else: monkeypatch.delattr(version, 'qtutils.qWebKitVersion', raising=False) patches['objects.backend'] = usertypes.Backend.QtWebEngine - substitutions['backend'] = 'QtWebEngine 1.2.3 (from faked)' + substitutions['backend'] = 'QtWebEngine 1.2.3\n (source: faked)' if params.known_distribution: patches['distribution'] = lambda: version.DistributionInfo( diff --git a/tests/unit/utils/usertypes/test_timer.py b/tests/unit/utils/usertypes/test_timer.py index c02f160b6..6aabc8c04 100644 --- a/tests/unit/utils/usertypes/test_timer.py +++ b/tests/unit/utils/usertypes/test_timer.py @@ -4,6 +4,9 @@ """Tests for Timer.""" +import logging +import fnmatch + import pytest from qutebrowser.qt.core import QObject @@ -65,3 +68,63 @@ def test_timeout_set_interval(qtbot): with qtbot.wait_signal(t.timeout, timeout=3000): t.setInterval(200) t.start() + + +@pytest.mark.parametrize( + "elapsed_ms, expected", + [ + (0, False), + (1, False), + (600, True), + (999, True), + (1000, True), + ], +) +def test_early_timeout_check(qtbot, mocker, elapsed_ms, expected): + time_mock = mocker.patch("time.monotonic", autospec=True) + + t = usertypes.Timer() + t.setInterval(1000) # anything long enough to not actually fire + time_mock.return_value = 0 # assigned to _start_time in start() + t.start() + time_mock.return_value = elapsed_ms / 1000 # used for `elapsed` + + assert t.check_timeout_validity() is expected + + t.stop() + + +def test_early_timeout_handler(qtbot, mocker, caplog): + time_mock = mocker.patch("time.monotonic", autospec=True) + + t = usertypes.Timer(name="t") + t.setInterval(3) + t.setSingleShot(True) + time_mock.return_value = 0 + with caplog.at_level(logging.WARNING): + with qtbot.wait_signal(t.timeout, timeout=10): + t.start() + time_mock.return_value = 1 / 1000 + + assert len(caplog.messages) == 1 + assert fnmatch.fnmatch( + caplog.messages[-1], + "Timer t (id *) triggered too early: interval 3 but only 0.001s passed", + ) + + +def test_early_manual_fire(qtbot, mocker, caplog): + """Same as above but start() never gets called.""" + time_mock = mocker.patch("time.monotonic", autospec=True) + + t = usertypes.Timer(name="t") + t.setInterval(3) + t.setSingleShot(True) + time_mock.return_value = 0 + with caplog.at_level(logging.WARNING): + with qtbot.wait_signal(t.timeout, timeout=10): + t.timeout.emit() + time_mock.return_value = 1 / 1000 + + assert len(caplog.messages) == 0 + assert t.check_timeout_validity() |