1# Copyright (c) Twisted Matrix Laboratories.
2# See LICENSE for details.
3
4"""
5Tests for L{incremental}.
6"""
7
8from __future__ import division, absolute_import
9
10import operator
11
12from incremental import getVersionString, IncomparableVersions
13from incremental import Version, _inf
14
15from twisted.trial.unittest import TestCase
16
17
18class VersionsTests(TestCase):
19    def test_localIsShort(self):
20        """
21        The local version is the same as the short version.
22        """
23        va = Version("dummy", 1, 0, 0, release_candidate=1, post=2, dev=3)
24        self.assertEqual(va.local(), va.short())
25
26    def test_versionComparison(self):
27        """
28        Versions can be compared for equality and order.
29        """
30        va = Version("dummy", 1, 0, 0)
31        vb = Version("dummy", 0, 1, 0)
32        self.assertTrue(va > vb)
33        self.assertTrue(vb < va)
34        self.assertTrue(va >= vb)
35        self.assertTrue(vb <= va)
36        self.assertTrue(va != vb)
37        self.assertTrue(vb == Version("dummy", 0, 1, 0))
38        self.assertTrue(vb == vb)
39
40    def test_versionComparisonCaseInsensitive(self):
41        """
42        Version package names are case insensitive.
43        """
44        va = Version("dummy", 1, 0, 0)
45        vb = Version("DuMmY", 0, 1, 0)
46        self.assertTrue(va > vb)
47        self.assertTrue(vb < va)
48        self.assertTrue(va >= vb)
49        self.assertTrue(vb <= va)
50        self.assertTrue(va != vb)
51        self.assertTrue(vb == Version("dummy", 0, 1, 0))
52        self.assertTrue(vb == vb)
53
54    def test_comparingNEXTReleases(self):
55        """
56        NEXT releases are always larger than numbered releases.
57        """
58        va = Version("whatever", "NEXT", 0, 0)
59        vb = Version("whatever", 1, 0, 0)
60        self.assertTrue(va > vb)
61        self.assertFalse(va < vb)
62        self.assertNotEquals(vb, va)
63
64    def test_NEXTMustBeAlone(self):
65        """
66        NEXT releases must always have the rest of the numbers set to 0.
67        """
68        with self.assertRaises(ValueError):
69            Version("whatever", "NEXT", 1, 0, release_candidate=0, post=0, dev=0)
70
71        with self.assertRaises(ValueError):
72            Version("whatever", "NEXT", 0, 1, release_candidate=0, post=0, dev=0)
73
74        with self.assertRaises(ValueError):
75            Version("whatever", "NEXT", 0, 0, release_candidate=1, post=0, dev=0)
76
77        with self.assertRaises(ValueError):
78            Version("whatever", "NEXT", 0, 0, release_candidate=0, post=1, dev=0)
79
80        with self.assertRaises(ValueError):
81            Version("whatever", "NEXT", 0, 0, release_candidate=0, post=0, dev=1)
82
83    def test_comparingNEXTReleasesEqual(self):
84        """
85        NEXT releases are equal to each other.
86        """
87        va = Version("whatever", "NEXT", 0, 0)
88        vb = Version("whatever", "NEXT", 0, 0)
89        self.assertEquals(vb, va)
90
91    def test_comparingPrereleasesWithReleases(self):
92        """
93        Prereleases are always less than versions without prereleases.
94        """
95        va = Version("whatever", 1, 0, 0, prerelease=1)
96        vb = Version("whatever", 1, 0, 0)
97        self.assertTrue(va < vb)
98        self.assertFalse(va > vb)
99        self.assertNotEquals(vb, va)
100
101    def test_prereleaseDeprecated(self):
102        """
103        Passing 'prerelease' to Version is deprecated.
104        """
105        Version("whatever", 1, 0, 0, prerelease=1)
106        warnings = self.flushWarnings([self.test_prereleaseDeprecated])
107        self.assertEqual(len(warnings), 1)
108        self.assertEqual(
109            warnings[0]["message"],
110            (
111                "Passing prerelease to incremental.Version was deprecated in "
112                "Incremental 16.9.0. Please pass release_candidate instead."
113            ),
114        )
115
116    def test_prereleaseAttributeDeprecated(self):
117        """
118        Accessing 'prerelease' on a Version is deprecated.
119        """
120        va = Version("whatever", 1, 0, 0, release_candidate=1)
121        va.prerelease
122        warnings = self.flushWarnings([self.test_prereleaseAttributeDeprecated])
123        self.assertEqual(len(warnings), 1)
124        self.assertEqual(
125            warnings[0]["message"],
126            (
127                "Accessing incremental.Version.prerelease was deprecated in "
128                "Incremental 16.9.0. Use Version.release_candidate instead."
129            ),
130        )
131
132    def test_comparingReleaseCandidatesWithReleases(self):
133        """
134        Release Candidates are always less than versions without release
135        candidates.
136        """
137        va = Version("whatever", 1, 0, 0, release_candidate=1)
138        vb = Version("whatever", 1, 0, 0)
139        self.assertTrue(va < vb)
140        self.assertFalse(va > vb)
141        self.assertNotEquals(vb, va)
142
143    def test_comparingPostReleasesWithReleases(self):
144        """
145        Post releases are always greater than versions without post
146        releases.
147        """
148        va = Version("whatever", 1, 0, 0, post=1)
149        vb = Version("whatever", 1, 0, 0)
150        self.assertTrue(va > vb)
151        self.assertFalse(va < vb)
152        self.assertNotEquals(vb, va)
153
154    def test_comparingDevReleasesWithPreviousPostReleases(self):
155        """
156        Dev releases are always greater than postreleases based on previous
157        releases.
158        """
159        va = Version("whatever", 1, 0, 1, dev=1)
160        vb = Version("whatever", 1, 0, 0, post=1)
161        self.assertTrue(va > vb)
162        self.assertFalse(va < vb)
163        self.assertNotEquals(vb, va)
164
165    def test_comparingDevReleasesWithReleases(self):
166        """
167        Dev releases are always less than versions without dev releases.
168        """
169        va = Version("whatever", 1, 0, 0, dev=1)
170        vb = Version("whatever", 1, 0, 0)
171        self.assertTrue(va < vb)
172        self.assertFalse(va > vb)
173        self.assertNotEquals(vb, va)
174
175    def test_rcEqualspre(self):
176        """
177        Release Candidates are equal to prereleases.
178        """
179        va = Version("whatever", 1, 0, 0, release_candidate=1)
180        vb = Version("whatever", 1, 0, 0, prerelease=1)
181        self.assertTrue(va == vb)
182        self.assertFalse(va != vb)
183
184    def test_rcOrpreButNotBoth(self):
185        """
186        Release Candidate and prerelease can't both be given.
187        """
188        with self.assertRaises(ValueError):
189            Version("whatever", 1, 0, 0, prerelease=1, release_candidate=1)
190
191    def test_comparingReleaseCandidates(self):
192        """
193        The value specified as the release candidate is used in version
194        comparisons.
195        """
196        va = Version("whatever", 1, 0, 0, release_candidate=1)
197        vb = Version("whatever", 1, 0, 0, release_candidate=2)
198        self.assertTrue(va < vb)
199        self.assertTrue(vb > va)
200        self.assertTrue(va <= vb)
201        self.assertTrue(vb >= va)
202        self.assertTrue(va != vb)
203        self.assertTrue(vb == Version("whatever", 1, 0, 0, release_candidate=2))
204        self.assertTrue(va == va)
205
206    def test_comparingPost(self):
207        """
208        The value specified as the postrelease is used in version comparisons.
209        """
210        va = Version("whatever", 1, 0, 0, post=1)
211        vb = Version("whatever", 1, 0, 0, post=2)
212        self.assertTrue(va < vb)
213        self.assertTrue(vb > va)
214        self.assertTrue(va <= vb)
215        self.assertTrue(vb >= va)
216        self.assertTrue(va != vb)
217        self.assertTrue(vb == Version("whatever", 1, 0, 0, post=2))
218        self.assertTrue(va == va)
219
220    def test_comparingDev(self):
221        """
222        The value specified as the dev release is used in version comparisons.
223        """
224        va = Version("whatever", 1, 0, 0, dev=1)
225        vb = Version("whatever", 1, 0, 0, dev=2)
226        self.assertTrue(va < vb)
227        self.assertTrue(vb > va)
228        self.assertTrue(va <= vb)
229        self.assertTrue(vb >= va)
230        self.assertTrue(va != vb)
231        self.assertTrue(vb == Version("whatever", 1, 0, 0, dev=2))
232        self.assertTrue(va == va)
233
234    def test_comparingDevAndRC(self):
235        """
236        The value specified as the dev release and release candidate is used in
237        version comparisons.
238        """
239        va = Version("whatever", 1, 0, 0, release_candidate=1, dev=1)
240        vb = Version("whatever", 1, 0, 0, release_candidate=1, dev=2)
241        self.assertTrue(va < vb)
242        self.assertTrue(vb > va)
243        self.assertTrue(va <= vb)
244        self.assertTrue(vb >= va)
245        self.assertTrue(va != vb)
246        self.assertTrue(vb == Version("whatever", 1, 0, 0, release_candidate=1, dev=2))
247        self.assertTrue(va == va)
248
249    def test_comparingDevAndRCDifferent(self):
250        """
251        The value specified as the dev release and release candidate is used in
252        version comparisons.
253        """
254        va = Version("whatever", 1, 0, 0, release_candidate=1, dev=1)
255        vb = Version("whatever", 1, 0, 0, release_candidate=2, dev=1)
256        self.assertTrue(va < vb)
257        self.assertTrue(vb > va)
258        self.assertTrue(va <= vb)
259        self.assertTrue(vb >= va)
260        self.assertTrue(va != vb)
261        self.assertTrue(vb == Version("whatever", 1, 0, 0, release_candidate=2, dev=1))
262        self.assertTrue(va == va)
263
264    def test_infComparison(self):
265        """
266        L{_inf} is equal to L{_inf}.
267
268        This is a regression test.
269        """
270        self.assertEqual(_inf, _inf)
271
272    def test_disallowBuggyComparisons(self):
273        """
274        The package names of the Version objects need to be the same.
275        """
276        self.assertRaises(
277            IncomparableVersions,
278            operator.eq,
279            Version("dummy", 1, 0, 0),
280            Version("dumym", 1, 0, 0),
281        )
282
283    def test_notImplementedComparisons(self):
284        """
285        Comparing a L{Version} to some other object type results in
286        C{NotImplemented}.
287        """
288        va = Version("dummy", 1, 0, 0)
289        vb = ("dummy", 1, 0, 0)  # a tuple is not a Version object
290        self.assertEqual(va.__cmp__(vb), NotImplemented)
291
292    def test_repr(self):
293        """
294        Calling C{repr} on a version returns a human-readable string
295        representation of the version.
296        """
297        self.assertEqual(repr(Version("dummy", 1, 2, 3)), "Version('dummy', 1, 2, 3)")
298
299    def test_reprWithPrerelease(self):
300        """
301        Calling C{repr} on a version with a prerelease returns a human-readable
302        string representation of the version including the prerelease as a
303        release candidate..
304        """
305        self.assertEqual(
306            repr(Version("dummy", 1, 2, 3, prerelease=4)),
307            "Version('dummy', 1, 2, 3, release_candidate=4)",
308        )
309
310    def test_reprWithReleaseCandidate(self):
311        """
312        Calling C{repr} on a version with a release candidate returns a
313        human-readable string representation of the version including the rc.
314        """
315        self.assertEqual(
316            repr(Version("dummy", 1, 2, 3, release_candidate=4)),
317            "Version('dummy', 1, 2, 3, release_candidate=4)",
318        )
319
320    def test_reprWithPost(self):
321        """
322        Calling C{repr} on a version with a postrelease returns a
323        human-readable string representation of the version including the
324        postrelease.
325        """
326        self.assertEqual(
327            repr(Version("dummy", 1, 2, 3, post=4)), "Version('dummy', 1, 2, 3, post=4)"
328        )
329
330    def test_reprWithDev(self):
331        """
332        Calling C{repr} on a version with a dev release returns a
333        human-readable string representation of the version including the dev
334        release.
335        """
336        self.assertEqual(
337            repr(Version("dummy", 1, 2, 3, dev=4)), "Version('dummy', 1, 2, 3, dev=4)"
338        )
339
340    def test_str(self):
341        """
342        Calling C{str} on a version returns a human-readable string
343        representation of the version.
344        """
345        self.assertEqual(str(Version("dummy", 1, 2, 3)), "[dummy, version 1.2.3]")
346
347    def test_strWithPrerelease(self):
348        """
349        Calling C{str} on a version with a prerelease includes the prerelease
350        as a release candidate.
351        """
352        self.assertEqual(
353            str(Version("dummy", 1, 0, 0, prerelease=1)), "[dummy, version 1.0.0.rc1]"
354        )
355
356    def test_strWithReleaseCandidate(self):
357        """
358        Calling C{str} on a version with a release candidate includes the
359        release candidate.
360        """
361        self.assertEqual(
362            str(Version("dummy", 1, 0, 0, release_candidate=1)),
363            "[dummy, version 1.0.0.rc1]",
364        )
365
366    def test_strWithPost(self):
367        """
368        Calling C{str} on a version with a postrelease includes the
369        postrelease.
370        """
371        self.assertEqual(
372            str(Version("dummy", 1, 0, 0, post=1)), "[dummy, version 1.0.0.post1]"
373        )
374
375    def test_strWithDevAndReleaseCandidate(self):
376        """
377        Calling C{str} on a version with a release candidate and dev release
378        includes the release candidate and the dev release.
379        """
380        self.assertEqual(
381            str(Version("dummy", 1, 0, 0, release_candidate=1, dev=2)),
382            "[dummy, version 1.0.0.rc1.dev2]",
383        )
384
385    def test_strWithDev(self):
386        """
387        Calling C{str} on a version with a dev release includes the dev
388        release.
389        """
390        self.assertEqual(
391            str(Version("dummy", 1, 0, 0, dev=1)), "[dummy, version 1.0.0.dev1]"
392        )
393
394    def test_strWithDevAndPost(self):
395        """
396        Calling C{str} on a version with a postrelease and dev release
397        includes the postrelease and the dev release.
398        """
399        self.assertEqual(
400            str(Version("dummy", 1, 0, 0, post=1, dev=2)),
401            "[dummy, version 1.0.0.post1.dev2]",
402        )
403
404    def testShort(self):
405        self.assertEqual(Version("dummy", 1, 2, 3).short(), "1.2.3")
406
407    def test_getVersionString(self):
408        """
409        L{getVersionString} returns a string with the package name and the
410        short version number.
411        """
412        self.assertEqual("Twisted 8.0.0", getVersionString(Version("Twisted", 8, 0, 0)))
413
414    def test_getVersionStringWithPrerelease(self):
415        """
416        L{getVersionString} includes the prerelease as a release candidate, if
417        any.
418        """
419        self.assertEqual(
420            getVersionString(Version("whatever", 8, 0, 0, prerelease=1)),
421            "whatever 8.0.0.rc1",
422        )
423
424    def test_getVersionStringWithReleaseCandidate(self):
425        """
426        L{getVersionString} includes the release candidate, if any.
427        """
428        self.assertEqual(
429            getVersionString(Version("whatever", 8, 0, 0, release_candidate=1)),
430            "whatever 8.0.0.rc1",
431        )
432
433    def test_getVersionStringWithPost(self):
434        """
435        L{getVersionString} includes the postrelease, if any.
436        """
437        self.assertEqual(
438            getVersionString(Version("whatever", 8, 0, 0, post=1)),
439            "whatever 8.0.0.post1",
440        )
441
442    def test_getVersionStringWithDev(self):
443        """
444        L{getVersionString} includes the dev release, if any.
445        """
446        self.assertEqual(
447            getVersionString(Version("whatever", 8, 0, 0, dev=1)), "whatever 8.0.0.dev1"
448        )
449
450    def test_getVersionStringWithDevAndRC(self):
451        """
452        L{getVersionString} includes the dev release and release candidate, if
453        any.
454        """
455        self.assertEqual(
456            getVersionString(Version("whatever", 8, 0, 0, release_candidate=2, dev=1)),
457            "whatever 8.0.0.rc2.dev1",
458        )
459
460    def test_getVersionStringWithDevAndPost(self):
461        """
462        L{getVersionString} includes the dev release and postrelease, if
463        any.
464        """
465        self.assertEqual(
466            getVersionString(Version("whatever", 8, 0, 0, post=2, dev=1)),
467            "whatever 8.0.0.post2.dev1",
468        )
469
470    def test_baseWithNEXT(self):
471        """
472        The C{base} method returns just "NEXT" when NEXT is the major version.
473        """
474        self.assertEqual(Version("foo", "NEXT", 0, 0).base(), "NEXT")
475
476    def test_base(self):
477        """
478        The C{base} method returns a very simple representation of the version.
479        """
480        self.assertEqual(Version("foo", 1, 0, 0).base(), "1.0.0")
481
482    def test_baseWithPrerelease(self):
483        """
484        The base version includes 'rcX' for versions with prereleases.
485        """
486        self.assertEqual(Version("foo", 1, 0, 0, prerelease=8).base(), "1.0.0.rc8")
487
488    def test_baseWithPost(self):
489        """
490        The base version includes 'postX' for versions with postreleases.
491        """
492        self.assertEqual(Version("foo", 1, 0, 0, post=8).base(), "1.0.0.post8")
493
494    def test_baseWithDev(self):
495        """
496        The base version includes 'devX' for versions with dev releases.
497        """
498        self.assertEqual(Version("foo", 1, 0, 0, dev=8).base(), "1.0.0.dev8")
499
500    def test_baseWithReleaseCandidate(self):
501        """
502        The base version includes 'rcX' for versions with prereleases.
503        """
504        self.assertEqual(
505            Version("foo", 1, 0, 0, release_candidate=8).base(), "1.0.0.rc8"
506        )
507
508    def test_baseWithDevAndRC(self):
509        """
510        The base version includes 'rcXdevX' for versions with dev releases and
511        a release candidate.
512        """
513        self.assertEqual(
514            Version("foo", 1, 0, 0, release_candidate=2, dev=8).base(), "1.0.0.rc2.dev8"
515        )
516
517    def test_baseWithDevAndPost(self):
518        """
519        The base version includes 'postXdevX' for versions with dev releases
520        and a postrelease.
521        """
522        self.assertEqual(
523            Version("foo", 1, 0, 0, post=2, dev=8).base(), "1.0.0.post2.dev8"
524        )
525