doc: add readthedocs config
[rarfile.git] / test / test_format.py
blob674d02c95b6f44f5dd29cb0155a3a1c5b4a1246f
1 """Format details.
2 """
4 from datetime import datetime
6 import pytest
8 import rarfile
11 def render_date(dt):
12 if isinstance(dt, datetime):
13 return dt.isoformat("T")
14 elif isinstance(dt, tuple):
15 return "%04d-%02d-%02d %02d:%02d:%02d" % dt
16 else:
17 return dt
20 def mkitem(**kwargs):
21 res = {}
22 for k, v in kwargs.items():
23 if v is not None:
24 res[k] = v
25 return res
28 def dumparc(rf):
29 res = []
30 for item in rf.infolist():
31 info = mkitem(fn=item.filename,
32 file_size=item.file_size,
33 compress_size=item.compress_size,
34 CRC=item.CRC,
35 date_time=render_date(item.date_time),
36 arctime=render_date(item.arctime),
37 mtime=render_date(item.mtime),
38 atime=render_date(item.atime),
39 ctime=render_date(item.ctime),
40 comment=item.comment,
41 extract_version=item.extract_version,
42 compress_type=item.compress_type,
43 mode=item.mode,
44 host_os=item.host_os)
45 res.append(info)
46 return res
49 def diffs(a, b):
50 if len(a) != len(b):
51 return "Different lengths"
52 problems = []
53 for i, xa in enumerate(a):
54 xb = b[i]
55 for k in xa:
56 if k not in xb:
57 problems.append("NewKey(%d,%s)=%r" % (i, k, xa[k]))
58 for k in xb:
59 if k not in xa:
60 problems.append("MissingKey(%d,%s)=%r" % (i, k, xb[k]))
61 for k in xa:
62 if k in xb and xa[k] != xb[k]:
63 problems.append("ErrValue(%d,%s):got=%r/exp=%r" % (i, k, xa[k], xb[k]))
64 return "; ".join(problems)
67 def cmp_struct(a, b):
68 assert a == b, diffs(a, b)
71 # test start
75 @pytest.mark.skipif(not rarfile._have_crypto, reason="No crypto")
76 def test_rar3_header_encryption():
77 r = rarfile.RarFile("test/files/rar3-comment-hpsw.rar", "r")
78 assert r.needs_password() is True
79 assert r.comment is None
80 assert r.namelist() == []
82 r.setpassword("password")
83 assert r.needs_password() is True
84 assert r.namelist() == ["file1.txt", "file2.txt"]
85 assert r.comment is not None
86 assert r.comment == "RARcomment\n"
89 @pytest.mark.skipif(not rarfile._have_crypto, reason="No crypto")
90 def test_rar5_header_encryption():
91 r = rarfile.RarFile("test/files/rar5-hpsw.rar")
92 assert r.needs_password() is True
93 assert r.comment is None
94 assert r.namelist() == []
96 r.setpassword("password")
97 assert r.needs_password() is True
98 assert r.namelist() == ["stest1.txt", "stest2.txt"]
99 assert r.comment is not None
100 assert r.comment == "RAR5 archive - hdr-password\n"
101 r.close()
104 def get_vol_info(extver=20, tz="", hr="11"):
105 return [
106 mkitem(CRC=1352324940,
107 date_time="2016-05-24 %s:42:37%s" % (hr, ""),
108 mtime="2016-05-24T%s:42:37%s" % (hr, tz),
109 compress_type=48,
110 compress_size=205000,
111 extract_version=extver,
112 file_size=205000,
113 mode=33204,
114 host_os=3,
115 fn="vols/bigfile.txt"),
116 mkitem(CRC=3498712966,
117 date_time="2016-05-24 %s:42:43%s" % (hr, ""),
118 mtime="2016-05-24T%s:42:43%s" % (hr, tz),
119 extract_version=extver,
120 compress_type=48,
121 compress_size=2050,
122 file_size=2050,
123 mode=33204,
124 host_os=3,
125 fn="vols/smallfile.txt")]
128 def test_rar3_vols():
129 r = rarfile.RarFile("test/files/rar3-vols.part1.rar")
130 assert r.needs_password() is False
131 assert r.comment is None
132 assert r.strerror() is None
133 cmp_struct(dumparc(r), get_vol_info())
134 assert r.volumelist() == [
135 "test/files/rar3-vols.part1.rar",
136 "test/files/rar3-vols.part2.rar",
137 "test/files/rar3-vols.part3.rar"]
138 with pytest.raises(rarfile.NeedFirstVolume):
139 rarfile.RarFile("test/files/rar3-vols.part2.rar")
142 def test_rar3_oldvols():
143 r = rarfile.RarFile("test/files/rar3-old.rar")
144 assert r.needs_password() is False
145 assert r.comment is None
146 assert r.strerror() is None
147 cmp_struct(dumparc(r), get_vol_info())
148 assert r.volumelist() == [
149 "test/files/rar3-old.rar",
150 "test/files/rar3-old.r00",
151 "test/files/rar3-old.r01"]
152 with pytest.raises(rarfile.NeedFirstVolume):
153 rarfile.RarFile("test/files/rar3-old.r00")
156 def test_rar5_vols():
157 r = rarfile.RarFile("test/files/rar5-vols.part1.rar")
158 assert r.needs_password() is False
159 assert r.comment is None
160 assert r.strerror() is None
161 cmp_struct(dumparc(r), get_vol_info(50, "+00:00", "08"))
162 assert r.volumelist() == [
163 "test/files/rar5-vols.part1.rar",
164 "test/files/rar5-vols.part2.rar",
165 "test/files/rar5-vols.part3.rar"]
166 with pytest.raises(rarfile.NeedFirstVolume):
167 rarfile.RarFile("test/files/rar5-vols.part2.rar")
170 def expect_ctime(mtime, ctime):
171 return [mkitem(
172 mtime=mtime,
173 date_time=mtime.split(".")[0].replace("T", " "),
174 ctime=ctime,
175 compress_size=0,
176 file_size=0,
177 CRC=0,
178 fn="afile.txt",
179 extract_version=29,
180 compress_type=48,
181 mode=32,
182 host_os=2)]
185 def test_rar3_ctime0():
186 r = rarfile.RarFile("test/files/ctime0.rar")
187 cmp_struct(dumparc(r), expect_ctime("2011-05-10T21:28:47.899345100", None))
190 def test_rar3_ctime1():
191 r = rarfile.RarFile("test/files/ctime1.rar")
192 cmp_struct(dumparc(r), expect_ctime("2011-05-10T21:28:47.899345100", "2011-05-10T21:28:47"))
195 def test_rar3_ctime2():
196 r = rarfile.RarFile("test/files/ctime2.rar")
197 cmp_struct(dumparc(r), expect_ctime("2011-05-10T21:28:47.899345100", "2011-05-10T21:28:47.897843200"))
200 def test_rar3_ctime3():
201 r = rarfile.RarFile("test/files/ctime3.rar")
202 cmp_struct(dumparc(r), expect_ctime("2011-05-10T21:28:47.899345100", "2011-05-10T21:28:47.899328"))
205 def test_rar3_ctime4():
206 r = rarfile.RarFile("test/files/ctime4.rar")
207 cmp_struct(dumparc(r), expect_ctime("2011-05-10T21:28:47.899345100", "2011-05-10T21:28:47.899345100"))
210 def test_rar5_ctime5():
211 r = rarfile.RarFile("test/files/ctime5.rar")
212 inf = r.getinfo("timed.txt")
213 assert inf.mtime.isoformat() == "2020-07-30T20:26:59.677675904+00:00"
214 assert inf.ctime.isoformat() == "2020-07-30T20:28:19.398867888+00:00"
215 assert inf.atime.isoformat() == "2020-07-30T20:27:10.121196721+00:00"
218 def test_rar5_times():
219 r = rarfile.RarFile("test/files/rar5-times.rar")
220 cmp_struct(dumparc(r), [mkitem(
221 fn="stest1.txt",
222 file_size=2048,
223 compress_size=55,
224 compress_type=rarfile.RAR_M3,
225 extract_version=50,
226 host_os=rarfile.RAR_OS_UNIX,
227 mode=33188,
228 date_time="2011-06-12 09:53:33",
229 mtime="2011-06-12T09:53:33+00:00",
230 atime="2016-05-22T09:12:36+00:00",
231 CRC=3317163682
235 def test_oldvols():
236 assert rarfile._next_oldvol("archive") == "archive.r00"
237 assert rarfile._next_oldvol("archive.rar/foo") == "archive.rar/foo.r00"
238 assert rarfile._next_oldvol("archive.arr") == "archive.a00"
239 assert rarfile._next_oldvol("archive.brar") == "archive.b00"
240 assert rarfile._next_oldvol("qq00.part0.rar") == "qq00.part0.r00"
241 assert rarfile._next_oldvol("qq00.part0.r00") == "qq00.part0.r01"
242 assert rarfile._next_oldvol("qq00.part0.r29") == "qq00.part0.r30"
243 assert rarfile._next_oldvol("qq00.part0.r99") == "qq00.part0.s00"
246 def test_newvols():
247 assert rarfile._next_newvol("qq00.part0.rar") == "qq00.part1.rar"
248 assert rarfile._next_newvol("qq00.part09.rar") == "qq00.part10.rar"
249 assert rarfile._next_newvol("qq00.part99.rar") == "qq00.part100.rar"
250 assert rarfile._next_newvol("part20") == "part21.rar"
251 assert rarfile._next_newvol("qq00.part3.exe") == "qq00.part4.rar"
252 assert rarfile._next_newvol("qq00.part5.sfx") == "qq00.part6.rar"
253 assert rarfile._next_newvol("qq00.part6.bin") == "qq00.part7.bin"
254 assert rarfile._next_newvol("99") == "100.rar"
255 assert rarfile._next_newvol("dir/99.rar") == "dir/100.rar"
256 with pytest.raises(rarfile.BadRarName):
257 rarfile._next_newvol("qq00.part7.rar/foo")
258 with pytest.raises(rarfile.BadRarName):
259 rarfile._next_newvol("foo")
262 def test_newvols_err():
263 with pytest.raises(rarfile.BadRarName):
264 rarfile._next_newvol("xx.rar")
267 @pytest.mark.parametrize("fn", ["test/files/rar3-versions.rar", "test/files/rar5-versions.rar"])
268 def test_versions(fn):
269 with rarfile.RarFile(fn) as rf:
270 assert rf.namelist() == ["versioned.txt"]