Mercurial > repos > melissacline > ucsc_xena_platform
comparison python-daemon-2.0.5/test/test_metadata.py @ 33:7ceb967147c3
start xena with no gui
add library files
author | jingchunzhu <jingchunzhu@gmail.com> |
---|---|
date | Wed, 22 Jul 2015 13:24:44 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
32:63b1ba1e3424 | 33:7ceb967147c3 |
---|---|
1 # -*- coding: utf-8 -*- | |
2 # | |
3 # test/test_metadata.py | |
4 # Part of ‘python-daemon’, an implementation of PEP 3143. | |
5 # | |
6 # Copyright © 2008–2015 Ben Finney <ben+python@benfinney.id.au> | |
7 # | |
8 # This is free software: you may copy, modify, and/or distribute this work | |
9 # under the terms of the Apache License, version 2.0 as published by the | |
10 # Apache Software Foundation. | |
11 # No warranty expressed or implied. See the file ‘LICENSE.ASF-2’ for details. | |
12 | |
13 """ Unit test for ‘_metadata’ private module. | |
14 """ | |
15 | |
16 from __future__ import (absolute_import, unicode_literals) | |
17 | |
18 import sys | |
19 import errno | |
20 import re | |
21 try: | |
22 # Python 3 standard library. | |
23 import urllib.parse as urlparse | |
24 except ImportError: | |
25 # Python 2 standard library. | |
26 import urlparse | |
27 import functools | |
28 import collections | |
29 import json | |
30 | |
31 import pkg_resources | |
32 import mock | |
33 import testtools.helpers | |
34 import testtools.matchers | |
35 import testscenarios | |
36 | |
37 from . import scaffold | |
38 from .scaffold import (basestring, unicode) | |
39 | |
40 import daemon._metadata as metadata | |
41 | |
42 | |
43 class HasAttribute(testtools.matchers.Matcher): | |
44 """ A matcher to assert an object has a named attribute. """ | |
45 | |
46 def __init__(self, name): | |
47 self.attribute_name = name | |
48 | |
49 def match(self, instance): | |
50 """ Assert the object `instance` has an attribute named `name`. """ | |
51 result = None | |
52 if not testtools.helpers.safe_hasattr(instance, self.attribute_name): | |
53 result = AttributeNotFoundMismatch(instance, self.attribute_name) | |
54 return result | |
55 | |
56 | |
57 class AttributeNotFoundMismatch(testtools.matchers.Mismatch): | |
58 """ The specified instance does not have the named attribute. """ | |
59 | |
60 def __init__(self, instance, name): | |
61 self.instance = instance | |
62 self.attribute_name = name | |
63 | |
64 def describe(self): | |
65 """ Emit a text description of this mismatch. """ | |
66 text = ( | |
67 "{instance!r}" | |
68 " has no attribute named {name!r}").format( | |
69 instance=self.instance, name=self.attribute_name) | |
70 return text | |
71 | |
72 | |
73 class metadata_value_TestCase(scaffold.TestCaseWithScenarios): | |
74 """ Test cases for metadata module values. """ | |
75 | |
76 expected_str_attributes = set([ | |
77 'version_installed', | |
78 'author', | |
79 'copyright', | |
80 'license', | |
81 'url', | |
82 ]) | |
83 | |
84 scenarios = [ | |
85 (name, {'attribute_name': name}) | |
86 for name in expected_str_attributes] | |
87 for (name, params) in scenarios: | |
88 if name == 'version_installed': | |
89 # No duck typing, this attribute might be None. | |
90 params['ducktype_attribute_name'] = NotImplemented | |
91 continue | |
92 # Expect an attribute of ‘str’ to test this value. | |
93 params['ducktype_attribute_name'] = 'isdigit' | |
94 | |
95 def test_module_has_attribute(self): | |
96 """ Metadata should have expected value as a module attribute. """ | |
97 self.assertThat( | |
98 metadata, HasAttribute(self.attribute_name)) | |
99 | |
100 def test_module_attribute_has_duck_type(self): | |
101 """ Metadata value should have expected duck-typing attribute. """ | |
102 if self.ducktype_attribute_name == NotImplemented: | |
103 self.skipTest("Can't assert this attribute's type") | |
104 instance = getattr(metadata, self.attribute_name) | |
105 self.assertThat( | |
106 instance, HasAttribute(self.ducktype_attribute_name)) | |
107 | |
108 | |
109 class parse_person_field_TestCase( | |
110 testscenarios.WithScenarios, testtools.TestCase): | |
111 """ Test cases for ‘get_latest_version’ function. """ | |
112 | |
113 scenarios = [ | |
114 ('simple', { | |
115 'test_person': "Foo Bar <foo.bar@example.com>", | |
116 'expected_result': ("Foo Bar", "foo.bar@example.com"), | |
117 }), | |
118 ('empty', { | |
119 'test_person': "", | |
120 'expected_result': (None, None), | |
121 }), | |
122 ('none', { | |
123 'test_person': None, | |
124 'expected_error': TypeError, | |
125 }), | |
126 ('no email', { | |
127 'test_person': "Foo Bar", | |
128 'expected_result': ("Foo Bar", None), | |
129 }), | |
130 ] | |
131 | |
132 def test_returns_expected_result(self): | |
133 """ Should return expected result. """ | |
134 if hasattr(self, 'expected_error'): | |
135 self.assertRaises( | |
136 self.expected_error, | |
137 metadata.parse_person_field, self.test_person) | |
138 else: | |
139 result = metadata.parse_person_field(self.test_person) | |
140 self.assertEqual(self.expected_result, result) | |
141 | |
142 | |
143 class YearRange_TestCase(scaffold.TestCaseWithScenarios): | |
144 """ Test cases for ‘YearRange’ class. """ | |
145 | |
146 scenarios = [ | |
147 ('simple', { | |
148 'begin_year': 1970, | |
149 'end_year': 1979, | |
150 'expected_text': "1970–1979", | |
151 }), | |
152 ('same year', { | |
153 'begin_year': 1970, | |
154 'end_year': 1970, | |
155 'expected_text': "1970", | |
156 }), | |
157 ('no end year', { | |
158 'begin_year': 1970, | |
159 'end_year': None, | |
160 'expected_text': "1970", | |
161 }), | |
162 ] | |
163 | |
164 def setUp(self): | |
165 """ Set up test fixtures. """ | |
166 super(YearRange_TestCase, self).setUp() | |
167 | |
168 self.test_instance = metadata.YearRange( | |
169 self.begin_year, self.end_year) | |
170 | |
171 def test_text_representation_as_expected(self): | |
172 """ Text representation should be as expected. """ | |
173 result = unicode(self.test_instance) | |
174 self.assertEqual(result, self.expected_text) | |
175 | |
176 | |
177 FakeYearRange = collections.namedtuple('FakeYearRange', ['begin', 'end']) | |
178 | |
179 @mock.patch.object(metadata, 'YearRange', new=FakeYearRange) | |
180 class make_year_range_TestCase(scaffold.TestCaseWithScenarios): | |
181 """ Test cases for ‘make_year_range’ function. """ | |
182 | |
183 scenarios = [ | |
184 ('simple', { | |
185 'begin_year': "1970", | |
186 'end_date': "1979-01-01", | |
187 'expected_range': FakeYearRange(begin=1970, end=1979), | |
188 }), | |
189 ('same year', { | |
190 'begin_year': "1970", | |
191 'end_date': "1970-01-01", | |
192 'expected_range': FakeYearRange(begin=1970, end=1970), | |
193 }), | |
194 ('no end year', { | |
195 'begin_year': "1970", | |
196 'end_date': None, | |
197 'expected_range': FakeYearRange(begin=1970, end=None), | |
198 }), | |
199 ('end date UNKNOWN token', { | |
200 'begin_year': "1970", | |
201 'end_date': "UNKNOWN", | |
202 'expected_range': FakeYearRange(begin=1970, end=None), | |
203 }), | |
204 ('end date FUTURE token', { | |
205 'begin_year': "1970", | |
206 'end_date': "FUTURE", | |
207 'expected_range': FakeYearRange(begin=1970, end=None), | |
208 }), | |
209 ] | |
210 | |
211 def test_result_matches_expected_range(self): | |
212 """ Result should match expected YearRange. """ | |
213 result = metadata.make_year_range(self.begin_year, self.end_date) | |
214 self.assertEqual(result, self.expected_range) | |
215 | |
216 | |
217 class metadata_content_TestCase(scaffold.TestCase): | |
218 """ Test cases for content of metadata. """ | |
219 | |
220 def test_copyright_formatted_correctly(self): | |
221 """ Copyright statement should be formatted correctly. """ | |
222 regex_pattern = ( | |
223 "Copyright © " | |
224 "\d{4}" # four-digit year | |
225 "(?:–\d{4})?" # optional range dash and ending four-digit year | |
226 ) | |
227 regex_flags = re.UNICODE | |
228 self.assertThat( | |
229 metadata.copyright, | |
230 testtools.matchers.MatchesRegex(regex_pattern, regex_flags)) | |
231 | |
232 def test_author_formatted_correctly(self): | |
233 """ Author information should be formatted correctly. """ | |
234 regex_pattern = ( | |
235 ".+ " # name | |
236 "<[^>]+>" # email address, in angle brackets | |
237 ) | |
238 regex_flags = re.UNICODE | |
239 self.assertThat( | |
240 metadata.author, | |
241 testtools.matchers.MatchesRegex(regex_pattern, regex_flags)) | |
242 | |
243 def test_copyright_contains_author(self): | |
244 """ Copyright information should contain author information. """ | |
245 self.assertThat( | |
246 metadata.copyright, | |
247 testtools.matchers.Contains(metadata.author)) | |
248 | |
249 def test_url_parses_correctly(self): | |
250 """ Homepage URL should parse correctly. """ | |
251 result = urlparse.urlparse(metadata.url) | |
252 self.assertIsInstance( | |
253 result, urlparse.ParseResult, | |
254 "URL value {url!r} did not parse correctly".format( | |
255 url=metadata.url)) | |
256 | |
257 | |
258 try: | |
259 FileNotFoundError | |
260 except NameError: | |
261 # Python 2 uses IOError. | |
262 FileNotFoundError = functools.partial(IOError, errno.ENOENT) | |
263 | |
264 version_info_filename = "version_info.json" | |
265 | |
266 def fake_func_has_metadata(testcase, resource_name): | |
267 """ Fake the behaviour of ‘pkg_resources.Distribution.has_metadata’. """ | |
268 if ( | |
269 resource_name != testcase.expected_resource_name | |
270 or not hasattr(testcase, 'test_version_info')): | |
271 return False | |
272 return True | |
273 | |
274 | |
275 def fake_func_get_metadata(testcase, resource_name): | |
276 """ Fake the behaviour of ‘pkg_resources.Distribution.get_metadata’. """ | |
277 if not fake_func_has_metadata(testcase, resource_name): | |
278 error = FileNotFoundError(resource_name) | |
279 raise error | |
280 content = testcase.test_version_info | |
281 return content | |
282 | |
283 | |
284 def fake_func_get_distribution(testcase, distribution_name): | |
285 """ Fake the behaviour of ‘pkg_resources.get_distribution’. """ | |
286 if distribution_name != metadata.distribution_name: | |
287 raise pkg_resources.DistributionNotFound | |
288 if hasattr(testcase, 'get_distribution_error'): | |
289 raise testcase.get_distribution_error | |
290 mock_distribution = testcase.mock_distribution | |
291 mock_distribution.has_metadata.side_effect = functools.partial( | |
292 fake_func_has_metadata, testcase) | |
293 mock_distribution.get_metadata.side_effect = functools.partial( | |
294 fake_func_get_metadata, testcase) | |
295 return mock_distribution | |
296 | |
297 | |
298 @mock.patch.object(metadata, 'distribution_name', new="mock-dist") | |
299 class get_distribution_version_info_TestCase(scaffold.TestCaseWithScenarios): | |
300 """ Test cases for ‘get_distribution_version_info’ function. """ | |
301 | |
302 default_version_info = { | |
303 'release_date': "UNKNOWN", | |
304 'version': "UNKNOWN", | |
305 'maintainer': "UNKNOWN", | |
306 } | |
307 | |
308 scenarios = [ | |
309 ('version 0.0', { | |
310 'test_version_info': json.dumps({ | |
311 'version': "0.0", | |
312 }), | |
313 'expected_version_info': {'version': "0.0"}, | |
314 }), | |
315 ('version 1.0', { | |
316 'test_version_info': json.dumps({ | |
317 'version': "1.0", | |
318 }), | |
319 'expected_version_info': {'version': "1.0"}, | |
320 }), | |
321 ('file lorem_ipsum.json', { | |
322 'version_info_filename': "lorem_ipsum.json", | |
323 'test_version_info': json.dumps({ | |
324 'version': "1.0", | |
325 }), | |
326 'expected_version_info': {'version': "1.0"}, | |
327 }), | |
328 ('not installed', { | |
329 'get_distribution_error': pkg_resources.DistributionNotFound(), | |
330 'expected_version_info': default_version_info, | |
331 }), | |
332 ('no version_info', { | |
333 'expected_version_info': default_version_info, | |
334 }), | |
335 ] | |
336 | |
337 def setUp(self): | |
338 """ Set up test fixtures. """ | |
339 super(get_distribution_version_info_TestCase, self).setUp() | |
340 | |
341 if hasattr(self, 'expected_resource_name'): | |
342 self.test_args = {'filename': self.expected_resource_name} | |
343 else: | |
344 self.test_args = {} | |
345 self.expected_resource_name = version_info_filename | |
346 | |
347 self.mock_distribution = mock.MagicMock() | |
348 func_patcher_get_distribution = mock.patch.object( | |
349 pkg_resources, 'get_distribution') | |
350 func_patcher_get_distribution.start() | |
351 self.addCleanup(func_patcher_get_distribution.stop) | |
352 pkg_resources.get_distribution.side_effect = functools.partial( | |
353 fake_func_get_distribution, self) | |
354 | |
355 def test_requests_installed_distribution(self): | |
356 """ The package distribution should be retrieved. """ | |
357 expected_distribution_name = metadata.distribution_name | |
358 version_info = metadata.get_distribution_version_info(**self.test_args) | |
359 pkg_resources.get_distribution.assert_called_with( | |
360 expected_distribution_name) | |
361 | |
362 def test_requests_specified_filename(self): | |
363 """ The specified metadata resource name should be requested. """ | |
364 if hasattr(self, 'get_distribution_error'): | |
365 self.skipTest("No access to distribution") | |
366 version_info = metadata.get_distribution_version_info(**self.test_args) | |
367 self.mock_distribution.has_metadata.assert_called_with( | |
368 self.expected_resource_name) | |
369 | |
370 def test_result_matches_expected_items(self): | |
371 """ The result should match the expected items. """ | |
372 version_info = metadata.get_distribution_version_info(**self.test_args) | |
373 self.assertEqual(self.expected_version_info, version_info) | |
374 | |
375 | |
376 # Local variables: | |
377 # coding: utf-8 | |
378 # mode: python | |
379 # End: | |
380 # vim: fileencoding=utf-8 filetype=python : |