summaryrefslogtreecommitdiff
path: root/tests/unit/utils/test_utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit/utils/test_utils.py')
-rw-r--r--tests/unit/utils/test_utils.py222
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)