173 lines
4.5 KiB
Python
173 lines
4.5 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from ptlinux.update_resolver import (
|
|
BLOCKED_STATUS,
|
|
PRERELEASE_CHANNEL,
|
|
STABLE_CHANNEL,
|
|
WITHDRAWN_STATUS,
|
|
ReleaseModelError,
|
|
ReleaseRecord,
|
|
SemanticVersion,
|
|
UpdateResolver,
|
|
previous_release_tag,
|
|
validate_channel_version,
|
|
validate_release_progression,
|
|
)
|
|
|
|
|
|
class SemanticVersionTests(unittest.TestCase):
|
|
def test_orders_beta_rc_final_and_multidigit_versions(self) -> None:
|
|
versions = [
|
|
SemanticVersion.parse(value)
|
|
for value in (
|
|
"1.9.0",
|
|
"1.9.0-rc.1",
|
|
"1.10.0",
|
|
"1.9.0-beta.2",
|
|
"1.9.0-beta.1",
|
|
"1.9.9",
|
|
)
|
|
]
|
|
|
|
self.assertEqual(
|
|
[str(value) for value in sorted(versions)],
|
|
[
|
|
"1.9.0-beta.1",
|
|
"1.9.0-beta.2",
|
|
"1.9.0-rc.1",
|
|
"1.9.0",
|
|
"1.9.9",
|
|
"1.10.0",
|
|
],
|
|
)
|
|
|
|
def test_rejects_unsupported_or_noncanonical_versions(self) -> None:
|
|
for value in (
|
|
"v1.2.3",
|
|
"01.2.3",
|
|
"1.02.3",
|
|
"1.2.03",
|
|
"1.2.3-alpha.1",
|
|
"1.2.3-beta",
|
|
"1.2.3+build",
|
|
):
|
|
with self.subTest(value=value):
|
|
with self.assertRaises(ReleaseModelError):
|
|
SemanticVersion.parse(value)
|
|
|
|
def test_rejects_channel_version_mismatches(self) -> None:
|
|
with self.assertRaisesRegex(ReleaseModelError, "belongs to prerelease"):
|
|
validate_channel_version(STABLE_CHANNEL, "1.9.0-beta.1")
|
|
with self.assertRaisesRegex(ReleaseModelError, "belongs to stable"):
|
|
validate_channel_version(PRERELEASE_CHANNEL, "1.9.0")
|
|
|
|
def test_selects_channel_specific_changelog_bases(self) -> None:
|
|
tags = ["not-a-release", "v1.7.4", "v1.9.0-beta.1", "v1.9.0-beta.2"]
|
|
|
|
self.assertEqual(
|
|
previous_release_tag(STABLE_CHANNEL, "1.8.0", tags),
|
|
"v1.7.4",
|
|
)
|
|
self.assertEqual(
|
|
previous_release_tag(PRERELEASE_CHANNEL, "1.9.0-rc.1", tags),
|
|
"v1.9.0-beta.2",
|
|
)
|
|
self.assertEqual(
|
|
previous_release_tag(PRERELEASE_CHANNEL, "2.0.0-beta.1", tags),
|
|
"v1.7.4",
|
|
)
|
|
|
|
def test_release_progression_cannot_move_a_channel_backwards(self) -> None:
|
|
validate_release_progression(
|
|
STABLE_CHANNEL,
|
|
"1.9.0",
|
|
["v1.8.0", "v2.0.0-beta.1"],
|
|
)
|
|
validate_release_progression(
|
|
PRERELEASE_CHANNEL,
|
|
"2.0.0-beta.2",
|
|
["v1.9.0", "v2.0.0-beta.1"],
|
|
)
|
|
with self.assertRaisesRegex(ReleaseModelError, "newer"):
|
|
validate_release_progression(
|
|
STABLE_CHANNEL,
|
|
"1.8.0",
|
|
["v1.9.0"],
|
|
)
|
|
with self.assertRaisesRegex(ReleaseModelError, "newer"):
|
|
validate_release_progression(
|
|
PRERELEASE_CHANNEL,
|
|
"1.9.0-rc.1",
|
|
["v2.0.0-beta.1"],
|
|
)
|
|
|
|
|
|
class UpdateResolverTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.resolver = UpdateResolver(
|
|
[
|
|
ReleaseRecord("1.7.4", STABLE_CHANNEL, tag="v1.7.4"),
|
|
ReleaseRecord("1.8.0", STABLE_CHANNEL, tag="v1.8.0"),
|
|
ReleaseRecord("1.9.0-beta.1", PRERELEASE_CHANNEL),
|
|
ReleaseRecord("1.9.0-beta.2", PRERELEASE_CHANNEL),
|
|
ReleaseRecord("1.9.0-rc.1", PRERELEASE_CHANNEL),
|
|
ReleaseRecord("2.0.0-beta.1", PRERELEASE_CHANNEL, WITHDRAWN_STATUS),
|
|
ReleaseRecord("2.0.0-beta.2", PRERELEASE_CHANNEL, BLOCKED_STATUS),
|
|
]
|
|
)
|
|
|
|
def test_stable_clients_never_receive_prereleases(self) -> None:
|
|
candidate = self.resolver.update_candidate("1.7.4", STABLE_CHANNEL)
|
|
|
|
self.assertIsNotNone(candidate)
|
|
assert candidate is not None
|
|
self.assertEqual(candidate.version, "1.8.0")
|
|
|
|
def test_prerelease_clients_receive_highest_active_semantic_version(self) -> None:
|
|
candidate = self.resolver.update_candidate(
|
|
"1.9.0-beta.1",
|
|
PRERELEASE_CHANNEL,
|
|
)
|
|
|
|
self.assertIsNotNone(candidate)
|
|
assert candidate is not None
|
|
self.assertEqual(candidate.version, "1.9.0-rc.1")
|
|
|
|
def test_prerelease_client_transitions_to_the_final_stable_release(self) -> None:
|
|
resolver = UpdateResolver(
|
|
[
|
|
ReleaseRecord("1.9.0-rc.1", PRERELEASE_CHANNEL),
|
|
ReleaseRecord("1.9.0", STABLE_CHANNEL),
|
|
]
|
|
)
|
|
|
|
candidate = resolver.update_candidate("1.9.0-rc.1", PRERELEASE_CHANNEL)
|
|
|
|
self.assertIsNotNone(candidate)
|
|
assert candidate is not None
|
|
self.assertEqual(candidate.version, "1.9.0")
|
|
|
|
def test_switching_to_stable_does_not_downgrade(self) -> None:
|
|
self.assertIsNone(
|
|
self.resolver.update_candidate("1.9.0-beta.2", STABLE_CHANNEL)
|
|
)
|
|
|
|
def test_channel_aware_rollback_candidates_are_real_releases(self) -> None:
|
|
stable = self.resolver.rollback_candidates("1.9.0", STABLE_CHANNEL)
|
|
prerelease = self.resolver.rollback_candidates(
|
|
"1.9.0-rc.1",
|
|
PRERELEASE_CHANNEL,
|
|
)
|
|
|
|
self.assertEqual([item.version for item in stable], ["1.8.0", "1.7.4"])
|
|
self.assertEqual(
|
|
[item.version for item in prerelease],
|
|
["1.9.0-beta.2", "1.9.0-beta.1", "1.8.0", "1.7.4"],
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|