diff options
Diffstat (limited to 'tests/unit/utils/test_utils.py')
-rw-r--r-- | tests/unit/utils/test_utils.py | 222 |
1 files changed, 104 insertions, 118 deletions
diff --git a/tests/unit/utils/test_utils.py b/tests/unit/utils/test_utils.py index 4cf60943c..b43638cb3 100644 --- a/tests/unit/utils/test_utils.py +++ b/tests/unit/utils/test_utils.py @@ -28,7 +28,7 @@ import functools import re import shlex import math -import zipfile +import operator from PyQt5.QtCore import QUrl, QRect from PyQt5.QtGui import QClipboard @@ -40,22 +40,117 @@ import yaml import qutebrowser import qutebrowser.utils # for test_qualname from qutebrowser.utils import utils, version, usertypes +from qutebrowser.utils.utils import VersionNumber class TestVersionNumber: - @pytest.mark.parametrize('args, expected', [ - ([5, 15, 2], 'VersionNumber(5, 15, 2)'), - ([5, 15], 'VersionNumber(5, 15)'), - ([5], 'VersionNumber(5)'), + @pytest.mark.parametrize('num, expected', [ + (VersionNumber(5, 15, 2), 'VersionNumber(5, 15, 2)'), + (VersionNumber(5, 15), 'VersionNumber(5, 15)'), + (VersionNumber(5), 'VersionNumber(5)'), ]) - def test_repr(self, args, expected): - num = utils.VersionNumber(*args) + def test_repr(self, num, expected): assert repr(num) == expected + @pytest.mark.parametrize('num, expected', [ + (VersionNumber(5, 15, 2), '5.15.2'), + (VersionNumber(5, 15), '5.15'), + (VersionNumber(5), '5'), + ]) + def test_str(self, num, expected): + assert str(num) == expected + def test_not_normalized(self): with pytest.raises(ValueError, match='Refusing to construct'): - utils.VersionNumber(5, 15, 0) + VersionNumber(5, 15, 0) + + @pytest.mark.parametrize('num, expected', [ + (VersionNumber(5, 15, 2), VersionNumber(5, 15)), + (VersionNumber(5, 15), VersionNumber(5, 15)), + (VersionNumber(6), VersionNumber(6)), + ]) + def test_strip_patch(self, num, expected): + assert num.strip_patch() == expected + + @pytest.mark.parametrize('s, expected', [ + ('1x6.2', VersionNumber(1)), + ('6', VersionNumber(6)), + ('5.15', VersionNumber(5, 15)), + ('5.15.3', VersionNumber(5, 15, 3)), + ('5.15.3.dev1234', VersionNumber(5, 15, 3)), + ]) + def test_parse_valid(self, s, expected): + assert VersionNumber.parse(s) == expected + + @pytest.mark.parametrize('s, message', [ + ('foo6', "Failed to parse foo6"), + ('.6', "Failed to parse .6"), + ('0x6.2', "Can't construct a null version"), + ]) + def test_parse_invalid(self, s, message): + with pytest.raises(ValueError, match=message): + VersionNumber.parse(s) + + @pytest.mark.parametrize('lhs, op, rhs, outcome', [ + # == + (VersionNumber(6), operator.eq, VersionNumber(6), True), + (VersionNumber(6), operator.eq, object(), False), + + # != + (VersionNumber(6), operator.ne, VersionNumber(5), True), + (VersionNumber(6), operator.ne, object(), True), + + # >= + (VersionNumber(5, 14), operator.ge, VersionNumber(5, 13, 5), True), + (VersionNumber(5, 14), operator.ge, VersionNumber(5, 14, 2), False), + (VersionNumber(5, 14, 3), operator.ge, VersionNumber(5, 14, 2), True), + (VersionNumber(5, 14, 3), operator.ge, VersionNumber(5, 14, 3), True), + (VersionNumber(5, 14), operator.ge, VersionNumber(5, 13), True), + (VersionNumber(5, 14), operator.ge, VersionNumber(5, 14), True), + (VersionNumber(5, 14), operator.ge, VersionNumber(5, 15), False), + (VersionNumber(5, 14), operator.ge, VersionNumber(4), True), + (VersionNumber(5, 14), operator.ge, VersionNumber(5), True), + (VersionNumber(5, 14), operator.ge, VersionNumber(6), False), + + # > + (VersionNumber(5, 14), operator.gt, VersionNumber(5, 13, 5), True), + (VersionNumber(5, 14), operator.gt, VersionNumber(5, 14, 2), False), + (VersionNumber(5, 14, 3), operator.gt, VersionNumber(5, 14, 2), True), + (VersionNumber(5, 14, 3), operator.gt, VersionNumber(5, 14, 3), False), + (VersionNumber(5, 14), operator.gt, VersionNumber(5, 13), True), + (VersionNumber(5, 14), operator.gt, VersionNumber(5, 14), False), + (VersionNumber(5, 14), operator.gt, VersionNumber(5, 15), False), + (VersionNumber(5, 14), operator.gt, VersionNumber(4), True), + (VersionNumber(5, 14), operator.gt, VersionNumber(5), True), + (VersionNumber(5, 14), operator.gt, VersionNumber(6), False), + + # <= + (VersionNumber(5, 14), operator.le, VersionNumber(5, 13, 5), False), + (VersionNumber(5, 14), operator.le, VersionNumber(5, 14, 2), True), + (VersionNumber(5, 14, 3), operator.le, VersionNumber(5, 14, 2), False), + (VersionNumber(5, 14, 3), operator.le, VersionNumber(5, 14, 3), True), + (VersionNumber(5, 14), operator.le, VersionNumber(5, 13), False), + (VersionNumber(5, 14), operator.le, VersionNumber(5, 14), True), + (VersionNumber(5, 14), operator.le, VersionNumber(5, 15), True), + (VersionNumber(5, 14), operator.le, VersionNumber(4), False), + (VersionNumber(5, 14), operator.le, VersionNumber(5), False), + (VersionNumber(5, 14), operator.le, VersionNumber(6), True), + + # < + (VersionNumber(5, 14), operator.lt, VersionNumber(5, 13, 5), False), + (VersionNumber(5, 14), operator.lt, VersionNumber(5, 14, 2), True), + (VersionNumber(5, 14, 3), operator.lt, VersionNumber(5, 14, 2), False), + (VersionNumber(5, 14, 3), operator.lt, VersionNumber(5, 14, 3), False), + (VersionNumber(5, 14), operator.lt, VersionNumber(5, 13), False), + (VersionNumber(5, 14), operator.lt, VersionNumber(5, 14), False), + (VersionNumber(5, 14), operator.lt, VersionNumber(5, 15), True), + (VersionNumber(5, 14), operator.lt, VersionNumber(4), False), + (VersionNumber(5, 14), operator.lt, VersionNumber(5), False), + (VersionNumber(5, 14), operator.lt, VersionNumber(6), True), + ]) + def test_comparisons(self, lhs, op, rhs, outcome): + assert op(lhs, rhs) == outcome ELLIPSIS = '\u2026' @@ -132,115 +227,6 @@ def freezer(request, monkeypatch): pytest.skip("Can't run with sys.frozen = True!") -@pytest.mark.usefixtures('freezer') -class TestReadFile: - - @pytest.fixture - def package_path(self, tmp_path): - return tmp_path / 'qutebrowser' - - @pytest.fixture - def html_path(self, package_path): - path = package_path / 'html' - path.mkdir(parents=True) - - for filename in ['test1.html', 'test2.html', 'README', 'unrelatedhtml']: - (path / filename).touch() - - subdir = path / 'subdir' - subdir.mkdir() - (subdir / 'subdir-file.html').touch() - - return path - - @pytest.fixture - def html_zip(self, tmp_path, html_path): - if not hasattr(zipfile, 'Path'): - pytest.skip("Needs zipfile.Path") - - zip_path = tmp_path / 'qutebrowser.zip' - with zipfile.ZipFile(zip_path, 'w') as zf: - for path in html_path.rglob('*'): - zf.write(path, path.relative_to(tmp_path)) - - assert sorted(zf.namelist()) == [ - 'qutebrowser/html/README', - 'qutebrowser/html/subdir/', - 'qutebrowser/html/subdir/subdir-file.html', - 'qutebrowser/html/test1.html', - 'qutebrowser/html/test2.html', - 'qutebrowser/html/unrelatedhtml', - ] - - yield zipfile.Path(zip_path) / 'qutebrowser' - - @pytest.fixture(params=['pathlib', 'zipfile']) - def resource_root(self, request): - """Resource files packaged either directly or via a zip.""" - if request.param == 'pathlib': - request.getfixturevalue('html_path') - return request.getfixturevalue('package_path') - elif request.param == 'zipfile': - return request.getfixturevalue('html_zip') - raise utils.Unreachable(request.param) - - def test_glob_resources(self, resource_root): - files = sorted(utils._glob_resources(resource_root, 'html', '.html')) - assert files == ['html/test1.html', 'html/test2.html'] - - def test_glob_resources_subdir(self, resource_root): - files = sorted(utils._glob_resources(resource_root, 'html/subdir', '.html')) - assert files == ['html/subdir/subdir-file.html'] - - def test_readfile(self): - """Read a test file.""" - content = utils.read_file(os.path.join('utils', 'testfile')) - assert content.splitlines()[0] == "Hello World!" - - @pytest.mark.parametrize('filename', ['javascript/scroll.js', - 'html/error.html']) - def test_read_cached_file(self, mocker, filename): - utils.preload_resources() - m = mocker.patch('qutebrowser.utils.utils.importlib_resources.files') - utils.read_file(filename) - m.assert_not_called() - - def test_readfile_binary(self): - """Read a test file in binary mode.""" - content = utils.read_file_binary(os.path.join('utils', 'testfile')) - assert content.splitlines()[0] == b"Hello World!" - - @pytest.mark.parametrize('name', ['read_file', 'read_file_binary']) - @pytest.mark.parametrize('fake_exception', [KeyError, FileNotFoundError, None]) - def test_not_found(self, name, fake_exception, monkeypatch): - """Test behavior when a resources file wasn't found. - - With fake_exception, we emulate the rather odd error handling of certain Python - versions: https://bugs.python.org/issue43063 - """ - class BrokenFileFake: - - def __init__(self, exc): - self.exc = exc - - def read_bytes(self): - raise self.exc("File does not exist") - - def read_text(self, encoding): - raise self.exc("File does not exist") - - def __truediv__(self, _other): - return self - - if fake_exception is not None: - monkeypatch.setattr(utils.importlib_resources, 'files', - lambda _pkg: BrokenFileFake(fake_exception)) - - meth = getattr(utils, name) - with pytest.raises(FileNotFoundError): - meth('doesnotexist') - - @pytest.mark.parametrize('seconds, out', [ (-1, '-0:01'), (0, '0:00'), @@ -784,7 +770,7 @@ class TestOpenFile: info = version.DistributionInfo( id='org.kde.Platform', parsed=version.Distribution.kde_flatpak, - version=utils.parse_version('5.12'), + version=VersionNumber.parse('5.12'), pretty='Unknown') monkeypatch.setattr(version, 'distribution', lambda: info) |