-
-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathtest_extractcode_cli.py
More file actions
288 lines (227 loc) · 10.5 KB
/
Copy pathtest_extractcode_cli.py
File metadata and controls
288 lines (227 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
#
# Copyright (c) nexB Inc. and others. All rights reserved.
# ScanCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
# See https://github.com/nexB/extractcode for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#
import os
import subprocess
import pytest
from commoncode.fileutils import as_posixpath
from commoncode.fileutils import resource_iter
from commoncode.testcase import FileDrivenTesting
from commoncode.system import on_windows
test_env = FileDrivenTesting()
test_env.test_data_dir = os.path.join(os.path.dirname(__file__), 'data')
project_root = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
"""
These CLI tests are dependent on py.test monkeypatch to ensure we are testing
the actual command outputs as if using a TTY or not.
"""
def run_extract(options, expected_rc=None, cwd=None):
"""
Run extractcode as a plain subprocess. Return rc, stdout, stderr.
"""
bin_dir = 'Scripts' if on_windows else 'bin'
# note: this assumes that we are using a standard directory layout as set
# with the configure script
cmd_loc = os.path.join(project_root, 'tmp', bin_dir, 'extractcode')
assert os.path.exists(cmd_loc + ('.exe' if on_windows else ''))
args = [cmd_loc] + options
result = subprocess.run(args,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
cwd=cwd,
universal_newlines=True,
)
if expected_rc is not None and result.returncode != expected_rc:
opts = ' '.join(options)
error = f'''
Failure to run: extractcode {opts}:
stdout:
{result.stdout}
stderr:
{result.stderr}
'''
assert result.returncode == expected_rc, error
return result
def test_extractcode_command_can_take_an_empty_directory():
test_dir = test_env.get_temp_dir()
result = run_extract([test_dir], expected_rc=0)
assert 'Extracting archives...' in result.stderr
assert 'Extracting done' in result.stderr
def test_extractcode_command_does_extract_verbose():
test_dir = test_env.get_test_loc('cli/extract', copy=True)
result = run_extract(['--verbose', test_dir], expected_rc=1)
assert os.path.exists(os.path.join(test_dir, 'some.tar.gz-extract'))
try:
assert 'some.tar.gz' in result.stdout
assert 'tarred_gzipped.tgz' in result.stdout
assert 'Extracting archives...' in result.stderr
assert 'ERROR extracting' in result.stderr
assert 'broken.tar.gz' in result.stderr
assert "broken.tar.gz: Unrecognized archive format" in result.stderr
assert 'Extracting done.' in result.stderr
except:
assert [result.stderr, result.stdout] == []
def test_extractcode_command_always_shows_something_if_not_using_a_tty_verbose_or_not():
test_dir = test_env.get_test_loc('cli/extract/some.tar.gz', copy=True)
result = run_extract(options=['--verbose', test_dir], expected_rc=0)
assert 'Extracting archives...' in result.stderr
assert 'Extracting: some.tar.gz' in result.stdout
assert 'Extracting done.' in result.stderr
result = run_extract(options=[test_dir], expected_rc=0)
assert 'Extracting archives...' in result.stderr
assert 'Extracting done.' in result.stderr
def test_extractcode_command_works_with_relative_paths():
# The setup is complex because we want to have a relative dir to the base
# dir where we run tests from, i.e. the git checkout dir To use relative
# paths, we use our tmp dir at the root of the code tree
from os.path import join
from commoncode import fileutils
import extractcode
import tempfile
import shutil
try:
test_file = test_env.get_test_loc('cli/extract_relative_path/basic.zip')
project_tmp = join(project_root, 'tmp')
fileutils.create_dir(project_tmp)
temp_rel = tempfile.mkdtemp(dir=project_tmp)
assert os.path.exists(temp_rel)
relative_dir = temp_rel.replace(project_root, '').strip('\\/')
shutil.copy(test_file, temp_rel)
test_src_file = join(relative_dir, 'basic.zip')
test_tgt_dir = join(project_root, test_src_file) + extractcode.EXTRACT_SUFFIX
result = run_extract([test_src_file], expected_rc=0, cwd=project_root)
assert 'Extracting done' in result.stderr
assert not 'WARNING' in result.stderr
assert not 'ERROR' in result.stderr
expected = ['/c/a/a.txt', '/c/b/a.txt', '/c/c/a.txt']
file_result = [
as_posixpath(f.replace(test_tgt_dir, ''))
for f in fileutils.resource_iter(test_tgt_dir, with_dirs=False)]
assert sorted(expected) == sorted(file_result)
finally:
fileutils.delete(relative_dir)
def test_extractcode_command_works_with_relative_paths_verbose():
# The setup is a tad complex because we want to have a relative dir
# to the base dir where we run tests from, i.e. the git checkout dir
# To use relative paths, we use our tmp dir at the root of the code tree
from os.path import join
from commoncode import fileutils
import tempfile
import shutil
try:
project_tmp = join(project_root, 'tmp')
fileutils.create_dir(project_tmp)
test_src_dir = tempfile.mkdtemp(dir=project_tmp).replace(project_root, '').strip('\\/')
test_file = test_env.get_test_loc('cli/extract_relative_path/basic.zip')
shutil.copy(test_file, test_src_dir)
test_src_file = join(test_src_dir, 'basic.zip')
result = run_extract(['--verbose', test_src_file] , expected_rc=0)
# extract the path from the second line of the output
# check that the path is relative and not absolute
lines = result.stderr.splitlines(False)
line = lines[1]
line_path = line.split(':', 1)[-1].strip()
if on_windows:
drive = test_file[:2]
assert not line_path.startswith(drive)
else:
assert not line_path.startswith('/')
finally:
fileutils.delete(test_src_dir)
def test_usage_and_help_return_a_correct_script_name_on_all_platforms():
options = ['--help']
result = run_extract(options , expected_rc=0)
assert 'Usage: extractcode [OPTIONS]' in result.stdout
# this was showing up on Windows
assert 'extractcode-script.py' not in result.stderr
result = run_extract([])
assert 'Usage: extractcode [OPTIONS]' in result.stderr
# this was showing up on Windows
assert 'extractcode-script.py' not in result.stderr
result = run_extract(['-xyz'] , expected_rc=2)
# this was showing up on Windows
assert 'extractcode-script.py' not in result.stderr
def test_extractcode_command_can_extract_archive_with_unicode_names_verbose():
test_dir = test_env.get_test_loc('cli/unicodearch', copy=True)
result = run_extract(['--verbose', test_dir] , expected_rc=0)
assert 'Sanders' in result.stdout
file_result = [
f for f in map(as_posixpath, resource_iter(test_dir, with_dirs=False))
if not f.endswith('unicodepath.tgz')]
file_result = [''.join(f.partition('/unicodepath/')[1:]) for f in file_result]
file_result = [f for f in file_result if f]
expected = [
'/unicodepath/Ho_',
'/unicodepath/Ho_a',
'/unicodepath/koristenjem Karkkainen - Sander.pdf'
]
assert sorted(expected) == sorted(file_result)
def test_extractcode_command_can_extract_archive_with_unicode_names():
test_dir = test_env.get_test_loc('cli/unicodearch', copy=True)
run_extract([test_dir] , expected_rc=0)
file_result = [
f for f in map(as_posixpath, resource_iter(test_dir, with_dirs=False))
if not f.endswith('unicodepath.tgz')]
file_result = [''.join(f.partition('/unicodepath/')[1:]) for f in file_result]
file_result = [f for f in file_result if f]
expected = [
'/unicodepath/Ho_',
'/unicodepath/Ho_a',
'/unicodepath/koristenjem Karkkainen - Sander.pdf'
]
assert sorted(expected) == sorted(file_result)
def test_extractcode_command_can_extract_shallow():
test_dir = test_env.get_test_loc('cli/extract_shallow', copy=True)
run_extract(['--shallow', test_dir] , expected_rc=0)
file_result = [
f for f in map(as_posixpath, resource_iter(test_dir, with_dirs=False))
if not f.endswith('unicodepath.tgz')]
file_result = [''.join(f.partition('/top.zip-extract/')[1:]) for f in file_result]
file_result = [f for f in file_result if f]
# this checks that the zip in top.zip are not extracted
expected = [
'/top.zip-extract/some3.zip',
'/top.zip-extract/some2.zip',
'/top.zip-extract/some1.zip',
]
assert sorted(expected) == sorted(file_result)
def test_extractcode_command_can_ignore():
test_dir = test_env.get_test_loc('cli/extract_ignore', copy=True)
run_extract(['--ignore', '*.tar', test_dir] , expected_rc=0)
file_result = [
f for f in map(as_posixpath, resource_iter(test_dir, with_dirs=False))
if not f.endswith('a.tar') or not f.endswith('b.tar')]
file_result = [''.join(f.partition('/a.zip-extract/')[1:]) for f in file_result]
file_result = [f for f in file_result if f]
expected = [
'/a.zip-extract/a.txt',
'/a.zip-extract/b.zip',
'/a.zip-extract/b.zip-extract/b.txt',
'/a.zip-extract/c.tar',
]
assert sorted(expected) == sorted(file_result)
def test_extractcode_command_does_not_crash_with_replace_originals_and_corrupted_archives():
test_dir = test_env.get_test_loc('cli/replace-originals', copy=True)
result = run_extract(['--replace-originals', '--verbose', test_dir] , expected_rc=1)
assert not os.path.exists(os.path.join(test_dir, 'rake.1.gz-extract'))
assert 'rake.1.gz' in result.stdout
assert 'Extracting archives...' in result.stderr
assert 'ERROR extracting' in result.stderr
assert 'rake.1.gz' in result.stderr
assert 'Not a gzipped file ' in result.stderr
assert 'issue6550.gz' in result.stderr
assert ' too many length or distance symbols' in result.stderr
assert 'Extracting done.' in result.stderr
@pytest.mark.skipif(on_windows, reason='FIXME: this test fails on Windows until we have support for long file names.')
def test_extractcode_command_can_extract_nuget():
test_dir = test_env.get_test_loc('cli/extract_nuget', copy=True)
result = run_extract(['--verbose', test_dir])
if result.returncode != 0:
print(result.stdout)
assert 'ERROR extracting' not in result.stdout
assert 'ERROR extracting' not in result.stderr