Improve coverage
[rarfile.git] / test / test_api.py
blobdfa3369b3ecd40b9637a3c5b898edc367991651c
1 """API tests.
2 """
4 import io
5 import os
6 from pathlib import Path
8 import pytest
10 import rarfile
14 # test start
17 def test_not_rar():
18 with pytest.raises(rarfile.NotRarFile):
19 rarfile.RarFile('rarfile.py', 'r')
20 with pytest.raises(rarfile.NotRarFile):
21 with open('rarfile.py', 'rb') as f:
22 rarfile.RarFile(f, 'r')
25 def test_bad_arc_mode_w():
26 with pytest.raises(NotImplementedError):
27 rarfile.RarFile('test/files/rar3-comment-plain.rar', 'w')
30 def test_bad_arc_mode_rb():
31 with pytest.raises(NotImplementedError):
32 rarfile.RarFile('test/files/rar3-comment-plain.rar', 'rb')
35 def test_bad_errs():
36 with pytest.raises(ValueError):
37 rarfile.RarFile('test/files/rar3-comment-plain.rar', 'r', errors='foo')
40 def test_bad_open_mode_w():
41 rf = rarfile.RarFile('test/files/rar3-comment-plain.rar')
42 with pytest.raises(NotImplementedError):
43 rf.open('qwe', 'w')
46 def test_bad_open_psw():
47 rf = rarfile.RarFile('test/files/rar3-comment-psw.rar')
48 with pytest.raises(rarfile.PasswordRequired):
49 rf.open('file1.txt')
52 def test_bad_filelike():
53 with pytest.raises(ValueError):
54 rarfile.is_rarfile(bytearray(10))
57 def test_open_psw_late_rar3():
58 rf = rarfile.RarFile('test/files/rar3-comment-psw.rar')
59 d1 = rf.open('file1.txt', 'r', 'password').read()
60 d2 = rf.open('file1.txt', 'r', b'password').read()
61 assert d1 == d2
64 def test_open_psw_late_rar5():
65 rf = rarfile.RarFile('test/files/rar5-psw.rar')
66 rf.open('stest1.txt', 'r', 'password').read()
67 rf.open('stest1.txt', 'r', b'password').read()
70 def test_open_pathlib_path():
71 rf = rarfile.RarFile('test/files/rar5-psw.rar')
72 rf.open(Path('stest1.txt'), 'r', 'password').read()
75 def test_read_psw_late_rar3():
76 rf = rarfile.RarFile('test/files/rar3-comment-psw.rar')
77 rf.read('file1.txt', 'password')
78 rf.read('file1.txt', b'password')
81 def test_read_psw_late_rar5():
82 rf = rarfile.RarFile('test/files/rar5-psw.rar')
83 rf.read('stest1.txt', 'password')
84 rf.read('stest1.txt', b'password')
87 def test_open_psw_late():
88 rf = rarfile.RarFile('test/files/rar5-psw.rar')
89 with pytest.raises(rarfile.BadRarFile):
90 rf.read('stest1.txt', 'password222')
93 def test_create_from_pathlib_path():
94 # Make sure we can open both relative and absolute Paths
95 rarfile.RarFile(Path('test/files/rar5-psw.rar'))
96 rarfile.RarFile(Path('test/files/rar5-psw.rar').resolve())
99 def test_detection():
100 assert rarfile.is_rarfile('test/files/ctime4.rar.exp') is False
101 assert rarfile.is_rarfile('test/files/ctime4.rar') is True
102 assert rarfile.is_rarfile('test/files/rar5-crc.rar') is True
104 assert rarfile.is_rarfile(Path('test/files/rar5-crc.rar')) is True
107 def test_signature_error():
108 with pytest.raises(rarfile.NotRarFile):
109 rarfile.RarFile('test/files/ctime4.rar.exp')
112 def test_signature_error_mem():
113 data = io.BytesIO(b'x' * 40)
114 with pytest.raises(rarfile.NotRarFile):
115 rarfile.RarFile(data)
118 def test_with():
119 with rarfile.RarFile('test/files/rar5-crc.rar') as rf:
120 data = rf.read('stest1.txt')
121 with rf.open('stest1.txt') as f:
122 dst = io.BytesIO()
123 while True:
124 buf = f.read(7)
125 if not buf:
126 break
127 dst.write(buf)
128 assert dst.getvalue() == data
131 def test_readline():
132 def load_readline(rf, fn):
133 with rf.open(fn) as f:
134 tr = io.TextIOWrapper(io.BufferedReader(f))
135 res = []
136 while True:
137 ln = tr.readline()
138 if not ln:
139 break
140 res.append(ln)
141 return res
143 rf = rarfile.RarFile('test/files/seektest.rar')
144 v1 = load_readline(rf, 'stest1.txt')
145 v2 = load_readline(rf, 'stest2.txt')
146 assert len(v1) == 512
147 assert v1 == v2
150 def test_printdir(capsys):
151 rf = rarfile.RarFile('test/files/seektest.rar')
152 rf.printdir()
153 res = capsys.readouterr()
154 assert res.out == 'stest1.txt\nstest2.txt\n'
157 def test_testrar():
158 rf = rarfile.RarFile('test/files/seektest.rar')
159 rf.testrar()
162 def test_iter():
163 rf = rarfile.RarFile('test/files/seektest.rar')
164 n1 = rf.namelist()
165 n2 = [m.filename for m in rf]
166 assert n1 == n2
169 def test_testrar_mem():
170 with open('test/files/seektest.rar', 'rb') as f:
171 arc = f.read()
172 rf = rarfile.RarFile(io.BytesIO(arc))
173 rf.testrar()
176 def test_extract(tmp_path):
177 ex1 = tmp_path / "extract1"
178 ex2 = tmp_path / "extract2"
179 ex3 = tmp_path / "extract3"
180 os.makedirs(str(ex1))
181 os.makedirs(str(ex2))
182 os.makedirs(str(ex3))
183 rf = rarfile.RarFile('test/files/seektest.rar')
185 rf.extractall(str(ex1))
186 assert os.path.isfile(str(ex1 / 'stest1.txt')) is True
187 assert os.path.isfile(str(ex1 / 'stest2.txt')) is True
189 rf.extract('stest1.txt', str(ex2))
190 assert os.path.isfile(str(ex2 / 'stest1.txt')) is True
191 assert os.path.isfile(str(ex2 / 'stest2.txt')) is False
193 inf = rf.getinfo('stest2.txt')
194 rf.extract(inf, str(ex3))
195 assert os.path.isfile(str(ex3 / 'stest1.txt')) is False
196 assert os.path.isfile(str(ex3 / 'stest2.txt')) is True
198 rf.extractall(str(ex2), ['stest1.txt'])
199 assert os.path.isfile(str(ex2 / 'stest1.txt')) is True
201 rf.extractall(str(ex3), [rf.getinfo('stest2.txt')])
202 assert os.path.isfile(str(ex3 / 'stest2.txt')) is True
204 ex4 = tmp_path / "extract4"
205 os.makedirs(str(ex4))
206 rf.extractall(ex4)
207 assert os.path.isfile(str(ex4 / 'stest1.txt')) is True
208 assert os.path.isfile(str(ex4 / 'stest2.txt')) is True
211 def test_extract_mem(tmp_path):
212 ex1 = tmp_path / "extract11"
213 ex2 = tmp_path / "extract22"
214 ex3 = tmp_path / "extract33"
215 os.makedirs(str(ex1))
216 os.makedirs(str(ex2))
217 os.makedirs(str(ex3))
219 with open('test/files/seektest.rar', 'rb') as f:
220 arc = f.read()
221 rf = rarfile.RarFile(io.BytesIO(arc))
223 rf.extractall(str(ex1))
224 assert os.path.isfile(str(ex1 / 'stest1.txt')) is True
225 assert os.path.isfile(str(ex1 / 'stest2.txt')) is True
227 rf.extract('stest1.txt', str(ex2))
228 assert os.path.isfile(str(ex2 / 'stest1.txt')) is True
229 assert os.path.isfile(str(ex2 / 'stest2.txt')) is False
231 inf = rf.getinfo('stest2.txt')
232 rf.extract(inf, str(ex3))
233 assert os.path.isfile(str(ex3 / 'stest1.txt')) is False
234 assert os.path.isfile(str(ex3 / 'stest2.txt')) is True
236 def get_rftype(h):
237 assert h.is_dir() == h.isdir()
238 return "".join([
239 h.is_file() and "F" or "-",
240 h.is_dir() and "D" or "-",
241 h.is_symlink() and "L" or "-",
245 def test_infocb():
246 infos = []
248 def info_cb(info):
249 infos.append((info.type, info.needs_password(), get_rftype(info), info._must_disable_hack()))
251 rf = rarfile.RarFile('test/files/seektest.rar', info_callback=info_cb)
252 assert infos == [
253 (rarfile.RAR_BLOCK_MAIN, False, "---", False),
254 (rarfile.RAR_BLOCK_FILE, False, "F--", False),
255 (rarfile.RAR_BLOCK_FILE, False, "F--", False),
256 (rarfile.RAR_BLOCK_ENDARC, False, "---", False)]
258 infos = []
259 rf = rarfile.RarFile('test/files/rar5-solid-qo.rar', info_callback=info_cb)
260 assert infos == [
261 (rarfile.RAR_BLOCK_MAIN, False, "---", True),
262 (rarfile.RAR_BLOCK_FILE, False, "F--", False),
263 (rarfile.RAR_BLOCK_FILE, False, "F--", True),
264 (rarfile.RAR_BLOCK_FILE, False, "F--", True),
265 (rarfile.RAR_BLOCK_FILE, False, "F--", True),
266 (rarfile.RAR_BLOCK_SUB, False, "---", False),
267 (rarfile.RAR_BLOCK_ENDARC, False, "---", False)]