3aec296164ae3acb87b60d990d8a37a78bd719cd
[sdc/sdc-distribution-client.git] /
1 # Copyright (c) 2011 OpenStack Foundation
2 # Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
3 # All Rights Reserved.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License"); you may
6 # not use this file except in compliance with the License. You may obtain
7 # a copy of the License at
8 #
9 #      http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 # License for the specific language governing permissions and limitations
15 # under the License.
16
17 from __future__ import print_function
18
19 import os
20 import sys
21 import tempfile
22
23 try:
24     import cStringIO as io
25     BytesIO = io.StringIO
26 except ImportError:
27     import io
28     BytesIO = io.BytesIO
29
30 import fixtures
31 import testscenarios
32
33 from pbr import git
34 from pbr import options
35 from pbr import packaging
36 from pbr.tests import base
37
38
39 class SkipFileWrites(base.BaseTestCase):
40
41     scenarios = [
42         ('changelog_option_true',
43          dict(option_key='skip_changelog', option_value='True',
44               env_key='SKIP_WRITE_GIT_CHANGELOG', env_value=None,
45               pkg_func=git.write_git_changelog, filename='ChangeLog')),
46         ('changelog_option_false',
47          dict(option_key='skip_changelog', option_value='False',
48               env_key='SKIP_WRITE_GIT_CHANGELOG', env_value=None,
49               pkg_func=git.write_git_changelog, filename='ChangeLog')),
50         ('changelog_env_true',
51          dict(option_key='skip_changelog', option_value='False',
52               env_key='SKIP_WRITE_GIT_CHANGELOG', env_value='True',
53               pkg_func=git.write_git_changelog, filename='ChangeLog')),
54         ('changelog_both_true',
55          dict(option_key='skip_changelog', option_value='True',
56               env_key='SKIP_WRITE_GIT_CHANGELOG', env_value='True',
57               pkg_func=git.write_git_changelog, filename='ChangeLog')),
58         ('authors_option_true',
59          dict(option_key='skip_authors', option_value='True',
60               env_key='SKIP_GENERATE_AUTHORS', env_value=None,
61               pkg_func=git.generate_authors, filename='AUTHORS')),
62         ('authors_option_false',
63          dict(option_key='skip_authors', option_value='False',
64               env_key='SKIP_GENERATE_AUTHORS', env_value=None,
65               pkg_func=git.generate_authors, filename='AUTHORS')),
66         ('authors_env_true',
67          dict(option_key='skip_authors', option_value='False',
68               env_key='SKIP_GENERATE_AUTHORS', env_value='True',
69               pkg_func=git.generate_authors, filename='AUTHORS')),
70         ('authors_both_true',
71          dict(option_key='skip_authors', option_value='True',
72               env_key='SKIP_GENERATE_AUTHORS', env_value='True',
73               pkg_func=git.generate_authors, filename='AUTHORS')),
74     ]
75
76     def setUp(self):
77         super(SkipFileWrites, self).setUp()
78         self.temp_path = self.useFixture(fixtures.TempDir()).path
79         self.root_dir = os.path.abspath(os.path.curdir)
80         self.git_dir = os.path.join(self.root_dir, ".git")
81         if not os.path.exists(self.git_dir):
82             self.skipTest("%s is missing; skipping git-related checks"
83                           % self.git_dir)
84             return
85         self.filename = os.path.join(self.temp_path, self.filename)
86         self.option_dict = dict()
87         if self.option_key is not None:
88             self.option_dict[self.option_key] = ('setup.cfg',
89                                                  self.option_value)
90         self.useFixture(
91             fixtures.EnvironmentVariable(self.env_key, self.env_value))
92
93     def test_skip(self):
94         self.pkg_func(git_dir=self.git_dir,
95                       dest_dir=self.temp_path,
96                       option_dict=self.option_dict)
97         self.assertEqual(
98             not os.path.exists(self.filename),
99             (self.option_value.lower() in options.TRUE_VALUES
100              or self.env_value is not None))
101
102 _changelog_content = """04316fe (review/monty_taylor/27519) Make python
103 378261a Add an integration test script.
104 3c373ac (HEAD, tag: 2013.2.rc2, tag: 2013.2, milestone-proposed) Merge "Lib
105 182feb3 (tag: 0.5.17) Fix pip invocation for old versions of pip.
106 fa4f46e (tag: 0.5.16) Remove explicit depend on distribute.
107 d1c53dd Use pip instead of easy_install for installation.
108 a793ea1 Merge "Skip git-checkout related tests when .git is missing"
109 6c27ce7 Skip git-checkout related tests when .git is missing
110 04984a5 Refactor hooks file.
111 a65e8ee (tag: 0.5.14, tag: 0.5.13) Remove jinja pin.
112 """
113
114
115 class GitLogsTest(base.BaseTestCase):
116
117     def setUp(self):
118         super(GitLogsTest, self).setUp()
119         self.temp_path = self.useFixture(fixtures.TempDir()).path
120         self.root_dir = os.path.abspath(os.path.curdir)
121         self.git_dir = os.path.join(self.root_dir, ".git")
122         self.useFixture(
123             fixtures.EnvironmentVariable('SKIP_GENERATE_AUTHORS'))
124         self.useFixture(
125             fixtures.EnvironmentVariable('SKIP_WRITE_GIT_CHANGELOG'))
126
127     def test_write_git_changelog(self):
128         self.useFixture(fixtures.FakePopen(lambda _: {
129             "stdout": BytesIO(_changelog_content.encode('utf-8'))
130         }))
131
132         git.write_git_changelog(git_dir=self.git_dir,
133                                 dest_dir=self.temp_path)
134
135         with open(os.path.join(self.temp_path, "ChangeLog"), "r") as ch_fh:
136             changelog_contents = ch_fh.read()
137             self.assertIn("2013.2", changelog_contents)
138             self.assertIn("0.5.17", changelog_contents)
139             self.assertIn("------", changelog_contents)
140             self.assertIn("Refactor hooks file", changelog_contents)
141             self.assertNotIn("Refactor hooks file.", changelog_contents)
142             self.assertNotIn("182feb3", changelog_contents)
143             self.assertNotIn("review/monty_taylor/27519", changelog_contents)
144             self.assertNotIn("0.5.13", changelog_contents)
145             self.assertNotIn('Merge "', changelog_contents)
146
147     def test_generate_authors(self):
148         author_old = u"Foo Foo <email@foo.com>"
149         author_new = u"Bar Bar <email@bar.com>"
150         co_author = u"Foo Bar <foo@bar.com>"
151         co_author_by = u"Co-authored-by: " + co_author
152
153         git_log_cmd = (
154             "git --git-dir=%s log --format=%%aN <%%aE>"
155             % self.git_dir)
156         git_co_log_cmd = ("git --git-dir=%s log" % self.git_dir)
157         git_top_level = "git rev-parse --show-toplevel"
158         cmd_map = {
159             git_log_cmd: author_new,
160             git_co_log_cmd: co_author_by,
161             git_top_level: self.root_dir,
162         }
163
164         exist_files = [self.git_dir,
165                        os.path.join(self.temp_path, "AUTHORS.in")]
166         self.useFixture(fixtures.MonkeyPatch(
167             "os.path.exists",
168             lambda path: os.path.abspath(path) in exist_files))
169
170         def _fake_run_shell_command(cmd, **kwargs):
171             return cmd_map[" ".join(cmd)]
172
173         self.useFixture(fixtures.MonkeyPatch(
174             "pbr.git._run_shell_command",
175             _fake_run_shell_command))
176
177         with open(os.path.join(self.temp_path, "AUTHORS.in"), "w") as auth_fh:
178             auth_fh.write("%s\n" % author_old)
179
180         git.generate_authors(git_dir=self.git_dir,
181                              dest_dir=self.temp_path)
182
183         with open(os.path.join(self.temp_path, "AUTHORS"), "r") as auth_fh:
184             authors = auth_fh.read()
185             self.assertTrue(author_old in authors)
186             self.assertTrue(author_new in authors)
187             self.assertTrue(co_author in authors)
188
189
190 class BuildSphinxTest(base.BaseTestCase):
191
192     scenarios = [
193         ('true_autodoc_caps',
194          dict(has_opt=True, autodoc='True', has_autodoc=True)),
195         ('true_autodoc_caps_with_excludes',
196          dict(has_opt=True, autodoc='True', has_autodoc=True,
197               excludes="fake_package.fake_private_module\n"
198               "fake_package.another_fake_*\n"
199               "fake_package.unknown_module")),
200         ('true_autodoc_lower',
201          dict(has_opt=True, autodoc='true', has_autodoc=True)),
202         ('false_autodoc',
203          dict(has_opt=True, autodoc='False', has_autodoc=False)),
204         ('no_autodoc',
205          dict(has_opt=False, autodoc='False', has_autodoc=False)),
206     ]
207
208     def setUp(self):
209         super(BuildSphinxTest, self).setUp()
210
211         self.useFixture(fixtures.MonkeyPatch(
212             "sphinx.setup_command.BuildDoc.run", lambda self: None))
213         from distutils import dist
214         self.distr = dist.Distribution()
215         self.distr.packages = ("fake_package",)
216         self.distr.command_options["build_sphinx"] = {
217             "source_dir": ["a", "."]}
218         pkg_fixture = fixtures.PythonPackage(
219             "fake_package", [("fake_module.py", b""),
220                              ("another_fake_module_for_testing.py", b""),
221                              ("fake_private_module.py", b"")])
222         self.useFixture(pkg_fixture)
223         self.useFixture(base.DiveDir(pkg_fixture.base))
224         self.distr.command_options["pbr"] = {}
225         if hasattr(self, "excludes"):
226             self.distr.command_options["pbr"]["autodoc_exclude_modules"] = (
227                 'setup.cfg',
228                 "fake_package.fake_private_module\n"
229                 "fake_package.another_fake_*\n"
230                 "fake_package.unknown_module")
231         if self.has_opt:
232             options = self.distr.command_options["pbr"]
233             options["autodoc_index_modules"] = ('setup.cfg', self.autodoc)
234
235     def test_build_doc(self):
236         build_doc = packaging.LocalBuildDoc(self.distr)
237         build_doc.run()
238
239         self.assertTrue(
240             os.path.exists("api/autoindex.rst") == self.has_autodoc)
241         self.assertTrue(
242             os.path.exists(
243                 "api/fake_package.fake_module.rst") == self.has_autodoc)
244         if not self.has_autodoc or hasattr(self, "excludes"):
245             assertion = self.assertFalse
246         else:
247             assertion = self.assertTrue
248         assertion(
249             os.path.exists(
250                 "api/fake_package.fake_private_module.rst"))
251         assertion(
252             os.path.exists(
253                 "api/fake_package.another_fake_module_for_testing.rst"))
254
255     def test_builders_config(self):
256         build_doc = packaging.LocalBuildDoc(self.distr)
257         build_doc.finalize_options()
258
259         self.assertEqual(2, len(build_doc.builders))
260         self.assertIn('html', build_doc.builders)
261         self.assertIn('man', build_doc.builders)
262
263         build_doc = packaging.LocalBuildDoc(self.distr)
264         build_doc.builders = ''
265         build_doc.finalize_options()
266
267         self.assertEqual('', build_doc.builders)
268
269         build_doc = packaging.LocalBuildDoc(self.distr)
270         build_doc.builders = 'man'
271         build_doc.finalize_options()
272
273         self.assertEqual(1, len(build_doc.builders))
274         self.assertIn('man', build_doc.builders)
275
276         build_doc = packaging.LocalBuildDoc(self.distr)
277         build_doc.builders = 'html,man,doctest'
278         build_doc.finalize_options()
279
280         self.assertIn('html', build_doc.builders)
281         self.assertIn('man', build_doc.builders)
282         self.assertIn('doctest', build_doc.builders)
283
284     def test_cmd_builder_override(self):
285
286         if self.has_opt:
287             self.distr.command_options["pbr"] = {
288                 "autodoc_index_modules": ('setup.cfg', self.autodoc)
289             }
290
291         self.distr.command_options["build_sphinx"]["builder"] = (
292             "command line", "non-existing-builder")
293
294         build_doc = packaging.LocalBuildDoc(self.distr)
295         self.assertNotIn('non-existing-builder', build_doc.builders)
296         self.assertIn('html', build_doc.builders)
297
298         # process command line options which should override config
299         build_doc.finalize_options()
300
301         self.assertIn('non-existing-builder', build_doc.builders)
302         self.assertNotIn('html', build_doc.builders)
303
304     def test_cmd_builder_override_multiple_builders(self):
305
306         if self.has_opt:
307             self.distr.command_options["pbr"] = {
308                 "autodoc_index_modules": ('setup.cfg', self.autodoc)
309             }
310
311         self.distr.command_options["build_sphinx"]["builder"] = (
312             "command line", "builder1,builder2")
313
314         build_doc = packaging.LocalBuildDoc(self.distr)
315         build_doc.finalize_options()
316
317         self.assertEqual(["builder1", "builder2"], build_doc.builders)
318
319
320 class ParseRequirementsTest(base.BaseTestCase):
321
322     def setUp(self):
323         super(ParseRequirementsTest, self).setUp()
324         (fd, self.tmp_file) = tempfile.mkstemp(prefix='openstack',
325                                                suffix='.setup')
326
327     def test_parse_requirements_normal(self):
328         with open(self.tmp_file, 'w') as fh:
329             fh.write("foo\nbar")
330         self.assertEqual(['foo', 'bar'],
331                          packaging.parse_requirements([self.tmp_file]))
332
333     def test_parse_requirements_with_git_egg_url(self):
334         with open(self.tmp_file, 'w') as fh:
335             fh.write("-e git://foo.com/zipball#egg=bar")
336         self.assertEqual(['bar'],
337                          packaging.parse_requirements([self.tmp_file]))
338
339     def test_parse_requirements_with_versioned_git_egg_url(self):
340         with open(self.tmp_file, 'w') as fh:
341             fh.write("-e git://foo.com/zipball#egg=bar-1.2.4")
342         self.assertEqual(['bar>=1.2.4'],
343                          packaging.parse_requirements([self.tmp_file]))
344
345     def test_parse_requirements_with_http_egg_url(self):
346         with open(self.tmp_file, 'w') as fh:
347             fh.write("https://foo.com/zipball#egg=bar")
348         self.assertEqual(['bar'],
349                          packaging.parse_requirements([self.tmp_file]))
350
351     def test_parse_requirements_with_versioned_http_egg_url(self):
352         with open(self.tmp_file, 'w') as fh:
353             fh.write("https://foo.com/zipball#egg=bar-4.2.1")
354         self.assertEqual(['bar>=4.2.1'],
355                          packaging.parse_requirements([self.tmp_file]))
356
357     def test_parse_requirements_removes_index_lines(self):
358         with open(self.tmp_file, 'w') as fh:
359             fh.write("-f foobar")
360         self.assertEqual([], packaging.parse_requirements([self.tmp_file]))
361
362     def test_parse_requirements_override_with_env(self):
363         with open(self.tmp_file, 'w') as fh:
364             fh.write("foo\nbar")
365         self.useFixture(
366             fixtures.EnvironmentVariable('PBR_REQUIREMENTS_FILES',
367                                          self.tmp_file))
368         self.assertEqual(['foo', 'bar'],
369                          packaging.parse_requirements())
370
371     def test_parse_requirements_override_with_env_multiple_files(self):
372         with open(self.tmp_file, 'w') as fh:
373             fh.write("foo\nbar")
374         self.useFixture(
375             fixtures.EnvironmentVariable('PBR_REQUIREMENTS_FILES',
376                                          "no-such-file," + self.tmp_file))
377         self.assertEqual(['foo', 'bar'],
378                          packaging.parse_requirements())
379
380     def test_get_requirement_from_file_empty(self):
381         actual = packaging.get_reqs_from_files([])
382         self.assertEqual([], actual)
383
384     def test_parse_requirements_with_comments(self):
385         with open(self.tmp_file, 'w') as fh:
386             fh.write("# this is a comment\nfoobar\n# and another one\nfoobaz")
387         self.assertEqual(['foobar', 'foobaz'],
388                          packaging.parse_requirements([self.tmp_file]))
389
390     def test_parse_requirements_python_version(self):
391         with open("requirements-py%d.txt" % sys.version_info[0],
392                   "w") as fh:
393             fh.write("# this is a comment\nfoobar\n# and another one\nfoobaz")
394         self.assertEqual(['foobar', 'foobaz'],
395                          packaging.parse_requirements())
396
397     def test_parse_requirements_right_python_version(self):
398         with open("requirements-py1.txt", "w") as fh:
399             fh.write("thisisatrap")
400         with open("requirements-py%d.txt" % sys.version_info[0],
401                   "w") as fh:
402             fh.write("# this is a comment\nfoobar\n# and another one\nfoobaz")
403         self.assertEqual(['foobar', 'foobaz'],
404                          packaging.parse_requirements())
405
406
407 class ParseDependencyLinksTest(base.BaseTestCase):
408
409     def setUp(self):
410         super(ParseDependencyLinksTest, self).setUp()
411         (fd, self.tmp_file) = tempfile.mkstemp(prefix="openstack",
412                                                suffix=".setup")
413
414     def test_parse_dependency_normal(self):
415         with open(self.tmp_file, "w") as fh:
416             fh.write("http://test.com\n")
417         self.assertEqual(
418             ["http://test.com"],
419             packaging.parse_dependency_links([self.tmp_file]))
420
421     def test_parse_dependency_with_git_egg_url(self):
422         with open(self.tmp_file, "w") as fh:
423             fh.write("-e git://foo.com/zipball#egg=bar")
424         self.assertEqual(
425             ["git://foo.com/zipball#egg=bar"],
426             packaging.parse_dependency_links([self.tmp_file]))
427
428
429 def load_tests(loader, in_tests, pattern):
430     return testscenarios.load_tests_apply_scenarios(loader, in_tests, pattern)