Update and rename MantenerFIFO to MantenerFIFO.md
[vsorcdistro/.git] / pbr / tests / test_setup.py
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
21 try:
22     import cStringIO as io
23     BytesIO = io.StringIO
24 except ImportError:
25     import io
26     BytesIO = io.BytesIO
27
28 import fixtures
29
30 from pbr import git
31 from pbr import options
32 from pbr import packaging
33 from pbr.tests import base
34
35
36 class SkipFileWrites(base.BaseTestCase):
37
38     scenarios = [
39         ('changelog_option_true',
40          dict(option_key='skip_changelog', option_value='True',
41               env_key='SKIP_WRITE_GIT_CHANGELOG', env_value=None,
42               pkg_func=git.write_git_changelog, filename='ChangeLog')),
43         ('changelog_option_false',
44          dict(option_key='skip_changelog', option_value='False',
45               env_key='SKIP_WRITE_GIT_CHANGELOG', env_value=None,
46               pkg_func=git.write_git_changelog, filename='ChangeLog')),
47         ('changelog_env_true',
48          dict(option_key='skip_changelog', option_value='False',
49               env_key='SKIP_WRITE_GIT_CHANGELOG', env_value='True',
50               pkg_func=git.write_git_changelog, filename='ChangeLog')),
51         ('changelog_both_true',
52          dict(option_key='skip_changelog', option_value='True',
53               env_key='SKIP_WRITE_GIT_CHANGELOG', env_value='True',
54               pkg_func=git.write_git_changelog, filename='ChangeLog')),
55         ('authors_option_true',
56          dict(option_key='skip_authors', option_value='True',
57               env_key='SKIP_GENERATE_AUTHORS', env_value=None,
58               pkg_func=git.generate_authors, filename='AUTHORS')),
59         ('authors_option_false',
60          dict(option_key='skip_authors', option_value='False',
61               env_key='SKIP_GENERATE_AUTHORS', env_value=None,
62               pkg_func=git.generate_authors, filename='AUTHORS')),
63         ('authors_env_true',
64          dict(option_key='skip_authors', option_value='False',
65               env_key='SKIP_GENERATE_AUTHORS', env_value='True',
66               pkg_func=git.generate_authors, filename='AUTHORS')),
67         ('authors_both_true',
68          dict(option_key='skip_authors', option_value='True',
69               env_key='SKIP_GENERATE_AUTHORS', env_value='True',
70               pkg_func=git.generate_authors, filename='AUTHORS')),
71     ]
72
73     def setUp(self):
74         super(SkipFileWrites, self).setUp()
75         self.temp_path = self.useFixture(fixtures.TempDir()).path
76         self.root_dir = os.path.abspath(os.path.curdir)
77         self.git_dir = os.path.join(self.root_dir, ".git")
78         if not os.path.exists(self.git_dir):
79             self.skipTest("%s is missing; skipping git-related checks"
80                           % self.git_dir)
81             return
82         self.filename = os.path.join(self.temp_path, self.filename)
83         self.option_dict = dict()
84         if self.option_key is not None:
85             self.option_dict[self.option_key] = ('setup.cfg',
86                                                  self.option_value)
87         self.useFixture(
88             fixtures.EnvironmentVariable(self.env_key, self.env_value))
89
90     def test_skip(self):
91         self.pkg_func(git_dir=self.git_dir,
92                       dest_dir=self.temp_path,
93                       option_dict=self.option_dict)
94         self.assertEqual(
95             not os.path.exists(self.filename),
96             (self.option_value.lower() in options.TRUE_VALUES
97              or self.env_value is not None))
98
99 _changelog_content = """7780758\x00Break parser\x00 (tag: refs/tags/1_foo.1)
100 04316fe\x00Make python\x00 (refs/heads/review/monty_taylor/27519)
101 378261a\x00Add an integration test script.\x00
102 3c373ac\x00Merge "Lib\x00 (HEAD, tag: refs/tags/2013.2.rc2, tag: refs/tags/2013.2, refs/heads/mile-proposed)
103 182feb3\x00Fix pip invocation for old versions of pip.\x00 (tag: refs/tags/0.5.17)
104 fa4f46e\x00Remove explicit depend on distribute.\x00 (tag: refs/tags/0.5.16)
105 d1c53dd\x00Use pip instead of easy_install for installation.\x00
106 a793ea1\x00Merge "Skip git-checkout related tests when .git is missing"\x00
107 6c27ce7\x00Skip git-checkout related tests when .git is missing\x00
108 451e513\x00Bug fix: create_stack() fails when waiting\x00
109 4c8cfe4\x00Improve test coverage: network delete API\x00 (tag: refs/tags/(evil))
110 d7e6167\x00Bug fix: Fix pass thru filtering in list_networks\x00 (tag: refs/tags/ev()il)
111 c47ec15\x00Consider 'in-use' a non-pending volume for caching\x00 (tag: refs/tags/ev)il)
112 8696fbd\x00Improve test coverage: private extension API\x00 (tag: refs/tags/ev(il)
113 f0440f8\x00Improve test coverage: hypervisor list\x00 (tag: refs/tags/e(vi)l)
114 04984a5\x00Refactor hooks file.\x00 (HEAD, tag: 0.6.7,b, tag: refs/tags/(12), refs/heads/master)
115 a65e8ee\x00Remove jinja pin.\x00 (tag: refs/tags/0.5.14, tag: refs/tags/0.5.13)
116 """  # noqa
117
118
119 def _make_old_git_changelog_format(line):
120     """Convert post-1.8.1 git log format to pre-1.8.1 git log format"""
121
122     if not line.strip():
123         return line
124     sha, msg, refname = line.split('\x00')
125     refname = refname.replace('tag: ', '')
126     return '\x00'.join((sha, msg, refname))
127
128 _old_git_changelog_content = '\n'.join(
129     _make_old_git_changelog_format(line)
130     for line in _changelog_content.split('\n'))
131
132
133 class GitLogsTest(base.BaseTestCase):
134
135     scenarios = [
136         ('pre1.8.3', {'changelog': _old_git_changelog_content}),
137         ('post1.8.3', {'changelog': _changelog_content}),
138     ]
139
140     def setUp(self):
141         super(GitLogsTest, self).setUp()
142         self.temp_path = self.useFixture(fixtures.TempDir()).path
143         self.root_dir = os.path.abspath(os.path.curdir)
144         self.git_dir = os.path.join(self.root_dir, ".git")
145         self.useFixture(
146             fixtures.EnvironmentVariable('SKIP_GENERATE_AUTHORS'))
147         self.useFixture(
148             fixtures.EnvironmentVariable('SKIP_WRITE_GIT_CHANGELOG'))
149
150     def test_write_git_changelog(self):
151         self.useFixture(fixtures.FakePopen(lambda _: {
152             "stdout": BytesIO(self.changelog.encode('utf-8'))
153         }))
154
155         git.write_git_changelog(git_dir=self.git_dir,
156                                 dest_dir=self.temp_path)
157
158         with open(os.path.join(self.temp_path, "ChangeLog"), "r") as ch_fh:
159             changelog_contents = ch_fh.read()
160             self.assertIn("2013.2", changelog_contents)
161             self.assertIn("0.5.17", changelog_contents)
162             self.assertIn("------", changelog_contents)
163             self.assertIn("Refactor hooks file", changelog_contents)
164             self.assertIn(
165                 "Bug fix: create\_stack() fails when waiting",
166                 changelog_contents)
167             self.assertNotIn("Refactor hooks file.", changelog_contents)
168             self.assertNotIn("182feb3", changelog_contents)
169             self.assertNotIn("review/monty_taylor/27519", changelog_contents)
170             self.assertNotIn("0.5.13", changelog_contents)
171             self.assertNotIn("0.6.7", changelog_contents)
172             self.assertNotIn("12", changelog_contents)
173             self.assertNotIn("(evil)", changelog_contents)
174             self.assertNotIn("ev()il", changelog_contents)
175             self.assertNotIn("ev(il", changelog_contents)
176             self.assertNotIn("ev)il", changelog_contents)
177             self.assertNotIn("e(vi)l", changelog_contents)
178             self.assertNotIn('Merge "', changelog_contents)
179             self.assertNotIn('1\_foo.1', changelog_contents)
180
181     def test_generate_authors(self):
182         author_old = u"Foo Foo <email@foo.com>"
183         author_new = u"Bar Bar <email@bar.com>"
184         co_author = u"Foo Bar <foo@bar.com>"
185         co_author_by = u"Co-authored-by: " + co_author
186
187         git_log_cmd = (
188             "git --git-dir=%s log --format=%%aN <%%aE>"
189             % self.git_dir)
190         git_co_log_cmd = ("git --git-dir=%s log" % self.git_dir)
191         git_top_level = "git rev-parse --show-toplevel"
192         cmd_map = {
193             git_log_cmd: author_new,
194             git_co_log_cmd: co_author_by,
195             git_top_level: self.root_dir,
196         }
197
198         exist_files = [self.git_dir,
199                        os.path.join(self.temp_path, "AUTHORS.in")]
200         self.useFixture(fixtures.MonkeyPatch(
201             "os.path.exists",
202             lambda path: os.path.abspath(path) in exist_files))
203
204         def _fake_run_shell_command(cmd, **kwargs):
205             return cmd_map[" ".join(cmd)]
206
207         self.useFixture(fixtures.MonkeyPatch(
208             "pbr.git._run_shell_command",
209             _fake_run_shell_command))
210
211         with open(os.path.join(self.temp_path, "AUTHORS.in"), "w") as auth_fh:
212             auth_fh.write("%s\n" % author_old)
213
214         git.generate_authors(git_dir=self.git_dir,
215                              dest_dir=self.temp_path)
216
217         with open(os.path.join(self.temp_path, "AUTHORS"), "r") as auth_fh:
218             authors = auth_fh.read()
219             self.assertTrue(author_old in authors)
220             self.assertTrue(author_new in authors)
221             self.assertTrue(co_author in authors)
222
223
224 class _SphinxConfig(object):
225     man_pages = ['foo']
226
227
228 class BaseSphinxTest(base.BaseTestCase):
229
230     def setUp(self):
231         super(BaseSphinxTest, self).setUp()
232
233         # setup_command requires the Sphinx instance to have some
234         # attributes that aren't set normally with the way we use the
235         # class (because we replace the constructor). Add default
236         # values directly to the class definition.
237         import sphinx.application
238         sphinx.application.Sphinx.messagelog = []
239         sphinx.application.Sphinx.statuscode = 0
240
241         self.useFixture(fixtures.MonkeyPatch(
242             "sphinx.application.Sphinx.__init__", lambda *a, **kw: None))
243         self.useFixture(fixtures.MonkeyPatch(
244             "sphinx.application.Sphinx.build", lambda *a, **kw: None))
245         self.useFixture(fixtures.MonkeyPatch(
246             "sphinx.application.Sphinx.config", _SphinxConfig))
247         self.useFixture(fixtures.MonkeyPatch(
248             "sphinx.config.Config.init_values", lambda *a: None))
249         self.useFixture(fixtures.MonkeyPatch(
250             "sphinx.config.Config.__init__", lambda *a: None))
251         from distutils import dist
252         self.distr = dist.Distribution()
253         self.distr.packages = ("fake_package",)
254         self.distr.command_options["build_sphinx"] = {
255             "source_dir": ["a", "."]}
256         pkg_fixture = fixtures.PythonPackage(
257             "fake_package", [("fake_module.py", b""),
258                              ("another_fake_module_for_testing.py", b""),
259                              ("fake_private_module.py", b"")])
260         self.useFixture(pkg_fixture)
261         self.useFixture(base.DiveDir(pkg_fixture.base))
262         self.distr.command_options["pbr"] = {}
263         if hasattr(self, "excludes"):
264             self.distr.command_options["pbr"]["autodoc_exclude_modules"] = (
265                 'setup.cfg',
266                 "fake_package.fake_private_module\n"
267                 "fake_package.another_fake_*\n"
268                 "fake_package.unknown_module")
269         if hasattr(self, 'has_opt') and self.has_opt:
270             options = self.distr.command_options["pbr"]
271             options["autodoc_index_modules"] = ('setup.cfg', self.autodoc)
272
273
274 class BuildSphinxTest(BaseSphinxTest):
275
276     scenarios = [
277         ('true_autodoc_caps',
278          dict(has_opt=True, autodoc='True', has_autodoc=True)),
279         ('true_autodoc_caps_with_excludes',
280          dict(has_opt=True, autodoc='True', has_autodoc=True,
281               excludes="fake_package.fake_private_module\n"
282               "fake_package.another_fake_*\n"
283               "fake_package.unknown_module")),
284         ('true_autodoc_lower',
285          dict(has_opt=True, autodoc='true', has_autodoc=True)),
286         ('false_autodoc',
287          dict(has_opt=True, autodoc='False', has_autodoc=False)),
288         ('no_autodoc',
289          dict(has_opt=False, autodoc='False', has_autodoc=False)),
290     ]
291
292     def test_build_doc(self):
293         build_doc = packaging.LocalBuildDoc(self.distr)
294         build_doc.run()
295
296         self.assertTrue(
297             os.path.exists("api/autoindex.rst") == self.has_autodoc)
298         self.assertTrue(
299             os.path.exists(
300                 "api/fake_package.fake_module.rst") == self.has_autodoc)
301         if not self.has_autodoc or hasattr(self, "excludes"):
302             assertion = self.assertFalse
303         else:
304             assertion = self.assertTrue
305         assertion(
306             os.path.exists(
307                 "api/fake_package.fake_private_module.rst"))
308         assertion(
309             os.path.exists(
310                 "api/fake_package.another_fake_module_for_testing.rst"))
311
312     def test_builders_config(self):
313         build_doc = packaging.LocalBuildDoc(self.distr)
314         build_doc.finalize_options()
315
316         self.assertEqual(1, len(build_doc.builders))
317         self.assertIn('html', build_doc.builders)
318
319         build_doc = packaging.LocalBuildDoc(self.distr)
320         build_doc.builders = ''
321         build_doc.finalize_options()
322
323         self.assertEqual('', build_doc.builders)
324
325         build_doc = packaging.LocalBuildDoc(self.distr)
326         build_doc.builders = 'man'
327         build_doc.finalize_options()
328
329         self.assertEqual(1, len(build_doc.builders))
330         self.assertIn('man', build_doc.builders)
331
332         build_doc = packaging.LocalBuildDoc(self.distr)
333         build_doc.builders = 'html,man,doctest'
334         build_doc.finalize_options()
335
336         self.assertIn('html', build_doc.builders)
337         self.assertIn('man', build_doc.builders)
338         self.assertIn('doctest', build_doc.builders)
339
340     def test_cmd_builder_override(self):
341
342         if self.has_opt:
343             self.distr.command_options["pbr"] = {
344                 "autodoc_index_modules": ('setup.cfg', self.autodoc)
345             }
346
347         self.distr.command_options["build_sphinx"]["builder"] = (
348             "command line", "non-existing-builder")
349
350         build_doc = packaging.LocalBuildDoc(self.distr)
351         self.assertNotIn('non-existing-builder', build_doc.builders)
352         self.assertIn('html', build_doc.builders)
353
354         # process command line options which should override config
355         build_doc.finalize_options()
356
357         self.assertIn('non-existing-builder', build_doc.builders)
358         self.assertNotIn('html', build_doc.builders)
359
360     def test_cmd_builder_override_multiple_builders(self):
361
362         if self.has_opt:
363             self.distr.command_options["pbr"] = {
364                 "autodoc_index_modules": ('setup.cfg', self.autodoc)
365             }
366
367         self.distr.command_options["build_sphinx"]["builder"] = (
368             "command line", "builder1,builder2")
369
370         build_doc = packaging.LocalBuildDoc(self.distr)
371         build_doc.finalize_options()
372
373         self.assertEqual(["builder1", "builder2"], build_doc.builders)
374
375
376 class APIAutoDocTest(base.BaseTestCase):
377
378     def setUp(self):
379         super(APIAutoDocTest, self).setUp()
380
381         # setup_command requires the Sphinx instance to have some
382         # attributes that aren't set normally with the way we use the
383         # class (because we replace the constructor). Add default
384         # values directly to the class definition.
385         import sphinx.application
386         sphinx.application.Sphinx.messagelog = []
387         sphinx.application.Sphinx.statuscode = 0
388
389         self.useFixture(fixtures.MonkeyPatch(
390             "sphinx.application.Sphinx.__init__", lambda *a, **kw: None))
391         self.useFixture(fixtures.MonkeyPatch(
392             "sphinx.application.Sphinx.build", lambda *a, **kw: None))
393         self.useFixture(fixtures.MonkeyPatch(
394             "sphinx.application.Sphinx.config", _SphinxConfig))
395         self.useFixture(fixtures.MonkeyPatch(
396             "sphinx.config.Config.init_values", lambda *a: None))
397         self.useFixture(fixtures.MonkeyPatch(
398             "sphinx.config.Config.__init__", lambda *a: None))
399         from distutils import dist
400         self.distr = dist.Distribution()
401         self.distr.packages = ("fake_package",)
402         self.distr.command_options["build_sphinx"] = {
403             "source_dir": ["a", "."]}
404         self.sphinx_options = self.distr.command_options["build_sphinx"]
405         pkg_fixture = fixtures.PythonPackage(
406             "fake_package", [("fake_module.py", b""),
407                              ("another_fake_module_for_testing.py", b""),
408                              ("fake_private_module.py", b"")])
409         self.useFixture(pkg_fixture)
410         self.useFixture(base.DiveDir(pkg_fixture.base))
411         self.pbr_options = self.distr.command_options.setdefault('pbr', {})
412         self.pbr_options["autodoc_index_modules"] = ('setup.cfg', 'True')
413
414     def test_default_api_build_dir(self):
415         build_doc = packaging.LocalBuildDoc(self.distr)
416         build_doc.run()
417
418         print('PBR OPTIONS:', self.pbr_options)
419         print('DISTR OPTIONS:', self.distr.command_options)
420
421         self.assertTrue(os.path.exists("api/autoindex.rst"))
422         self.assertTrue(os.path.exists("api/fake_package.fake_module.rst"))
423         self.assertTrue(
424             os.path.exists(
425                 "api/fake_package.fake_private_module.rst"))
426         self.assertTrue(
427             os.path.exists(
428                 "api/fake_package.another_fake_module_for_testing.rst"))
429
430     def test_different_api_build_dir(self):
431         # Options have to come out of the settings dict as a tuple
432         # showing the source and the value.
433         self.pbr_options['api_doc_dir'] = (None, 'contributor/api')
434         build_doc = packaging.LocalBuildDoc(self.distr)
435         build_doc.run()
436
437         print('PBR OPTIONS:', self.pbr_options)
438         print('DISTR OPTIONS:', self.distr.command_options)
439
440         self.assertTrue(os.path.exists("contributor/api/autoindex.rst"))
441         self.assertTrue(
442             os.path.exists("contributor/api/fake_package.fake_module.rst"))
443         self.assertTrue(
444             os.path.exists(
445                 "contributor/api/fake_package.fake_private_module.rst"))