| # SPDX-License-Identifier: Apache-2.0 |
| # |
| # Modifications by Apache Solr contributors; see git log for details. |
| # Licensed under the Apache License, Version 2.0. |
| # |
| # The OpenSearch Contributors require contributions made to |
| # this file be licensed under the Apache-2.0 license or a |
| # compatible open source license. |
| # Modifications Copyright OpenSearch Contributors. See |
| # GitHub history for details. |
| # Licensed to Elasticsearch B.V. under one or more contributor |
| # license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright |
| # ownership. Elasticsearch B.V. licenses this file to you under |
| # the Apache License, Version 2.0 (the "License"); you may |
| # not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| import random |
| import re |
| |
| import pytest # type: ignore |
| |
| from solrorbit import exceptions |
| from solrorbit.utils import versions |
| |
| |
| class TestsVersions: |
| def test_is_version_identifier(self): |
| assert versions.is_version_identifier(None) is False |
| assert versions.is_version_identifier("") is False |
| assert versions.is_version_identifier(" \t ") is False |
| assert versions.is_version_identifier("5-ab-c") is False |
| assert versions.is_version_identifier("5.1") is False |
| assert versions.is_version_identifier("5") is False |
| |
| assert versions.is_version_identifier("5.0.0") |
| assert versions.is_version_identifier("1.7.3") |
| assert versions.is_version_identifier("20.3.7-SNAPSHOT") |
| |
| assert versions.is_version_identifier(None, strict=False) is False |
| assert versions.is_version_identifier("", strict=False) is False |
| assert versions.is_version_identifier("5.1", strict=False) |
| assert versions.is_version_identifier("5", strict=False) |
| assert versions.is_version_identifier("23", strict=False) |
| assert versions.is_version_identifier("20.3.7-SNAPSHOT", strict=False) |
| |
| def test_finds_components_for_valid_version(self): |
| assert versions.components("5.0.3") == (5, 0, 3, None) |
| assert versions.components("7.12.1-SNAPSHOT") == (7, 12, 1, "SNAPSHOT") |
| |
| assert versions.components("25", strict=False) == (25, None, None, None) |
| assert versions.components("5.1", strict=False) == (5, 1, None, None) |
| |
| def test_major_version(self): |
| assert versions.major_version("7.10.2") == 7 |
| assert versions.major_version("7.12.1-SNAPSHOT") == 7 |
| assert versions.major_version("25.0.3") == 25 |
| |
| @pytest.mark.parametrize("seed", range(40)) |
| def test_latest_bounded_minor(self, seed): |
| _alternatives = ["7", "7.10", "7.11.2", "7.2", "5", "6", "main"] |
| random.seed(seed) |
| alternatives = _alternatives.copy() |
| random.shuffle(alternatives) |
| |
| assert versions.latest_bounded_minor(alternatives, versions.VersionVariants("7.6.3")) == 2 |
| assert versions.latest_bounded_minor(alternatives, versions.VersionVariants("7.12.3")) == 10,\ |
| "Nearest alternative with major.minor, skip alternatives with major.minor.patch" |
| assert versions.latest_bounded_minor(alternatives, versions.VersionVariants("7.11.2")) == 10,\ |
| "Skips all alternatives with major.minor.patch, even if exact match" |
| assert versions.latest_bounded_minor(alternatives, versions.VersionVariants("7.1.0")) is None,\ |
| "No matching alternative with minor version" |
| |
| def test_components_ignores_invalid_versions(self): |
| with pytest.raises( |
| exceptions.InvalidSyntax, |
| match=re.escape( |
| r"version string '5.0.0a' does not conform to pattern " |
| r"'^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$'")): |
| versions.components("5.0.0a") |
| |
| def test_versionvariants_parses_correct_version_string(self): |
| assert versions.VersionVariants("5.0.3").all_versions == [ |
| ("5.0.3", "with_patch"), |
| ("5.0", "with_minor"), |
| ("5", "with_major")] |
| assert versions.VersionVariants("7.12.1-SNAPSHOT").all_versions == [ |
| ("7.12.1-SNAPSHOT", "with_suffix"), |
| ("7.12.1", "with_patch"), |
| ("7.12", "with_minor"), |
| ("7", "with_major")] |
| assert versions.VersionVariants("10.3.63").all_versions == [ |
| ("10.3.63", "with_patch"), |
| ("10.3", "with_minor"), |
| ("10", "with_major")] |
| |
| def test_versions_rejects_invalid_version_strings(self): |
| with pytest.raises( |
| exceptions.InvalidSyntax, |
| match=re.escape(r"version string '5.0.0a-SNAPSHOT' does not conform to pattern " |
| r"'^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$'") |
| ): |
| versions.VersionVariants("5.0.0a-SNAPSHOT") |
| |
| def test_find_best_match(self): |
| assert versions.best_match(["1.7", "2", "5.0.0-alpha1", "5", "main"], "6.0.0-alpha1") == "main",\ |
| "Assume main for versions newer than latest alternative available" |
| |
| assert versions.best_match(["1.7", "2", "5.0.0-alpha1", "5", "main"], "5.1.0-SNAPSHOT") == "5",\ |
| "Best match for specific version" |
| |
| assert versions.best_match(["1.7", "2", "5.0.0-alpha1", "5", "main"], None) == "main",\ |
| "Assume main on unknown version" |
| |
| assert versions.best_match(["1.7", "2", "5.0.0-alpha1", "5", "main"], "0.4") is None,\ |
| "Reject versions that are too old" |
| |
| assert versions.best_match(["7", "7.10.2", "7.11", "7.2", "5", "6", "main"], "7.10.2") == "7.10.2", \ |
| "Exact match" |
| |
| assert versions.best_match(["7", "7.10", "main"], "7.1.0") == "7", \ |
| "Best match is major version" |
| |
| assert versions.best_match(["7", "7.11", "7.2", "5", "6", "main"], "7.11.0") == "7.11",\ |
| "Best match for specific minor version" |
| |
| assert versions.best_match(["7", "7.11", "7.2", "5", "6", "main"], "7.12.0") == "7.11",\ |
| "If no exact match, best match is the nearest prior minor" |
| |
| assert versions.best_match(["7", "7.11", "7.2", "5", "6", "main"], "7.3.0") == "7.2",\ |
| "If no exact match, best match is the nearest prior minor" |
| |
| assert versions.best_match(["7", "7.11", "7.2", "5", "6", "main"], "7.10.0") == "7.2", \ |
| "If no exact match, best match is the nearest prior minor" |
| |
| assert versions.best_match(["7", "7.1", "7.11.1", "7.11.0", "7.2", "5", "6", "main"], "7.12.0") == "7.2",\ |
| "Patch or patch-suffix branches are not supported and ignored, best match is nearest prior minor" |
| |
| assert versions.best_match(["7", "7.11", "7.2", "5", "6", "main"], "7.1.0") == "7",\ |
| "If no exact match and no minor match, next best match is major version" |
| |
| def test_version_comparison(self): |
| assert versions.Version.from_string("7.10.2") < versions.Version.from_string("7.11.0") |
| assert versions.Version.from_string("7.10.2") == versions.Version.from_string("7.10.2") |