Skip to content

Commit 338ff4f

Browse files
committed
version: Implement comparison and backport fixes
Backport dependency parsing from toltec-dev/toltec#530 (see #27). Add unit tests for version.py. Implement version comparison rules and dependency matching.
1 parent 5aac6fb commit 338ff4f

File tree

2 files changed

+507
-54
lines changed

2 files changed

+507
-54
lines changed

tests/test_version.py

Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
# Copyright (c) 2022 The Toltec Contributors
2+
# SPDX-License-Identifier: MIT
3+
4+
import unittest
5+
from toltec.version import (
6+
Version,
7+
Dependency,
8+
DependencyKind,
9+
VersionComparator,
10+
InvalidVersionError,
11+
InvalidDependencyError,
12+
)
13+
14+
15+
class TestVersion(unittest.TestCase):
16+
def test_init(self):
17+
with self.assertRaises(
18+
InvalidVersionError,
19+
msg="Invalid epoch '-1', only non-negative values are allowed",
20+
):
21+
version = Version(-1, "test", "0")
22+
23+
with self.assertRaises(
24+
InvalidVersionError,
25+
msg="Invalid chars in upstream version 't:est', allowed chars "
26+
"are A-Za-z0-9.+~-",
27+
):
28+
version = Version(0, "t:est", "0")
29+
30+
with self.assertRaises(
31+
InvalidVersionError,
32+
msg="Upstream version cannot be empty",
33+
):
34+
version = Version(0, "", "0")
35+
36+
with self.assertRaises(
37+
InvalidVersionError,
38+
msg="Invalid chars in revision '1-2-3', allowed chars are "
39+
"A-Za-z0-9.+~",
40+
):
41+
version = Version(0, "test", "1-2-3")
42+
43+
with self.assertRaises(
44+
InvalidVersionError,
45+
msg="Revision cannot be empty",
46+
):
47+
version = Version(0, "test", "")
48+
49+
version = Version(1, "test", "1")
50+
self.assertEqual(version.upstream, "test")
51+
self.assertEqual(version.revision, "1")
52+
self.assertEqual(version.epoch, 1)
53+
54+
def test_parse(self):
55+
valid_versions = (
56+
("0.0.0-1", Version(0, "0.0.0", "1")),
57+
("0.0.1-1", Version(0, "0.0.1", "1")),
58+
("0.1.0-3", Version(0, "0.1.0", "3")),
59+
("0.1.1", Version(0, "0.1.1", "0")),
60+
("1.0-0", Version(0, "1.0", "0")),
61+
("1.0.0", Version(0, "1.0.0", "0")),
62+
("1-0-0", Version(0, "1-0", "0")),
63+
("1:0.0.14-1", Version(1, "0.0.14", "1")),
64+
("1.0.20210219-2", Version(0, "1.0.20210219", "2")),
65+
("1.3.5-14", Version(0, "1.3.5", "14")),
66+
("19.21-2", Version(0, "19.21", "2")),
67+
("2.0.10-1", Version(0, "2.0.10", "1")),
68+
("2020.11.08-2", Version(0, "2020.11.08", "2")),
69+
)
70+
71+
for string, parsed in valid_versions:
72+
self.assertEqual(Version.parse(string), parsed)
73+
74+
with self.assertRaises(
75+
InvalidVersionError,
76+
msg="Invalid epoch 'test', must be numeric",
77+
):
78+
version = Version.parse("test:1.1")
79+
80+
with self.assertRaises(
81+
InvalidVersionError,
82+
msg="Upstream version cannot be empty",
83+
):
84+
version = Version.parse("0:-1")
85+
86+
def test_compare(self):
87+
self.assertEqual(Version(0, "1.0", "1"), Version(0, "1.0", "1"))
88+
89+
ordered_pairs = (
90+
(Version(0, "1.0", "1"), Version(1, "0.1", "1")),
91+
(Version(0, "1.0", "1"), Version(0, "1.0", "2")),
92+
(Version(0, "1.0", "2"), Version(0, "1.1", "1")),
93+
(Version(1, "1.0~~", "7"), Version(1, "1.0~~a", "1")),
94+
(Version(1, "1.0~~a", "7"), Version(1, "1.0~", "1")),
95+
(Version(1, "1.0~", "7"), Version(1, "1.0", "1")),
96+
(Version(1, "1.0", "7"), Version(1, "1.0a", "1")),
97+
)
98+
99+
for lower, greater in ordered_pairs:
100+
self.assertTrue(lower < greater)
101+
self.assertTrue(lower <= greater)
102+
self.assertTrue(greater > lower)
103+
self.assertTrue(greater >= lower)
104+
self.assertFalse(greater < lower)
105+
self.assertFalse(greater <= lower)
106+
self.assertFalse(lower > greater)
107+
self.assertFalse(lower >= greater)
108+
109+
110+
class TestDependency(unittest.TestCase):
111+
def test_init(self):
112+
version = Version(1, "0.1", "1")
113+
dep = Dependency(
114+
DependencyKind.BUILD,
115+
"test",
116+
VersionComparator.GREATER_THAN_OR_EQUAL,
117+
version,
118+
)
119+
self.assertEqual(dep.kind, DependencyKind.BUILD)
120+
self.assertEqual(dep.package, "test")
121+
self.assertEqual(
122+
dep.version_comparator,
123+
VersionComparator.GREATER_THAN_OR_EQUAL,
124+
)
125+
self.assertEqual(dep.version, version)
126+
127+
def test_parse(self):
128+
valid_deps = (
129+
(
130+
"test",
131+
Dependency(
132+
DependencyKind.HOST,
133+
"test",
134+
VersionComparator.EQUAL,
135+
None,
136+
),
137+
),
138+
(
139+
"host:test",
140+
Dependency(
141+
DependencyKind.HOST,
142+
"test",
143+
VersionComparator.EQUAL,
144+
None,
145+
),
146+
),
147+
(
148+
"build:test",
149+
Dependency(
150+
DependencyKind.BUILD,
151+
"test",
152+
VersionComparator.EQUAL,
153+
None,
154+
),
155+
),
156+
(
157+
"test=0.1-1",
158+
Dependency(
159+
DependencyKind.HOST,
160+
"test",
161+
VersionComparator.EQUAL,
162+
Version(0, "0.1", "1"),
163+
),
164+
),
165+
(
166+
"test<<0.1-1",
167+
Dependency(
168+
DependencyKind.HOST,
169+
"test",
170+
VersionComparator.LOWER_THAN,
171+
Version(0, "0.1", "1"),
172+
),
173+
),
174+
(
175+
"test<=0.1-1",
176+
Dependency(
177+
DependencyKind.HOST,
178+
"test",
179+
VersionComparator.LOWER_THAN_OR_EQUAL,
180+
Version(0, "0.1", "1"),
181+
),
182+
),
183+
(
184+
"test>>0.1-1",
185+
Dependency(
186+
DependencyKind.HOST,
187+
"test",
188+
VersionComparator.GREATER_THAN,
189+
Version(0, "0.1", "1"),
190+
),
191+
),
192+
(
193+
"test>=0.1-1",
194+
Dependency(
195+
DependencyKind.HOST,
196+
"test",
197+
VersionComparator.GREATER_THAN_OR_EQUAL,
198+
Version(0, "0.1", "1"),
199+
),
200+
),
201+
(
202+
"test=1:0.1-1",
203+
Dependency(
204+
DependencyKind.HOST,
205+
"test",
206+
VersionComparator.EQUAL,
207+
Version(1, "0.1", "1"),
208+
),
209+
),
210+
(
211+
"build:test=1:0.1-1",
212+
Dependency(
213+
DependencyKind.BUILD,
214+
"test",
215+
VersionComparator.EQUAL,
216+
Version(1, "0.1", "1"),
217+
),
218+
),
219+
)
220+
221+
for string, parsed in valid_deps:
222+
self.assertEqual(Dependency.parse(string), parsed)
223+
224+
with self.assertRaises(
225+
InvalidDependencyError,
226+
msg="Unknown dependency type 'invalid', valid types are "
227+
"'build', 'host'",
228+
):
229+
dep = Dependency.parse("invalid:test")
230+
231+
with self.assertRaises(
232+
InvalidDependencyError,
233+
msg="Invalid version comparator '<<>>', valid operators are "
234+
"'<<', '<=', '=', '>=', '>>'",
235+
):
236+
dep = Dependency.parse("host:test<<>>0.1")
237+
238+
def test_to_debian(self):
239+
converted_versions = (
240+
("test", "test"),
241+
("host:test", "test"),
242+
("test=0.1-1", "test (= 0.1-1)"),
243+
("test<<0.1-1", "test (<< 0.1-1)"),
244+
("test<=0.1-1", "test (<= 0.1-1)"),
245+
("test>>0.1-1", "test (>> 0.1-1)"),
246+
("test>=0.1-1", "test (>= 0.1-1)"),
247+
("test=1:0.1-1", "test (= 1:0.1-1)"),
248+
)
249+
250+
for ours, debian in converted_versions:
251+
self.assertEqual(Dependency.parse(ours).to_debian(), debian)
252+
253+
def test_match(self):
254+
matches = (
255+
("test", "0.1", True),
256+
("test", "0.1-0", True),
257+
("test", "0:0.1-0", True),
258+
("test", "0.1-1", True),
259+
("test", "0.0", True),
260+
("test", "1:0.0", True),
261+
("test=0.1", "0.1", True),
262+
("test=0.1", "0.1-0", True),
263+
("test=0.1", "0:0.1-0", True),
264+
("test=0.1", "0.1-1", False),
265+
("test=0.1", "0.0", False),
266+
("test=0.1", "1:0.0", False),
267+
("test>=0.1", "0.1", True),
268+
("test>=0.1", "0.1-0", True),
269+
("test>=0.1", "0:0.1-0", True),
270+
("test>=0.1", "0.1-1", True),
271+
("test>=0.1", "0.0", False),
272+
("test>=0.1", "1:0.0", True),
273+
("test>>0.1", "0.1", False),
274+
("test>>0.1", "0.1-0", False),
275+
("test>>0.1", "0:0.1-0", False),
276+
("test>>0.1", "0.1-1", True),
277+
("test>>0.1", "0.0", False),
278+
("test>>0.1", "1:0.0", True),
279+
("test<=0.1", "0.1", True),
280+
("test<=0.1", "0.1-0", True),
281+
("test<=0.1", "0:0.1-0", True),
282+
("test<=0.1", "0.1-1", False),
283+
("test<=0.1", "0.0", True),
284+
("test<=0.1", "1:0.0", False),
285+
("test<<0.1", "0.1", False),
286+
("test<<0.1", "0.1-0", False),
287+
("test<<0.1", "0:0.1-0", False),
288+
("test<<0.1", "0.1-1", False),
289+
("test<<0.1", "0.0", True),
290+
("test<<0.1", "1:0.0", False),
291+
)
292+
293+
for dep, version, result in matches:
294+
self.assertEqual(
295+
Dependency.parse(dep).match(Version.parse(version)),
296+
result,
297+
f"match {dep} with {version} is {result}",
298+
)

0 commit comments

Comments
 (0)