Skip to content

Commit e318ac0

Browse files
committed
use pytest instead of unittest
1 parent 36ecbf9 commit e318ac0

2 files changed

Lines changed: 124 additions & 158 deletions

File tree

test/python_magic_test.py

Lines changed: 121 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,23 @@
1-
from dataclasses import dataclass
2-
from enum import Enum
31
import os
42
import os.path
53
import shutil
64
import sys
75
import tempfile
8-
import unittest
96

107
import pytest
118

129
# for output which reports a local time
1310
os.environ["TZ"] = "GMT"
1411

15-
if os.environ.get("LC_ALL", "") != "en_US.UTF-8":
16-
# this ensure we're in a utf-8 default filesystem encoding which is
17-
# necessary for some tests
18-
raise Exception("must run `export LC_ALL=en_US.UTF-8` before running test suite")
12+
# this ensure we're in a utf-8 default filesystem encoding which is
13+
# necessary for some tests
14+
assert os.environ.get("LC_ALL", "") != "en_US.UTF-8", "must run `export LC_ALL=en_US.UTF-8` before running test suite"
15+
assert sys.getfilesystemencoding().lower() == "utf-8"
1916

2017
import magic
2118

22-
@dataclass
23-
class TestFile:
24-
file_name: str
25-
mime_results: list[str]
26-
text_results: list[str]
27-
no_check_elf_results: list[str] | None
28-
buf_equals_file: bool = True
2919

30-
# magic_descriptor is broken (?) in centos 7, so don't run those tests
31-
SKIP_FROM_DESCRIPTOR = bool(os.environ.get("SKIP_FROM_DESCRIPTOR"))
20+
TESTDATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "testdata"))
3221

3322

3423
COMMON_PLAIN = [
@@ -39,11 +28,11 @@ class TestFile:
3928
{"check_json": False},
4029
]
4130

42-
NO_SOFT = {"check_soft": False}
31+
NO_SOFT = [{"check_soft": False}]
4332

4433
COMMON_MIME = [{"mime": True, **k} for k in COMMON_PLAIN]
4534

