From 4190fe1ef148c4627524b77419b7d940b088c4af Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 14 Jul 2017 14:00:52 -0300 Subject: [PATCH] topotest: add version comparison function Implemented a version comparison function that tells if a version contained in a string is greater/less/equal to another. --- tests/topotests/lib/test/test_version.py | 80 ++++++++++++++++++++++++ tests/topotests/lib/topotest.py | 55 ++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 tests/topotests/lib/test/test_version.py diff --git a/tests/topotests/lib/test/test_version.py b/tests/topotests/lib/test/test_version.py new file mode 100644 index 0000000000..4bb1c0b018 --- /dev/null +++ b/tests/topotests/lib/test/test_version.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python + +# +# test_version.py +# Tests for library function: version_cmp(). +# +# Copyright (c) 2017 by +# Network Device Education Foundation, Inc. ("NetDEF") +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +Tests for the version_cmp() function. +""" + +import os +import sys +import pytest + +# Save the Current Working Directory to find lib files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, '../../')) + +# pylint: disable=C0413 +from lib.topotest import version_cmp + +def test_valid_versions(): + "Test valid version compare results" + + curver = '3.0' + samever = '3' + oldver = '2.0' + newver = '3.0.1' + newerver = '3.0.11' + vercustom = '3.0-dev' + verysmallinc = '3.0.0.0.0.0.0.1' + + assert version_cmp(curver, oldver) == 1 + assert version_cmp(curver, newver) == -1 + assert version_cmp(curver, curver) == 0 + assert version_cmp(curver, newerver) == -1 + assert version_cmp(newver, newerver) == -1 + assert version_cmp(curver, samever) == 0 + assert version_cmp(curver, vercustom) == 0 + assert version_cmp(vercustom, vercustom) == 0 + assert version_cmp(vercustom, oldver) == 1 + assert version_cmp(vercustom, newver) == -1 + assert version_cmp(vercustom, samever) == 0 + assert version_cmp(curver, verysmallinc) == -1 + assert version_cmp(newver, verysmallinc) == 1 + assert version_cmp(verysmallinc, verysmallinc) == 0 + assert version_cmp(vercustom, verysmallinc) == -1 + +def test_invalid_versions(): + "Test invalid version strings" + + curver = '3.0' + badver1 = '.1' + badver2 = '-1.0' + badver3 = '.' + badver4 = '3.-0.3' + + with pytest.raises(ValueError): + assert version_cmp(curver, badver1) + assert version_cmp(curver, badver2) + assert version_cmp(curver, badver3) + assert version_cmp(curver, badver4) diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index b83d75a717..7872e7087a 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -232,6 +232,61 @@ def normalize_text(text): text = re.sub(r'\r', '', text) return text +def version_cmp(v1, v2): + """ + Compare two version strings and returns: + + * `-1`: if `v1` is less than `v2` + * `0`: if `v1` is equal to `v2` + * `1`: if `v1` is greater than `v2` + + Raises `ValueError` if versions are not well formated. + """ + vregex = r'(?P\d+(\.(\d+))*)' + v1m = re.match(vregex, v1) + v2m = re.match(vregex, v2) + if v1m is None or v2m is None: + raise ValueError("got a invalid version string") + + # Split values + v1g = v1m.group('whole').split('.') + v2g = v2m.group('whole').split('.') + + # Get the longest version string + vnum = len(v1g) + if len(v2g) > vnum: + vnum = len(v2g) + + # Reverse list because we are going to pop the tail + v1g.reverse() + v2g.reverse() + for _ in range(vnum): + try: + v1n = int(v1g.pop()) + except IndexError: + while v2g: + v2n = int(v2g.pop()) + if v2n > 0: + return -1 + break + + try: + v2n = int(v2g.pop()) + except IndexError: + if v1n > 0: + return 1 + while v1g: + v1n = int(v1g.pop()) + if v1n > 0: + return -1 + break + + if v1n > v2n: + return 1 + if v1n < v2n: + return -1 + return 0 + def checkAddressSanitizerError(output, router, component): "Checks for AddressSanitizer in output. If found, then logs it and returns true, false otherwise" -- 2.39.5