def test_ordered_versop_expressions(self): """Given set of ranges, order them according to version/operator (most recent/specific first)""" # simple version ordering, all different versions ovop = OrderedVersionOperators() versop_exprs = [ '> 3.0.0', '>= 2.5.0', '> 2.0.0', '== 1.0.0', ] # add version expressions out of order intentionally ovop.add(versop_exprs[1]) ovop.add(versop_exprs[-1]) ovop.add(versop_exprs[0]) ovop.add(versop_exprs[2]) # verify whether order is what we expect it to be self.assertEqual(ovop.versops, [VersionOperator(x) for x in versop_exprs]) # more complex version ordering, identical/overlapping vesions ovop = OrderedVersionOperators() versop_exprs = [ '== 1.0.0', '> 1.0.0', '< 1.0.0', ] # add version expressions out of order intentionally ovop.add(versop_exprs[-1]) ovop.add(versop_exprs[1]) ovop.add(versop_exprs[0]) # verify whether order is what we expect it to be self.assertEqual(ovop.versops, [VersionOperator(x) for x in versop_exprs])
def test_boolean(self): """Test boolean test""" self.assertTrue(VersionOperator('>= 123')) self.assertTrue(VersionOperator('123')) error_msg = "Failed to parse '<=' as a version operator string" self.assertErrorRegex(EasyBuildError, error_msg, VersionOperator, '<=')
def test_versop_overlap_conflict(self): """Test overlap/conflicts""" overlap_conflict = [ ('> 3', '> 3', (True, False)), # equal, and thus overlap. no conflict ('> 3', '< 2', (False, False)), # no overlap ('> 3', '== 3', (False, False)), # no overlap ('< 3', '> 2', (True, True) ), # overlap, and conflict (region between 2 and 3 is ambiguous) ('>= 3', '== 3', (True, True)), # overlap, and conflict (boundary 3 is ambigous) ('> 3', '>= 3', (True, False) ), # overlap, no conflict ('> 3' is more strict then '>= 3') # suffix ('> 2', '> 1', (True, False) ), # suffix both equal (both None), ordering like above ('> 2 suffix:-x1', '> 1 suffix:-x1', (True, False)), # suffix both equal (both -x1), ordering like above ('> 2 suffix:-x1', '> 1 suffix:-x2', (True, True)), # suffix not equal, conflict (and overlap) ('> 2 suffix:-x1', '< 1 suffix:-x2', (False, True)), # suffix not equal, conflict (and no overlap) ('> 2 suffix:-x1', '< 1 suffix:-x1', (False, False)), # suffix equal, no conflict (and no overlap) ] for l, r, res in overlap_conflict: vl = VersionOperator(l) vr = VersionOperator(r) self.assertEqual(vl.test_overlap_and_conflict(vr), res)
def test_versop_gt(self): """Test strict greater then ordering""" left_gt_right = [ ( '> 2', '> 1' ), # True, order by strictness equals order by boundaries for gt/ge ( '< 8', '< 10' ), # True, order by strictness equals inversed order by boundaries for lt/le ( '== 4', '> 3' ), # equality is more strict then inequality, but this order by boundaries ( '> 3', '== 2' ), # there is no overlap, so just order the intervals according their boundaries ('== 1', '> 1'), # no overlap, same boundaries, order by operator ('== 1', '< 1'), # no overlap, same boundaries, order by operator ( '> 1', '>= 1' ), # no overlap, same boundaries, order by operator (order by strictness) ( '< 1', '<= 1' ), # no overlap, same boundaries, order by operator (order by strictness) ( '> 1', '< 1' ), # no overlap, same boundaries, order by operator (quite arbitrary in this case) # suffix ('> 2 suffix:-x1', '> 1 suffix:-x1' ), # equal suffixes, regular ordering ] for l, r in left_gt_right: self.assertTrue( VersionOperator(l) > VersionOperator(r), "%s gt %s" % (l, r))
def test_hashing(self): """Test hashing of VersionOperator and ToolchainVersionOperator instances.""" test_cases = [ VersionOperator('1.2.3'), VersionOperator('> 1.2.3'), ToolchainVersionOperator('foo'), ToolchainVersionOperator('foo > 1.2.3'), ] for test_case in test_cases: self.assertTrue(hash(test_case))
def test_ordered_versop_add_data(self): """Test the add and data handling""" ovop = OrderedVersionOperators() tests = [ ('> 1', '5'), ('> 2', { 'x': 3 }), ] for versop_txt, data in tests: versop = VersionOperator(versop_txt) ovop.add(versop) # no data was added, this is a new entry, mapper is initialised with None self.assertEqual(ovop.get_data(versop), None) ovop.add(versop, data) # test data self.assertEqual(ovop.get_data(versop), data) # new data for same versops tests = [ ('> 1', '6'), ('> 2', { 'x': 4 }), ] for versop_txt, data in tests: versop = VersionOperator(versop_txt) ovop.add(versop, data) # test updated data self.assertEqual(ovop.get_data(versop), data) # 'update' a value # the data for '> 1' has no .update() extra_data = {'y': 4} tests = [ ('> 2', extra_data), ] for versop_txt, data in tests: versop = VersionOperator(versop_txt) prevdata = copy.deepcopy(ovop.get_data(versop)) prevdata.update(extra_data) ovop.add(versop, data, update=True) # test updated data self.assertEqual(ovop.get_data(versop), prevdata) # use update=True on new element versop = VersionOperator('> 10000') new_data = {'new': 5} ovop.add(versop, new_data, update=True) # test updated data self.assertEqual(ovop.get_data(versop), new_data)
def test_versop_overlap_conflict(self): """Test overlap/conflicts""" overlap_conflict = [ ('> 3', '> 3', (True, False)), # equal, and thus overlap. no conflict ('> 3', '< 2', (False, False)), # no overlap ('> 3', '== 3', (False, False)), # no overlap ('< 3', '> 2', (True, True)), # overlap, and conflict (region between 2 and 3 is ambiguous) ('>= 3', '== 3' , (True, True)), # overlap, and conflict (boundary 3 is ambigous) ('> 3', '>= 3' , (True, False)), # overlap, no conflict ('> 3' is more strict then '>= 3') ] for l, r, res in overlap_conflict: vl = VersionOperator(l) vr = VersionOperator(r) self.assertEqual(vl.test_overlap_and_conflict(vr), res)
def test_parser_regex(self): """Test the version parser""" vop = VersionOperator() # version tests self.assertTrue(vop.regex.search('< 4')) self.assertTrue(vop.regex.search('>= 20131016')) self.assertTrue(vop.regex.search('<= 1.2.3')) self.assertTrue(vop.regex.search('> 2.4')) self.assertTrue(vop.regex.search('== 1.2b')) self.assertTrue(vop.regex.search('< 2.0dev')) self.assertTrue( vop.regex.search('1.2.3')) # operator is optional, '==' is default self.assertFalse( vop.regex.search('>=') ) # version is mandatory (even if DEFAULT_UNDEFINED_VERSION exists) self.assertFalse(vop.regex.search( '%s1.2.3' % vop.SEPARATOR)) # no separator usage w/o something to separate self.assertFalse(vop.regex.search( '1.2.3%s' % vop.SEPARATOR)) # no separator usage w/o something to separate self.assertFalse( vop.regex.search('>%s2.4' % vop.SEPARATOR * 2)) # double space as separator is not allowed self.assertFalse(vop.regex.search( '>%s 2.4' % vop.SEPARATOR)) # double separator is not allowed self.assertTrue(vop.regex.search( '>%sa2.4' % vop.SEPARATOR)) # version starts/ends with *any* word character self.assertTrue(vop.regex.search( '>%s2.4_' % vop.SEPARATOR)) # version starts/ends with *any* word character self.assertTrue(vop.regex.search( '>%sG2.4_' % vop.SEPARATOR)) # version starts/ends with *any* word character
def test_versop_overlap_conflict(self): """Test overlap/conflicts""" overlap_conflict = [ ('> 3', '> 3', (True, False)), # equal, and thus overlap. no conflict ('> 3', '< 2', (False, False)), # no overlap ('> 3', '== 3', (False, False)), # no overlap ('< 3', '> 2', (True, True)), # overlap, and conflict (region between 2 and 3 is ambiguous) ('>= 3', '== 3' , (True, True)), # overlap, and conflict (boundary 3 is ambigous) ('> 3', '>= 3' , (True, False)), # overlap, no conflict ('> 3' is more strict then '>= 3') # suffix ('> 2', '> 1', (True, False)), # suffix both equal (both None), ordering like above ('> 2 suffix:-x1', '> 1 suffix:-x1', (True, False)), # suffix both equal (both -x1), ordering like above ('> 2 suffix:-x1', '> 1 suffix:-x2', (True, True)), # suffix not equal, conflict (and overlap) ('> 2 suffix:-x1', '< 1 suffix:-x2', (False, True)), # suffix not equal, conflict (and no overlap) ('> 2 suffix:-x1', '< 1 suffix:-x1', (False, False)), # suffix equal, no conflict (and no overlap) ] for l, r, res in overlap_conflict: vl = VersionOperator(l) vr = VersionOperator(r) self.assertEqual(vl.test_overlap_and_conflict(vr), res)
def test_dependency(self): """Test Dependency class""" versop_str = '>= 1.5' tc_versop_str = 'GCC >= 3.0' versop = VersionOperator(versop_str) tc_versop = ToolchainVersionOperator(tc_versop_str) txt = Dependency.SEPARATOR_DEP.join([versop_str]) dest = {'versop':versop} res = Dependency(txt) self.assertEqual(dest, res) self.assertEqual(str(res), txt) txt = Dependency.SEPARATOR_DEP.join([versop_str, tc_versop_str]) dest = {'versop':versop, 'tc_versop':tc_versop} res = Dependency(txt) self.assertEqual(dest, res) self.assertEqual(str(res), txt)
def _from_string(self, txt): """Convert from string versop_str;tc_versop_str -> {'versop': versop, 'tc_versop': tc_versop} """ res = {} items = self._split_string(txt, sep=self.SEPARATOR_DEP) if len(items) < 1 or len(items) > 2: msg = 'Dependency has at least one element (a version operator string), ' msg += 'and at most 2 (2nd element the toolchain version operator string). ' msg += 'Separator %s.' % self.SEPARATOR_DEP raise ValueError(msg) res['versop'] = VersionOperator(items[0]) if len(items) > 1: res['tc_versop'] = ToolchainVersionOperator(items[1]) return res
def test_vop_test(self): """Test version checker""" vop = VersionOperator('1.2.3') self.assertTrue(vop.operator == vop.DEFAULT_UNDEFINED_OPERATOR) vop = VersionOperator('>= 1.2.3') self.assertTrue(vop.test('1.2.3')) # 1.2.3 >= 1.2.3: True self.assertFalse(vop.test('1.2.2')) # 1.2.2 >= 1.2.3 : False self.assertTrue(vop.test('1.2.4')) # 1.2.4 >= 1.2.3 : True vop = VersionOperator('< 1.2.3') self.assertFalse(vop.test('1.2.3')) # 1.2.3 < 1.2.3: False self.assertTrue(vop.test('1.2.2')) # 1.2.2 < 1.2.3 : True self.assertFalse(vop.test('1.2.4')) # 1.2.4 < 1.2.3 : False self.assertFalse(vop.test('2a')) # 2a < 1.2.3 : False self.assertTrue(vop.test('1.1a')) # 1.1a < 1.2.3 : True self.assertFalse(vop.test('1a')) # 1a < 1.2.3 : False (beware!) self.assertFalse( vop.test('1.2.3dev')) # 1.2.3dev < 1.2.3 : False (beware!)
def test_vop_test(self): """Test version checker""" vop = VersionOperator('1.2.3') self.assertTrue(vop.operator == vop.DEFAULT_UNDEFINED_OPERATOR) vop = VersionOperator('>= 1.2.3') self.assertTrue(vop.test('1.2.3')) # 1.2.3 >= 1.2.3: True self.assertFalse(vop.test('1.2.2')) # 1.2.2 >= 1.2.3 : False self.assertTrue(vop.test('1.2.4')) # 1.2.4 >= 1.2.3 : True vop = VersionOperator('< 1.2.3') self.assertFalse(vop.test('1.2.3')) # 1.2.3 < 1.2.3: False self.assertTrue(vop.test('1.2.2')) # 1.2.2 < 1.2.3 : True self.assertFalse(vop.test('1.2.4')) # 1.2.4 < 1.2.3 : False self.assertFalse(vop.test('2a')) # 2a < 1.2.3 : False self.assertTrue(vop.test('1.1a')) # 1.1a < 1.2.3 : True self.assertFalse(vop.test('1a')) # 1a < 1.2.3 : False (beware!) self.assertFalse(vop.test('1.2.3dev')) # 1.2.3dev < 1.2.3 : False (beware!)
def test_boolean(self): """Test boolean test""" self.assertTrue(VersionOperator('>= 123')) self.assertTrue(VersionOperator('123')) self.assertFalse(VersionOperator('<='))