Ticket #1355: test-1355.darcs.patch

File test-1355.darcs.patch, 6.3 KB (added by davidsarah, at 2011-02-21T02:03:34Z)

Add unit tests for cross_check_pkg_resources_versus_import, and a regression test for ref #1355. This requires a little refactoring to make it testable.

Line 
11 patch for repository http://tahoe-lafs.org/source/tahoe-lafs/trunk:
2
3Mon Feb 21 01:58:17 GMT Standard Time 2011  david-sarah@jacaranda.org
4  * Add unit tests for cross_check_pkg_resources_versus_import, and a regression test for ref #1355. This requires a little refactoring to make it testable.
5
6New patches:
7
8[Add unit tests for cross_check_pkg_resources_versus_import, and a regression test for ref #1355. This requires a little refactoring to make it testable.
9david-sarah@jacaranda.org**20110221015817
10 Ignore-this: 51d181698f8c20d3aca58b057e9c475a
11] {
12hunk ./src/allmydata/__init__.py 254
13     import pkg_resources
14     from _auto_deps import install_requires
15 
16+    pkg_resources_vers_and_locs = dict([(p.project_name.lower(), (str(p.version), p.location))
17+                                        for p in pkg_resources.require(install_requires)])
18+
19+    return cross_check(pkg_resources_vers_and_locs, _vers_and_locs_list)
20+
21+
22+def cross_check(pkg_resources_vers_and_locs, imported_vers_and_locs_list):
23+    """This function returns a list of errors due to any failed cross-checks."""
24+
25     errors = []
26     not_pkg_resourceable = set(['sqlite3', 'python', 'platform', __appname__.lower()])
27     not_import_versionable = set(['zope.interface', 'mock', 'pyasn1'])
28hunk ./src/allmydata/__init__.py 268
29     ignorable = set(['argparse', 'pyutil', 'zbase32', 'distribute'])
30 
31-    pkg_resources_vers_and_locs = dict([(p.project_name.lower(), (str(p.version), p.location))
32-                                        for p in pkg_resources.require(install_requires)])
33-
34-    for name, (imp_ver, imp_loc, imp_comment) in _vers_and_locs_list:
35+    for name, (imp_ver, imp_loc, imp_comment) in imported_vers_and_locs_list:
36         name = name.lower()
37         if name not in not_pkg_resourceable:
38             if name not in pkg_resources_vers_and_locs:
39hunk ./src/allmydata/__init__.py 315
40                                               "by pkg_resources, but version %s (normalized to %s, from %r) by import."
41                                               % (name, pr_ver, str(pr_normver), pr_loc, imp_ver, str(imp_normver), imp_loc))
42 
43-    imported_packages = set([p.lower() for (p, _) in _vers_and_locs_list])
44+    imported_packages = set([p.lower() for (p, _) in imported_vers_and_locs_list])
45     for pr_name, (pr_ver, pr_loc) in pkg_resources_vers_and_locs.iteritems():
46         if pr_name not in imported_packages and pr_name not in ignorable:
47             errors.append("Warning: dependency %s (version %s) found by pkg_resources not found by import."
48hunk ./src/allmydata/test/test_version.py 4
49 
50 from twisted.trial import unittest
51 
52-from allmydata import check_requirement, PackagingError
53+from allmydata import check_requirement, cross_check, PackagingError
54 from allmydata.util.verlib import NormalizedVersion as V, \
55                                   IrrationalVersionError, \
56                                   suggest_normalized_version as suggest
57hunk ./src/allmydata/test/test_version.py 33
58         self.failUnlessRaises(ImportError, check_requirement,
59                               "foo >= 1.0", {"foo": (None, None, "foomodule")})
60 
61+    def test_cross_check_ticket_1355(self):
62+        # The bug in #1355 is triggered when a version string from either pkg_resources or import
63+        # is not parseable at all by normalized_version.
64+
65+        res = cross_check({"foo": ("unparseable", "")}, [("foo", ("1.0", "", None))])
66+        self.failUnlessEqual(len(res), 1)
67+        self.failUnlessIn("by pkg_resources could not be parsed", res[0])
68+
69+        res = cross_check({"foo": ("1.0", "")}, [("foo", ("unparseable", "", None))])
70+        self.failUnlessEqual(len(res), 1)
71+        self.failUnlessIn(") could not be parsed", res[0])
72+
73+    def test_cross_check(self):
74+        res = cross_check({}, [])
75+        self.failUnlessEqual(res, [])
76+
77+        res = cross_check({}, [("sqlite3", ("1.0", "", "blah"))])
78+        self.failUnlessEqual(res, [])
79+
80+        res = cross_check({"foo": ("unparseable", "")}, [])
81+        self.failUnlessEqual(len(res), 1)
82+        self.failUnlessIn("not found by import", res[0])
83+
84+        res = cross_check({"argparse": ("unparseable", "")}, [])
85+        self.failUnlessEqual(len(res), 0)
86+
87+        res = cross_check({}, [("foo", ("unparseable", "", None))])
88+        self.failUnlessEqual(len(res), 1)
89+        self.failUnlessIn("not found by pkg_resources", res[0])
90+
91+        res = cross_check({"distribute": ("1.0", "/somewhere")}, [("setuptools", ("2.0", "/somewhere", "distribute"))])
92+        self.failUnlessEqual(len(res), 0)
93+
94+        res = cross_check({"distribute": ("1.0", "/somewhere")}, [("setuptools", ("2.0", "/somewhere", None))])
95+        self.failUnlessEqual(len(res), 1)
96+        self.failUnlessIn("location mismatch", res[0])
97+
98+        res = cross_check({"distribute": ("1.0", "/somewhere")}, [("setuptools", ("2.0", "/somewhere_different", None))])
99+        self.failUnlessEqual(len(res), 1)
100+        self.failUnlessIn("location mismatch", res[0])
101+
102+        res = cross_check({"zope.interface": ("1.0", "")}, [("zope.interface", ("unknown", "", None))])
103+        self.failUnlessEqual(len(res), 0)
104+
105+        res = cross_check({"foo": ("1.0", "")}, [("foo", ("unknown", "", None))])
106+        self.failUnlessEqual(len(res), 1)
107+        self.failUnlessIn("could not find a version number", res[0])
108+
109+        # When pkg_resources and import both find a package, there is only a warning if both
110+        # the version and the path fail to match.
111+
112+        res = cross_check({"foo": ("1.0", "/somewhere")}, [("foo", ("2.0", "/somewhere", None))])
113+        self.failUnlessEqual(len(res), 0)
114+
115+        res = cross_check({"foo": ("1.0", "/somewhere")}, [("foo", ("1.0", "/somewhere_different", None))])
116+        self.failUnlessEqual(len(res), 0)
117+
118+        res = cross_check({"foo": ("1.0-r123", "/somewhere")}, [("foo", ("1.0.post123", "/somewhere_different", None))])
119+        self.failUnlessEqual(len(res), 0)
120+
121+        res = cross_check({"foo": ("1.0", "/somewhere")}, [("foo", ("2.0", "/somewhere_different", None))])
122+        self.failUnlessEqual(len(res), 1)
123+        self.failUnlessIn("but version '2.0'", res[0])
124+
125 
126 # based on https://bitbucket.org/tarek/distutilsversion/src/17df9a7d96ef/test_verlib.py
127 
128}
129
130Context:
131
132[TAG allmydata-tahoe-1.8.2
133warner@lothar.com**20110131020101]
134Patch bundle hash:
13563b353632f4e14321b0f14ce2568c156072624d9