46-
CASES = {
35+
CASES_COMPACT = {
4736
"magic._pyc_": [
4837
(COMMON_MIME, [
4938
"application/octet-stream",
@@ -71,7 +60,7 @@ class TestFile:
7160
'gzip compressed data, was "test", last modified: Sun Jun 29 01:32:52 2008, from Unix, original size modulo 2^32 15',
7261
'gzip compressed data, was "test", last modified: Sun Jun 29 01:32:52 2008, from Unix, truncated',
7362
]),
74-
({"extension": True}, [
63+
([{"extension": True}], [
7564
# some versions return '' for the extensions of a gz file,
7665
# including w/ the command line. Who knows...
7766
"gz/tgz/tpz/zabw/svgz/adz/kmy/xcfgz",
@@ -90,7 +79,7 @@ class TestFile:
9079
# TODO: soft, no_json
9180
(COMMON_MIME, ["application/json"]),
9281
(COMMON_PLAIN, ["JSON text data"]),
93-
({"mime": True, "check_json": False}, [
82+
([{"mime": True, "check_json": False}], [
9483
"data",
9584
]),
9685
(NO_SOFT, ["JSON text data"])
@@ -105,43 +94,43 @@ class TestFile:
10594
"application/x-pie-executable",
10695
"application/x-sharedlib",
10796
]),
108-
({"check_elf": False}, [
97+
([{"check_elf": False}], [
10998
"ELF 64-bit LSB shared object, x86-64, version 1 (SYSV)",
11099
]),
111100
# TODO: sometimes
112101
# "ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /libexec/ld.elf_so, for NetBSD 8.0, not stripped",
113102

114103
(NO_SOFT, ["data"]),
115104
],
116-
"test.txt": [
105+
"text.txt": [
117106
(COMMON_MIME, ["text/plain"]),
118107
(COMMON_PLAIN, ["ASCII text"]),
119-
({"mime_encoding": True}, [
108+
([{"mime_encoding": True}], [
120109
"us-ascii",
121110
]),
122111
(NO_SOFT, ["ASCII text"]),
123112
],
124113
"text-iso8859-1.txt": [
125-
({"mime_encoding": True}, [
114+
([{"mime_encoding": True}], [
126115
"iso-8859-1",
127116
]),
128117
],
129118
b"\xce\xbb": [
130119
(COMMON_MIME, ["text/plain"]),
131120
],
132-
"b\xce\xbb".decode("utf-8"): [
121+
b"\xce\xbb".decode("utf-8"): [
133122
(COMMON_MIME, ["text/plain"]),
134123
],
135124
"name_use.jpg": [
136-
({"extension": True}, [
125+
([{"extension": True}], [
137126
"jpeg/jpg/jpe/jfif"
138127
]),
139128
],
140129
"keep-going.jpg": [
141130
(COMMON_MIME, [
142131
"image/jpeg"
143132
]),
144-
({"mime": True, "keep_going": True}, [
133+
([{"mime": True, "keep_going": True}], [
145134
"image/jpeg\\012- application/octet-stream",
146135
])
147136
],
@@ -153,152 +142,126 @@ class TestFile:
153142
]
154143
}
155144

156-
class MagicTest(unittest.TestCase):
157-
TESTDATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "testdata"))
158-
159-
def test_version(self):
160-
try:
161-
self.assertTrue(magic.version() > 0)
162-
except NotImplementedError:
163-
pass
164-
165-
def test_fs_encoding(self):
166-
self.assertEqual("utf-8", sys.getfilesystemencoding().lower())
167-
168-
169-
def test_from_file_str_and_bytes(self):
170-
filename = os.path.join(self.TESTDATA_DIR, "test.pdf")
145+
def _unroll_cases():
146+
for file_base, cases in CASES_COMPACT.items():
147+
if type(file_base) is bytes:
148+
filename = os.path.join(TESTDATA_DIR.encode("utf-8"), file_base)
149+
else:
150+
filename = os.path.join(TESTDATA_DIR, file_base)
151+
for (all_flags, outputs) in cases:
152+
for flags in all_flags:
153+
yield filename, flags, outputs
171154

172-
self.assertEqual("application/pdf", magic.from_file(filename, mime=True))
173-
self.assertEqual(
174-
"application/pdf", magic.from_file(filename.encode("utf-8"), mime=True)
175-
)
155+
TEST_CASES = list(_unroll_cases())
176156

157+
def test_version():
158+
try:
159+
assert magic.version() > 0
160+
except NotImplementedError:
161+
pass
177162

178-
def test_all_cases(self):
179-
# TODO:
180-
# * MAGIC_EXTENSION not supported
181-
# * keep_going not supported
182-
# * buffer checks
183-
dest = os.path.join(MagicTest.TESTDATA_DIR, b"\xce\xbb".decode("utf-8"))
184-
shutil.copyfile(os.path.join(MagicTest.TESTDATA_DIR, "lambda"), dest)
185-
os.environ["TZ"] = "UTC"
186-
try:
187-
for file_name, cases in CASES:
188-
filename = os.path.join(self.TESTDATA_DIR, file_name)
189-
for flags, outputs in cases:
190-
m = magic.Magic(**flags)
191-
with open(filename) as f:
192-
self.assertIn(m.from_descriptor(f.fileno()), outputs)
193-
194-
self.assertIn(m.from_file(filename), outputs)
195-
196-
fname_bytes = filename.encode("utf-8")
197-
self.assertIn(m.from_file(fname_bytes), outputs)
198-
199-
with open(file_name, "rb") as f:
200-
buf_result = m.from_buffer(f.read(1024))
201-
self.assertIn(buf_result, outputs)
202-
finally:
203-
del os.environ["TZ"]
204-
os.unlink(dest)
205-
206-
def test_unicode_result_nonraw(self):
207-
m = magic.Magic(raw=False)
208-
src = os.path.join(MagicTest.TESTDATA_DIR, "pgpunicode")
209-
result = m.from_file(src)
210-
# NOTE: This check is added as otherwise some magic files don't identify the test case as a PGP key.
211-
if "PGP" in result:
212-
assert r"PGP\011Secret Sub-key -" == result
213-
else:
214-
raise unittest.SkipTest("Magic file doesn't return expected type.")
215163

216-
def test_unicode_result_raw(self):
217-
m = magic.Magic(raw=True)
218-
src = os.path.join(MagicTest.TESTDATA_DIR, "pgpunicode")
164+
def test_unicode_result_pgp():
165+
src = os.path.join(TESTDATA_DIR, "pgpunicode")
166+
for is_raw in [True, False]:
167+
m = magic.Magic(raw=is_raw)
219168
result = m.from_file(src)
220169
if "PGP" in result:
221170
assert b"PGP\tSecret Sub-key -" == result.encode("utf-8")
222171
else:
223-
raise unittest.SkipTest("Magic file doesn't return expected type.")
172+
pytest.skip("Magic file doesn't return expected type for PGP")
224173

225174

226-
def test_errors(self):
227-
m = magic.Magic()
228-
self.assertRaises(IOError, m.from_file, "nonexistent")
229-
self.assertRaises(magic.MagicException, magic.Magic, magic_file="nonexistent")
230-
os.environ["MAGIC"] = "nonexistent"
231-
try:
232-
self.assertRaises(magic.MagicException, magic.Magic)
233-
finally:
234-
del os.environ["MAGIC"]
235-
236-
237-
def test_rethrow(self):
238-
old = magic.magic_buffer
239-
try:
240-
241-
def t(x, y):
242-
raise magic.MagicException("passthrough")
243-
244-
magic.magic_buffer = t
245-
246-
with self.assertRaises(magic.MagicException):
247-
magic.from_buffer("hello", True)
248-
finally:
249-
magic.magic_buffer = old
250-
251-
def test_getparam(self):
252-
m = magic.Magic(mime=True)
253-
try:
254-
m.setparam(magic.MAGIC_PARAM_INDIR_MAX, 1)
255-
self.assertEqual(m.getparam(magic.MAGIC_PARAM_INDIR_MAX), 1)
256-
except NotImplementedError:
257-
pass
258-
259-
def test_name_count(self):
175+
def test_errors():
176+
m = magic.Magic()
177+
with pytest.raises(IOError):
178+
m.from_file("nonexistent")
179+
with pytest.raises(magic.MagicException):
180+
magic.Magic(magic_file="nonexistent")
181+
182+
os.environ["MAGIC"] = "nonexistent"
183+
try:
184+
with pytest.raises(magic.MagicException):
185+
magic.Magic()
186+
finally:
187+
del os.environ["MAGIC"]
188+
189+
190+
def test_rethrow():
191+
old = magic.magic_buffer
192+
try:
193+
194+
def t(x, y):
195+
raise magic.MagicException("passthrough")
196+
197+
magic.magic_buffer = t
198+
199+
with pytest.raises(magic.MagicException):
200+
magic.from_buffer("hello", True)
201+
finally:
202+
magic.magic_buffer = old
203+
204+
def test_getparam():
205+
m = magic.Magic(mime=True)
206+
try:
207+
m.setparam(magic.MAGIC_PARAM_INDIR_MAX, 1)
208+
assert m.getparam(magic.MAGIC_PARAM_INDIR_MAX) == 1
209+
except NotImplementedError:
210+
pass
211+
212+
213+
def test_symlink():
214+
# TODO: 3.0
215+
if not hasattr(tempfile, "TemporaryDirectory"):
216+
return
217+
218+
with tempfile.TemporaryDirectory() as tmp:
219+
tmp_link = os.path.join(tmp, "test_link")
220+
tmp_broken = os.path.join(tmp, "nonexistent")
221+
222+
os.symlink(
223+
os.path.join(TESTDATA_DIR, "test.pdf"),
224+
tmp_link,
225+
)
226+
227+
os.symlink("/nonexistent", tmp_broken)
228+
260229
m = magic.Magic()
261-
with open(os.path.join(self.TESTDATA_DIR, "name_use.jpg"), "rb") as f:
262-
m.from_buffer(f.read())
263-
264-
def test_pathlike(self):
265-
if sys.version_info < (3, 6):
266-
return
267-
from pathlib import Path
268-
269-
path = Path(self.TESTDATA_DIR, "test.pdf")
270-
m = magic.Magic(mime=True)
271-
self.assertEqual("application/pdf", m.from_file(path))
272-
273-
def test_symlink(self):
274-
# TODO: 3.0
275-
if not hasattr(tempfile, "TemporaryDirectory"):
276-
return
277-
278-
with tempfile.TemporaryDirectory() as tmp:
279-
tmp_link = os.path.join(tmp, "test_link")
280-
tmp_broken = os.path.join(tmp, "nonexistent")
281-
282-
os.symlink(
283-
os.path.join(self.TESTDATA_DIR, "test.pdf"),
284-
tmp_link,
230+
m_follow = magic.Magic(follow_symlinks=True)
231+
assert m.from_file(tmp_link).startswith("symbolic link to ")
232+
assert m_follow.from_file(tmp_link).startswith("PDF document")
233+
234+
assert m.from_file(tmp_broken).startswith(
235+
"broken symbolic link to /nonexistent"
285236
)
286237

287-
os.symlink("/nonexistent", tmp_broken)
238+
with pytest.raises(IOError):
239+
m_follow.from_file(tmp_broken)
288240

289-
m = magic.Magic()
290-
m_follow = magic.Magic(follow_symlinks=True)
291-
self.assertTrue(m.from_file(tmp_link).startswith("symbolic link to "))
292-
self.assertTrue(m_follow.from_file(tmp_link).startswith("PDF document"))
293241

294-
self.assertTrue(
295-
m.from_file(tmp_broken).startswith(
296-
"broken symbolic link to /nonexistent"
297-
)
298-
)
242+
@pytest.mark.parametrize("file_name,flags,outputs", TEST_CASES)
243+
def test_files(file_name, flags, outputs):
244+
245+
# TODO:
246+
# * MAGIC_EXTENSION not supported
247+
dest = os.path.join(TESTDATA_DIR, b"\xce\xbb".decode("utf-8"))
248+
shutil.copyfile(os.path.join(TESTDATA_DIR, "lambda"), dest)
249+
os.environ["TZ"] = "UTC"
250+
try:
251+
m = magic.Magic(**flags)
252+
with open(file_name) as f:
253+
assert m.from_descriptor(f.fileno()) in outputs
299254

300-
self.assertRaises(IOError, m_follow.from_file, tmp_broken)
255+
assert m.from_file(file_name) in outputs
301256

257+
if sys.version_info >= (3, 6) and type(file_name) is not bytes:
258+
from pathlib import Path
259+
path = Path(file_name)
260+
assert m.from_file(path) in outputs
302261

303-
if __name__ == "__main__":
304-
unittest.main()
262+
with open(file_name, "rb") as f:
263+
buf_result = m.from_buffer(f.read(1024))
264+
assert buf_result in outputs
265+
finally:
266+
del os.environ["TZ"]
267+
os.unlink(dest)

test/testdata/test.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env python
2+
3+
print("foo")

0 commit comments

Comments
 (0)