1 | # -*- coding: utf-8 -*- |
||
2 | |||
3 | """ |
||
4 | test_generate_hooks |
||
5 | ------------------- |
||
6 | |||
7 | Tests formerly known from a unittest residing in test_generate.py named |
||
8 | TestHooks.test_ignore_hooks_dirs |
||
9 | TestHooks.test_run_python_hooks |
||
10 | TestHooks.test_run_python_hooks_cwd |
||
11 | TestHooks.test_run_shell_hooks |
||
12 | """ |
||
13 | |||
14 | from __future__ import unicode_literals |
||
15 | import errno |
||
16 | import os |
||
17 | import sys |
||
18 | import stat |
||
19 | import pytest |
||
20 | |||
21 | from cookiecutter import generate |
||
22 | from cookiecutter import utils |
||
23 | from cookiecutter.exceptions import FailedHookException |
||
24 | |||
25 | WINDOWS = sys.platform.startswith('win') |
||
26 | |||
27 | |||
28 | @pytest.fixture(scope='function') |
||
29 | def remove_additional_folders(request): |
||
30 | """ |
||
31 | Remove some special folders which are created by the tests. |
||
32 | """ |
||
33 | def fin_remove_additional_folders(): |
||
34 | directories_to_delete = [ |
||
35 | 'tests/test-pyhooks/inputpyhooks', |
||
36 | 'inputpyhooks', |
||
37 | 'inputhooks', |
||
38 | 'tests/test-shellhooks', |
||
39 | 'tests/test-hooks', |
||
40 | ] |
||
41 | for directory in directories_to_delete: |
||
42 | if os.path.exists(directory): |
||
43 | utils.rmtree(directory) |
||
44 | request.addfinalizer(fin_remove_additional_folders) |
||
45 | |||
46 | |||
47 | @pytest.mark.usefixtures('clean_system', 'remove_additional_folders') |
||
48 | def test_ignore_hooks_dirs(): |
||
49 | generate.generate_files( |
||
50 | context={ |
||
51 | 'cookiecutter': {'pyhooks': 'pyhooks'} |
||
52 | }, |
||
53 | repo_dir='tests/test-pyhooks/', |
||
54 | output_dir='tests/test-pyhooks/' |
||
55 | ) |
||
56 | assert not os.path.exists('tests/test-pyhooks/inputpyhooks/hooks') |
||
57 | |||
58 | |||
59 | @pytest.mark.usefixtures('clean_system', 'remove_additional_folders') |
||
60 | def test_run_python_hooks(): |
||
61 | generate.generate_files( |
||
62 | context={ |
||
63 | 'cookiecutter': {'pyhooks': 'pyhooks'} |
||
64 | }, |
||
65 | repo_dir='tests/test-pyhooks/'.replace("/", os.sep), |
||
66 | output_dir='tests/test-pyhooks/'.replace("/", os.sep) |
||
67 | ) |
||
68 | assert os.path.exists('tests/test-pyhooks/inputpyhooks/python_pre.txt') |
||
69 | assert os.path.exists('tests/test-pyhooks/inputpyhooks/python_post.txt') |
||
70 | |||
71 | |||
72 | @pytest.mark.usefixtures('clean_system', 'remove_additional_folders') |
||
73 | def test_run_python_hooks_cwd(): |
||
74 | generate.generate_files( |
||
75 | context={ |
||
76 | 'cookiecutter': {'pyhooks': 'pyhooks'} |
||
77 | }, |
||
78 | repo_dir='tests/test-pyhooks/' |
||
79 | ) |
||
80 | assert os.path.exists('inputpyhooks/python_pre.txt') |
||
81 | assert os.path.exists('inputpyhooks/python_post.txt') |
||
82 | |||
83 | |||
84 | @pytest.mark.skipif(WINDOWS, reason='OSError.errno=8 is not thrown on Windows') |
||
85 | @pytest.mark.usefixtures('clean_system', 'remove_additional_folders') |
||
86 | def test_empty_hooks(): |
||
87 | # OSError.errno=8 is not thrown on Windows when the script is empty |
||
88 | # because it always runs through shell instead of needing a shebang. |
||
89 | with pytest.raises(FailedHookException) as excinfo: |
||
90 | generate.generate_files( |
||
91 | context={ |
||
92 | 'cookiecutter': {'shellhooks': 'shellhooks'} |
||
93 | }, |
||
94 | repo_dir='tests/test-shellhooks-empty/', |
||
95 | overwrite_if_exists=True |
||
96 | ) |
||
97 | assert 'shebang' in str(excinfo.value) |
||
98 | |||
99 | |||
100 | @pytest.mark.usefixtures('clean_system', 'remove_additional_folders') |
||
101 | def test_oserror_hooks(mocker): |
||
102 | |||
103 | message = 'Out of memory' |
||
104 | |||
105 | err = OSError(message) |
||
106 | err.errno = errno.ENOMEM |
||
107 | |||
108 | prompt = mocker.patch('subprocess.Popen') |
||
109 | prompt.side_effect = err |
||
110 | |||
111 | with pytest.raises(FailedHookException) as excinfo: |
||
112 | generate.generate_files( |
||
113 | context={ |
||
114 | 'cookiecutter': {'shellhooks': 'shellhooks'} |
||
115 | }, |
||
116 | repo_dir='tests/test-shellhooks-empty/', |
||
117 | overwrite_if_exists=True |
||
118 | ) |
||
119 | assert message in str(excinfo.value) |
||
120 | |||
121 | |||
122 | View Code Duplication | @pytest.mark.usefixtures('clean_system', 'remove_additional_folders') |
|
0 ignored issues
–
show
Duplication
introduced
by
Loading history...
|
|||
123 | def test_run_failing_hook_removes_output_directory(): |
||
124 | repo_path = os.path.abspath('tests/test-hooks/') |
||
125 | hooks_path = os.path.abspath('tests/test-hooks/hooks') |
||
126 | |||
127 | hook_dir = os.path.join(repo_path, 'hooks') |
||
128 | template = os.path.join(repo_path, 'input{{cookiecutter.hooks}}') |
||
129 | os.mkdir(repo_path) |
||
130 | os.mkdir(hook_dir) |
||
131 | os.mkdir(template) |
||
132 | |||
133 | hook_path = os.path.join(hooks_path, 'pre_gen_project.py') |
||
134 | |||
135 | with open(hook_path, 'w') as f: |
||
136 | f.write("#!/usr/bin/env python\n") |
||
137 | f.write("import sys; sys.exit(1)\n") |
||
138 | |||
139 | with pytest.raises(FailedHookException) as excinfo: |
||
140 | generate.generate_files( |
||
141 | context={ |
||
142 | 'cookiecutter': {'hooks': 'hooks'} |
||
143 | }, |
||
144 | repo_dir='tests/test-hooks/', |
||
145 | overwrite_if_exists=True |
||
146 | ) |
||
147 | |||
148 | assert 'Hook script failed' in str(excinfo.value) |
||
149 | assert not os.path.exists('inputhooks') |
||
150 | |||
151 | |||
152 | View Code Duplication | @pytest.mark.usefixtures('clean_system', 'remove_additional_folders') |
|
0 ignored issues
–
show
|
|||
153 | def test_run_failing_hook_preserves_existing_output_directory(): |
||
154 | repo_path = os.path.abspath('tests/test-hooks/') |
||
155 | hooks_path = os.path.abspath('tests/test-hooks/hooks') |
||
156 | |||
157 | hook_dir = os.path.join(repo_path, 'hooks') |
||
158 | template = os.path.join(repo_path, 'input{{cookiecutter.hooks}}') |
||
159 | os.mkdir(repo_path) |
||
160 | os.mkdir(hook_dir) |
||
161 | os.mkdir(template) |
||
162 | |||
163 | hook_path = os.path.join(hooks_path, 'pre_gen_project.py') |
||
164 | |||
165 | with open(hook_path, 'w') as f: |
||
166 | f.write("#!/usr/bin/env python\n") |
||
167 | f.write("import sys; sys.exit(1)\n") |
||
168 | |||
169 | os.mkdir('inputhooks') |
||
170 | with pytest.raises(FailedHookException) as excinfo: |
||
171 | generate.generate_files( |
||
172 | context={ |
||
173 | 'cookiecutter': {'hooks': 'hooks'} |
||
174 | }, |
||
175 | repo_dir='tests/test-hooks/', |
||
176 | overwrite_if_exists=True |
||
177 | ) |
||
178 | |||
179 | assert 'Hook script failed' in str(excinfo.value) |
||
180 | assert os.path.exists('inputhooks') |
||
181 | |||
182 | |||
183 | def make_test_repo(name): |
||
184 | hooks = os.path.join(name, 'hooks') |
||
185 | template = os.path.join(name, 'input{{cookiecutter.shellhooks}}') |
||
186 | os.mkdir(name) |
||
187 | os.mkdir(hooks) |
||
188 | os.mkdir(template) |
||
189 | |||
190 | with open(os.path.join(template, 'README.rst'), 'w') as f: |
||
191 | f.write("foo\n===\n\nbar\n") |
||
192 | |||
193 | if sys.platform.startswith('win'): |
||
194 | filename = os.path.join(hooks, 'pre_gen_project.bat') |
||
195 | with open(filename, 'w') as f: |
||
196 | f.write("@echo off\n") |
||
197 | f.write("\n") |
||
198 | f.write("echo pre generation hook\n") |
||
199 | f.write("echo. >shell_pre.txt\n") |
||
200 | |||
201 | filename = os.path.join(hooks, 'post_gen_project.bat') |
||
202 | with open(filename, 'w') as f: |
||
203 | f.write("@echo off\n") |
||
204 | f.write("\n") |
||
205 | f.write("echo post generation hook\n") |
||
206 | f.write("echo. >shell_post.txt\n") |
||
207 | else: |
||
208 | filename = os.path.join(hooks, 'pre_gen_project.sh') |
||
209 | with open(filename, 'w') as f: |
||
210 | f.write("#!/bin/bash\n") |
||
211 | f.write("\n") |
||
212 | f.write("echo 'pre generation hook';\n") |
||
213 | f.write("touch 'shell_pre.txt'\n") |
||
214 | # Set the execute bit |
||
215 | os.chmod(filename, os.stat(filename).st_mode | stat.S_IXUSR) |
||
216 | |||
217 | filename = os.path.join(hooks, 'post_gen_project.sh') |
||
218 | with open(filename, 'w') as f: |
||
219 | f.write("#!/bin/bash\n") |
||
220 | f.write("\n") |
||
221 | f.write("echo 'post generation hook';\n") |
||
222 | f.write("touch 'shell_post.txt'\n") |
||
223 | # Set the execute bit |
||
224 | os.chmod(filename, os.stat(filename).st_mode | stat.S_IXUSR) |
||
225 | |||
226 | |||
227 | @pytest.mark.usefixtures('clean_system', 'remove_additional_folders') |
||
228 | def test_run_shell_hooks(): |
||
229 | make_test_repo('tests/test-shellhooks') |
||
230 | generate.generate_files( |
||
231 | context={ |
||
232 | 'cookiecutter': {'shellhooks': 'shellhooks'} |
||
233 | }, |
||
234 | repo_dir='tests/test-shellhooks/', |
||
235 | output_dir='tests/test-shellhooks/' |
||
236 | ) |
||
237 | shell_pre_file = 'tests/test-shellhooks/inputshellhooks/shell_pre.txt' |
||
238 | shell_post_file = 'tests/test-shellhooks/inputshellhooks/shell_post.txt' |
||
239 | assert os.path.exists(shell_pre_file) |
||
240 | assert os.path.exists(shell_post_file) |
||
241 |