00001
00002
00003
00004
00005
00006 """Test the various functions from 'base'."""
00007
00008 from .compat import unittest, is_python2
00009
00010 from semantic_version import base
00011
00012 class ComparisonTestCase(unittest.TestCase):
00013 def test_identifier_cmp(self):
00014 cases = [
00015
00016 ('1', '1', 0),
00017 ('1', '2', -1),
00018 ('11', '2', 1),
00019 ('3333', '40', 1),
00020
00021
00022 ('aa', 'ab', -1),
00023 ('aa', 'aa', 0),
00024 ('ab', 'aa', 1),
00025 ('aaa', 'ab', -1),
00026
00027
00028 ('10', '1a', -1),
00029 ('1a', '10', 1),
00030 ('ab1', '42', 1),
00031 ]
00032
00033 for a, b, expected in cases:
00034 result = base.identifier_cmp(a, b)
00035 self.assertEqual(expected, result,
00036 "identifier_cmp(%r, %r) returned %d instead of %d" % (
00037 a, b, result, expected))
00038
00039 def test_identifier_list_cmp(self):
00040 cases = [
00041
00042 (['1', '2', '3'], ['1', '2', '3'], 0),
00043 (['1', '2', '3'], ['1', '3', '2'], -1),
00044 (['1', '2', '4'], ['1', '2', '3'], 1),
00045
00046
00047 (['1', 'a'], ['1', 'a', '0'], -1),
00048 (['1', 'a', '0'], ['1', 'a'], 1),
00049 (['1', 'b'], ['1', 'a', '1000'], 1),
00050 ]
00051
00052 for a, b, expected in cases:
00053 result = base.identifier_list_cmp(a, b)
00054 self.assertEqual(expected, result,
00055 "identifier_list_cmp(%r, %r) returned %d instead of %d" % (
00056 a, b, result, expected))
00057
00058
00059 class TopLevelTestCase(unittest.TestCase):
00060 """Test module-level functions."""
00061
00062 versions = (
00063 ('0.1.0', '0.1.1', -1),
00064 ('0.1.1', '0.1.1', 0),
00065 ('0.1.1', '0.1.0', 1),
00066 ('0.1.0-alpha', '0.1.0', -1),
00067 ('0.1.0-alpha+2', '0.1.0-alpha', 1),
00068 )
00069
00070 def test_compare(self):
00071 for a, b, expected in self.versions:
00072 result = base.compare(a, b)
00073 self.assertEqual(expected, result,
00074 "compare(%r, %r) should be %r instead of %r" % (a, b, expected, result))
00075
00076 matches = (
00077 ('>=0.1.1', '0.1.2'),
00078 ('>=0.1.1', '0.1.1'),
00079 ('>=0.1.1', '0.1.1-alpha'),
00080 ('>=0.1.1,!=0.2.0', '0.2.1'),
00081 )
00082
00083 def test_match(self):
00084 for spec, version in self.matches:
00085 self.assertTrue(base.match(spec, version),
00086 "%r should accept %r" % (spec, version))
00087
00088 valid_strings = (
00089 '1.0.0-alpha',
00090 '1.0.0-alpha.1',
00091 '1.0.0-beta.2',
00092 '1.0.0-beta.11',
00093 '1.0.0-rc.1',
00094 '1.0.0-rc.1+build.1',
00095 '1.0.0',
00096 '1.0.0+0.3.7',
00097 '1.3.7+build',
00098 '1.3.7+build.2.b8f12d7',
00099 '1.3.7+build.11.e0f985a',
00100 '1.1.1',
00101 '1.1.2',
00102 '1.1.3-rc4.5',
00103 '1.1.3-rc42.3-14-15.24+build.2012-04-13.223',
00104 '1.1.3+build.2012-04-13.HUY.alpha-12.1',
00105 )
00106
00107 def test_validate_valid(self):
00108 for version in self.valid_strings:
00109 self.assertTrue(base.validate(version),
00110 "%r should be a valid version" % (version,))
00111
00112 invalid_strings = (
00113 '1',
00114 'v1',
00115 '1.2.3.4',
00116 '1.2',
00117 '1.2a3',
00118 '1.2.3a4',
00119 'v12.34.5',
00120 '1.2.3+4+5',
00121 )
00122
00123 def test_validate_invalid(self):
00124 for version in self.invalid_strings:
00125 self.assertFalse(base.validate(version),
00126 "%r should not be a valid version" % (version,))
00127
00128
00129 class VersionTestCase(unittest.TestCase):
00130 versions = {
00131 '1.0.0-alpha': (1, 0, 0, ('alpha',), ()),
00132 '1.0.0-alpha.1': (1, 0, 0, ('alpha', '1'), ()),
00133 '1.0.0-beta.2': (1, 0, 0, ('beta', '2'), ()),
00134 '1.0.0-beta.11': (1, 0, 0, ('beta', '11'), ()),
00135 '1.0.0-rc.1': (1, 0, 0, ('rc', '1'), ()),
00136 '1.0.0-rc.1+build.1': (1, 0, 0, ('rc', '1'), ('build', '1')),
00137 '1.0.0': (1, 0, 0, (), ()),
00138 '1.0.0+0.3.7': (1, 0, 0, (), ('0', '3', '7')),
00139 '1.3.7+build': (1, 3, 7, (), ('build',)),
00140 '1.3.7+build.2.b8f12d7': (1, 3, 7, (), ('build', '2', 'b8f12d7')),
00141 '1.3.7+build.11.e0f985a': (1, 3, 7, (), ('build', '11', 'e0f985a')),
00142 '1.1.1': (1, 1, 1, (), ()),
00143 '1.1.2': (1, 1, 2, (), ()),
00144 '1.1.3-rc4.5': (1, 1, 3, ('rc4', '5'), ()),
00145 '1.1.3-rc42.3-14-15.24+build.2012-04-13.223':
00146 (1, 1, 3, ('rc42', '3-14-15', '24'), ('build', '2012-04-13', '223')),
00147 '1.1.3+build.2012-04-13.HUY.alpha-12.1':
00148 (1, 1, 3, (), ('build', '2012-04-13', 'HUY', 'alpha-12', '1')),
00149 }
00150
00151 def test_parsing(self):
00152 for text, expected_fields in self.versions.items():
00153 version = base.Version(text)
00154 actual_fields = (version.major, version.minor, version.patch,
00155 version.prerelease, version.build)
00156 self.assertEqual(expected_fields, actual_fields)
00157
00158 def test_str(self):
00159 for text in self.versions:
00160 version = base.Version(text)
00161 self.assertEqual(text, str(version))
00162 self.assertEqual("Version('%s')" % text, repr(version))
00163
00164 def test_compare_to_self(self):
00165 for text in self.versions:
00166 self.assertEqual(base.Version(text), base.Version(text))
00167 self.assertNotEqual(text, base.Version(text))
00168
00169 partial_versions = {
00170 '1.1': (1, 1, None, None, None),
00171 '2': (2, None, None, None, None),
00172 '1.0.0-alpha': (1, 0, 0, ('alpha',), None),
00173 '1.0.0-alpha.1': (1, 0, 0, ('alpha', '1'), None),
00174 '1.0.0-beta.2': (1, 0, 0, ('beta', '2'), None),
00175 '1.0.0-beta.11': (1, 0, 0, ('beta', '11'), None),
00176 '1.0.0-rc.1': (1, 0, 0, ('rc', '1'), None),
00177 '1.0.0': (1, 0, 0, None, None),
00178 '1.1.1': (1, 1, 1, None, None),
00179 '1.1.2': (1, 1, 2, None, None),
00180 '1.1.3-rc4.5': (1, 1, 3, ('rc4', '5'), None),
00181 '1.0.0-': (1, 0, 0, (), None),
00182 '1.0.0+': (1, 0, 0, (), ()),
00183 '1.0.0-rc.1+build.1': (1, 0, 0, ('rc', '1'), ('build', '1')),
00184 '1.0.0+0.3.7': (1, 0, 0, (), ('0', '3', '7')),
00185 '1.3.7+build': (1, 3, 7, (), ('build',)),
00186 '1.3.7+build.2.b8f12d7': (1, 3, 7, (), ('build', '2', 'b8f12d7')),
00187 '1.3.7+build.11.e0f985a': (1, 3, 7, (), ('build', '11', 'e0f985a')),
00188 '1.1.3-rc42.3-14-15.24+build.2012-04-13.223':
00189 (1, 1, 3, ('rc42', '3-14-15', '24'), ('build', '2012-04-13', '223')),
00190 '1.1.3+build.2012-04-13.HUY.alpha-12.1':
00191 (1, 1, 3, (), ('build', '2012-04-13', 'HUY', 'alpha-12', '1')),
00192 }
00193
00194 def test_parsing_partials(self):
00195 for text, expected_fields in self.partial_versions.items():
00196 version = base.Version(text, partial=True)
00197 actual_fields = (version.major, version.minor, version.patch,
00198 version.prerelease, version.build)
00199 self.assertEqual(expected_fields, actual_fields)
00200 self.assertTrue(version.partial, "%r should have partial=True" % version)
00201
00202 def test_str_partials(self):
00203 for text in self.partial_versions:
00204 version = base.Version(text, partial=True)
00205 self.assertEqual(text, str(version))
00206 self.assertEqual("Version('%s', partial=True)" % text, repr(version))
00207
00208 def test_compare_partial_to_self(self):
00209 for text in self.partial_versions:
00210 self.assertEqual(
00211 base.Version(text, partial=True),
00212 base.Version(text, partial=True))
00213 self.assertNotEqual(text, base.Version(text, partial=True))
00214
00215 def test_hash(self):
00216 self.assertEqual(1,
00217 len(set([base.Version('0.1.0'), base.Version('0.1.0')])))
00218
00219 self.assertEqual(2,
00220 len(set([base.Version('0.1.0'), base.Version('0.1.0', partial=True)])))
00221
00222
00223 self.assertEqual(1,
00224 len(set([
00225 base.Version('0.1.0-a1+34'),
00226 base.Version('0.1.0-a1+34', partial=True)
00227 ]))
00228 )
00229
00230 @unittest.skipIf(is_python2, "Comparisons to other objects are broken in Py2.")
00231 def test_invalid_comparisons(self):
00232 v = base.Version('0.1.0')
00233 with self.assertRaises(TypeError):
00234 v < '0.1.0'
00235 with self.assertRaises(TypeError):
00236 v <= '0.1.0'
00237 with self.assertRaises(TypeError):
00238 v > '0.1.0'
00239 with self.assertRaises(TypeError):
00240 v >= '0.1.0'
00241
00242 self.assertTrue(v != '0.1.0')
00243 self.assertFalse(v == '0.1.0')
00244
00245
00246 class SpecItemTestCase(unittest.TestCase):
00247 components = {
00248 '==0.1.0': (base.SpecItem.KIND_EQUAL, 0, 1, 0, None, None),
00249 '==0.1.2-rc3': (base.SpecItem.KIND_EQUAL, 0, 1, 2, ('rc3',), None),
00250 '==0.1.2+build3.14': (base.SpecItem.KIND_EQUAL, 0, 1, 2, (), ('build3', '14')),
00251 '<=0.1.1+': (base.SpecItem.KIND_LTE, 0, 1, 1, (), ()),
00252 '<0.1.1': (base.SpecItem.KIND_LT, 0, 1, 1, None, None),
00253 '<=0.1.1': (base.SpecItem.KIND_LTE, 0, 1, 1, None, None),
00254 '<=0.1.1-': (base.SpecItem.KIND_LTE, 0, 1, 1, (), None),
00255 '>=0.2.3-rc2': (base.SpecItem.KIND_GTE, 0, 2, 3, ('rc2',), None),
00256 '>0.2.3-rc2+': (base.SpecItem.KIND_GT, 0, 2, 3, ('rc2',), ()),
00257 '>=2.0.0': (base.SpecItem.KIND_GTE, 2, 0, 0, None, None),
00258 '!=0.1.1+': (base.SpecItem.KIND_NEQ, 0, 1, 1, (), ()),
00259 '!=0.3.0': (base.SpecItem.KIND_NEQ, 0, 3, 0, None, None),
00260 }
00261
00262 def test_components(self):
00263 for spec_text, components in self.components.items():
00264 kind, major, minor, patch, prerelease, build = components
00265 spec = base.SpecItem(spec_text)
00266
00267 self.assertEqual(kind, spec.kind)
00268 self.assertEqual(major, spec.spec.major)
00269 self.assertEqual(minor, spec.spec.minor)
00270 self.assertEqual(patch, spec.spec.patch)
00271 self.assertEqual(prerelease, spec.spec.prerelease)
00272 self.assertEqual(build, spec.spec.build)
00273
00274 self.assertNotEqual(spec, spec_text)
00275 self.assertEqual(spec_text, str(spec))
00276
00277 matches = {
00278 '==0.1.0': (
00279 ['0.1.0', '0.1.0-rc1', '0.1.0+build1', '0.1.0-rc1+build2'],
00280 ['0.0.1', '0.2.0', '0.1.1'],
00281 ),
00282 '==0.1.2-rc3': (
00283 ['0.1.2-rc3+build1', '0.1.2-rc3+build4.5'],
00284 ['0.1.2-rc4', '0.1.2', '0.1.3'],
00285 ),
00286 '==0.1.2+build3.14': (
00287 ['0.1.2+build3.14'],
00288 ['0.1.2-rc+build3.14', '0.1.2+build3.15'],
00289 ),
00290 '<=0.1.1': (
00291 ['0.0.0', '0.1.1-alpha1', '0.1.1', '0.1.1+build2'],
00292 ['0.1.2'],
00293 ),
00294 '<0.1.1': (
00295 ['0.1.0', '0.0.0'],
00296 ['0.1.1', '0.1.1-zzz+999', '1.2.0', '0.1.1+build3'],
00297 ),
00298 '<=0.1.1': (
00299 ['0.1.1+build4', '0.1.1-alpha', '0.1.0'],
00300 ['0.2.3', '1.1.1', '0.1.2'],
00301 ),
00302 '<0.1.1-': (
00303 ['0.1.0', '0.1.1-alpha', '0.1.1-alpha+4'],
00304 ['0.2.0', '1.0.0', '0.1.1', '0.1.1+build1'],
00305 ),
00306 '>=0.2.3-rc2': (
00307 ['0.2.3-rc3', '0.2.3', '0.2.3+1', '0.2.3-rc2', '0.2.3-rc2+1'],
00308 ['0.2.3-rc1', '0.2.2'],
00309 ),
00310 '>0.2.3-rc2+': (
00311 ['0.2.3-rc3', '0.2.3', '0.2.3-rc2+1'],
00312 ['0.2.3-rc1', '0.2.2', '0.2.3-rc2'],
00313 ),
00314 '>2.0.0+': (
00315 ['2.1.1', '2.0.0+b1', '3.1.4'],
00316 ['1.9.9', '1.9.9999', '2.0.0', '2.0.0-rc4'],
00317 ),
00318 '!=0.1.1': (
00319 ['0.1.2', '0.1.0', '1.4.2'],
00320 ['0.1.1', '0.1.1-alpha', '0.1.1+b1'],
00321 ),
00322 '!=0.3.4-': (
00323 ['0.4.0', '1.3.0', '0.3.4-alpha', '0.3.4-alpha+b1'],
00324 ['0.3.4', '0.3.4+b1'],
00325 ),
00326 }
00327
00328 def test_matches(self):
00329 for spec_text, versions in self.matches.items():
00330 spec = base.SpecItem(spec_text)
00331 matching, failing = versions
00332
00333 for version_text in matching:
00334 version = base.Version(version_text)
00335 self.assertTrue(spec.match(version), "%r should match %r" % (version, spec))
00336
00337 for version_text in failing:
00338 version = base.Version(version_text)
00339 self.assertFalse(spec.match(version),
00340 "%r should not match %r" % (version, spec))
00341
00342 def test_equality(self):
00343 spec1 = base.SpecItem('==0.1.0')
00344 spec2 = base.SpecItem('==0.1.0')
00345 self.assertEqual(spec1, spec2)
00346 self.assertFalse(spec1 == '==0.1.0')
00347
00348 def test_to_string(self):
00349 spec = base.SpecItem('==0.1.0')
00350 self.assertEqual('==0.1.0', str(spec))
00351 self.assertEqual(base.SpecItem.KIND_EQUAL, spec.kind)
00352
00353 def test_hash(self):
00354 self.assertEqual(1,
00355 len(set([base.SpecItem('==0.1.0'), base.SpecItem('==0.1.0')])))
00356
00357
00358 class CoerceTestCase(unittest.TestCase):
00359 examples = {
00360
00361 '0.0.0': ('0', '0.0', '0.0.0', '0.0.0+', '0-'),
00362 '0.1.0': ('0.1', '0.1+', '0.1-', '0.1.0'),
00363 '0.1.0+2': ('0.1.0+2', '0.1.0.2'),
00364 '0.1.0+2.3.4': ('0.1.0+2.3.4', '0.1.0+2+3+4', '0.1.0.2+3+4'),
00365 '0.1.0+2-3.4': ('0.1.0+2-3.4', '0.1.0+2-3+4', '0.1.0.2-3+4', '0.1.0.2_3+4'),
00366 '0.1.0-a2.3': ('0.1.0-a2.3', '0.1.0a2.3', '0.1.0_a2.3'),
00367 '0.1.0-a2.3+4.5-6': ('0.1.0-a2.3+4.5-6', '0.1.0a2.3+4.5-6', '0.1.0a2.3+4.5_6', '0.1.0a2.3+4+5/6'),
00368 }
00369
00370 def test_coerce(self):
00371 for equivalent, samples in self.examples.items():
00372 target = base.Version(equivalent)
00373 for sample in samples:
00374 v_sample = base.Version.coerce(sample)
00375 self.assertEqual(target, v_sample)
00376
00377 def test_invalid(self):
00378 self.assertRaises(ValueError, base.Version.coerce, 'v1')
00379
00380
00381 class SpecTestCase(unittest.TestCase):
00382 examples = {
00383 '>=0.1.1,<0.1.2': ['>=0.1.1', '<0.1.2'],
00384 '>=0.1.0,!=0.1.3-rc1,<0.1.3': ['>=0.1.0', '!=0.1.3-rc1', '<0.1.3'],
00385 }
00386
00387 def test_parsing(self):
00388 for spec_list_text, specs in self.examples.items():
00389 spec_list = base.Spec(spec_list_text)
00390
00391 self.assertEqual(spec_list_text, str(spec_list))
00392 self.assertNotEqual(spec_list_text, spec_list)
00393 self.assertEqual(specs, [str(spec) for spec in spec_list])
00394
00395 for spec_text in specs:
00396 self.assertTrue(repr(base.SpecItem(spec_text)) in repr(spec_list))
00397
00398 split_examples = {
00399 ('>=0.1.1', '<0.1.2', '!=0.1.1+build1'): ['>=0.1.1', '<0.1.2', '!=0.1.1+build1'],
00400 ('>=0.1.0', '!=0.1.3-rc1,<0.1.3'): ['>=0.1.0', '!=0.1.3-rc1', '<0.1.3'],
00401 }
00402
00403 def test_parsing_split(self):
00404 for spec_list_texts, specs in self.split_examples.items():
00405 spec_list = base.Spec(*spec_list_texts)
00406
00407 self.assertEqual(','.join(spec_list_texts), str(spec_list))
00408 self.assertEqual(specs, [str(spec) for spec in spec_list])
00409 self.assertEqual(spec_list, base.Spec(','.join(spec_list_texts)))
00410
00411 for spec_text in specs:
00412 self.assertTrue(repr(base.SpecItem(spec_text)) in repr(spec_list))
00413
00414 matches = {
00415 '>=0.1.1,<0.1.2': (
00416 ['0.1.1', '0.1.1+4', '0.1.1-alpha'],
00417 ['0.1.2-alpha', '0.1.2', '1.3.4'],
00418 ),
00419 '>=0.1.0+,!=0.1.3-rc1,<0.1.4': (
00420 ['0.1.1', '0.1.0+b4', '0.1.2', '0.1.3-rc2'],
00421 ['0.0.1', '0.1.4', '0.1.4-alpha', '0.1.3-rc1+4',
00422 '0.1.0-alpha', '0.2.2', '0.1.4-rc1'],
00423 ),
00424 }
00425
00426 def test_matches(self):
00427 for spec_list_text, versions in self.matches.items():
00428 spec_list = base.Spec(spec_list_text)
00429 matching, failing = versions
00430
00431 for version_text in matching:
00432 version = base.Version(version_text)
00433 self.assertTrue(version in spec_list,
00434 "%r should be in %r" % (version, spec_list))
00435 self.assertTrue(spec_list.match(version),
00436 "%r should match %r" % (version, spec_list))
00437
00438 for version_text in failing:
00439 version = base.Version(version_text)
00440 self.assertFalse(version in spec_list,
00441 "%r should not be in %r" % (version, spec_list))
00442 self.assertFalse(spec_list.match(version),
00443 "%r should not match %r" % (version, spec_list))
00444
00445 def test_equality(self):
00446 for spec_list_text in self.examples:
00447 slist1 = base.Spec(spec_list_text)
00448 slist2 = base.Spec(spec_list_text)
00449 self.assertEqual(slist1, slist2)
00450 self.assertFalse(slist1 == spec_list_text)
00451
00452 def test_filter_empty(self):
00453 s = base.Spec('>=0.1.1')
00454 res = tuple(s.filter(()))
00455 self.assertEqual((), res)
00456
00457 def test_filter_incompatible(self):
00458 s = base.Spec('>=0.1.1,!=0.1.4')
00459 res = tuple(s.filter([
00460 base.Version('0.1.0'),
00461 base.Version('0.1.4'),
00462 base.Version('0.1.4-alpha'),
00463 ]))
00464 self.assertEqual((), res)
00465
00466 def test_filter_compatible(self):
00467 s = base.Spec('>=0.1.1,!=0.1.4,<0.2.0')
00468 res = tuple(s.filter([
00469 base.Version('0.1.0'),
00470 base.Version('0.1.1'),
00471 base.Version('0.1.5'),
00472 base.Version('0.1.4-alpha'),
00473 base.Version('0.1.2'),
00474 base.Version('0.2.0-rc1'),
00475 base.Version('3.14.15'),
00476 ]))
00477
00478 expected = (
00479 base.Version('0.1.1'),
00480 base.Version('0.1.5'),
00481 base.Version('0.1.2'),
00482 )
00483
00484 self.assertEqual(expected, res)
00485
00486 def test_select_empty(self):
00487 s = base.Spec('>=0.1.1')
00488 self.assertIsNone(s.select(()))
00489
00490 def test_select_incompatible(self):
00491 s = base.Spec('>=0.1.1,!=0.1.4')
00492 res = s.select([
00493 base.Version('0.1.0'),
00494 base.Version('0.1.4'),
00495 base.Version('0.1.4-alpha'),
00496 ])
00497 self.assertIsNone(res)
00498
00499 def test_select_compatible(self):
00500 s = base.Spec('>=0.1.1,!=0.1.4,<0.2.0')
00501 res = s.select([
00502 base.Version('0.1.0'),
00503 base.Version('0.1.1'),
00504 base.Version('0.1.5'),
00505 base.Version('0.1.4-alpha'),
00506 base.Version('0.1.2'),
00507 base.Version('0.2.0-rc1'),
00508 base.Version('3.14.15'),
00509 ])
00510
00511 self.assertEqual(base.Version('0.1.5'), res)
00512
00513 def test_contains(self):
00514 self.assertFalse('ii' in base.Spec('>=0.1.1'))
00515
00516 def test_hash(self):
00517 self.assertEqual(1,
00518 len(set([base.Spec('>=0.1.1'), base.Spec('>=0.1.1')])))
00519
00520
00521 if __name__ == '__main__':
00522 unittest.main()