blob: 0b19af6a10a713abb7113d207a417122eb84c8a5 [file] [log] [blame]
Ezio Melotti85769532012-03-12 23:52:40 +02001from test.support import findfile, run_unittest, TESTFN, captured_stdout, unlink
R. David Murrayb507d2e2009-04-29 15:34:32 +00002import unittest
R. David Murrayeb01a6c2009-04-29 20:40:42 +00003import os
Sandro Tosibdd53542012-01-01 18:04:37 +01004import io
Ezio Melotti85769532012-03-12 23:52:40 +02005import struct
R. David Murrayb507d2e2009-04-29 15:34:32 +00006
7import aifc
8
9
10class AIFCTest(unittest.TestCase):
11
12 def setUp(self):
R. David Murrayeb01a6c2009-04-29 20:40:42 +000013 self.f = self.fout = None
R. David Murrayb507d2e2009-04-29 15:34:32 +000014 self.sndfilepath = findfile('Sine-1000Hz-300ms.aif')
15
R. David Murrayeb01a6c2009-04-29 20:40:42 +000016 def tearDown(self):
17 if self.f is not None:
18 self.f.close()
19 if self.fout is not None:
20 try:
21 self.fout.close()
22 except (aifc.Error, AttributeError):
23 pass
Ezio Melotti85769532012-03-12 23:52:40 +020024 unlink(TESTFN)
25 unlink(TESTFN + '.aiff')
R. David Murrayeb01a6c2009-04-29 20:40:42 +000026
R. David Murrayb507d2e2009-04-29 15:34:32 +000027 def test_skipunknown(self):
28 #Issue 2245
29 #This file contains chunk types aifc doesn't recognize.
Benjamin Peterson25c95f12009-05-08 20:42:26 +000030 self.f = aifc.open(self.sndfilepath)
R. David Murrayb507d2e2009-04-29 15:34:32 +000031
32 def test_params(self):
R. David Murrayeb01a6c2009-04-29 20:40:42 +000033 f = self.f = aifc.open(self.sndfilepath)
Ezio Melotti85769532012-03-12 23:52:40 +020034 self.assertEqual(f.getfp().name, self.sndfilepath)
R. David Murrayb507d2e2009-04-29 15:34:32 +000035 self.assertEqual(f.getnchannels(), 2)
36 self.assertEqual(f.getsampwidth(), 2)
37 self.assertEqual(f.getframerate(), 48000)
38 self.assertEqual(f.getnframes(), 14400)
R. David Murrayb507d2e2009-04-29 15:34:32 +000039 self.assertEqual(f.getcomptype(), b'NONE')
40 self.assertEqual(f.getcompname(), b'not compressed')
41 self.assertEqual(
42 f.getparams(),
43 (2, 2, 48000, 14400, b'NONE', b'not compressed'),
44 )
R. David Murrayb507d2e2009-04-29 15:34:32 +000045
46 def test_read(self):
R. David Murrayeb01a6c2009-04-29 20:40:42 +000047 f = self.f = aifc.open(self.sndfilepath)
Ezio Melotti85769532012-03-12 23:52:40 +020048 self.assertEqual(f.readframes(0), b'')
R. David Murrayb507d2e2009-04-29 15:34:32 +000049 self.assertEqual(f.tell(), 0)
50 self.assertEqual(f.readframes(2), b'\x00\x00\x00\x00\x0b\xd4\x0b\xd4')
51 f.rewind()
52 pos0 = f.tell()
53 self.assertEqual(pos0, 0)
54 self.assertEqual(f.readframes(2), b'\x00\x00\x00\x00\x0b\xd4\x0b\xd4')
55 pos2 = f.tell()
56 self.assertEqual(pos2, 2)
57 self.assertEqual(f.readframes(2), b'\x17t\x17t"\xad"\xad')
58 f.setpos(pos2)
59 self.assertEqual(f.readframes(2), b'\x17t\x17t"\xad"\xad')
60 f.setpos(pos0)
61 self.assertEqual(f.readframes(2), b'\x00\x00\x00\x00\x0b\xd4\x0b\xd4')
Ezio Melotti85769532012-03-12 23:52:40 +020062 with self.assertRaises(aifc.Error):
63 f.setpos(-1)
64 with self.assertRaises(aifc.Error):
65 f.setpos(f.getnframes() + 1)
R. David Murrayb507d2e2009-04-29 15:34:32 +000066
R. David Murrayeb01a6c2009-04-29 20:40:42 +000067 def test_write(self):
68 f = self.f = aifc.open(self.sndfilepath)
69 fout = self.fout = aifc.open(TESTFN, 'wb')
70 fout.aifc()
71 fout.setparams(f.getparams())
72 for frame in range(f.getnframes()):
73 fout.writeframes(f.readframes(1))
74 fout.close()
75 fout = self.fout = aifc.open(TESTFN, 'rb')
76 f.rewind()
77 self.assertEqual(f.getparams(), fout.getparams())
78 self.assertEqual(f.readframes(5), fout.readframes(5))
79
80 def test_compress(self):
81 f = self.f = aifc.open(self.sndfilepath)
82 fout = self.fout = aifc.open(TESTFN, 'wb')
83 fout.aifc()
84 fout.setnchannels(f.getnchannels())
85 fout.setsampwidth(f.getsampwidth())
86 fout.setframerate(f.getframerate())
87 fout.setcomptype(b'ULAW', b'foo')
88 for frame in range(f.getnframes()):
89 fout.writeframes(f.readframes(1))
90 fout.close()
91 self.assertLess(
92 os.stat(TESTFN).st_size,
93 os.stat(self.sndfilepath).st_size*0.75,
94 )
95 fout = self.fout = aifc.open(TESTFN, 'rb')
96 f.rewind()
97 self.assertEqual(f.getparams()[0:3], fout.getparams()[0:3])
98 self.assertEqual(fout.getcomptype(), b'ULAW')
99 self.assertEqual(fout.getcompname(), b'foo')
R. David Murrayb507d2e2009-04-29 15:34:32 +0000100
R. David Murray99352742009-05-07 18:24:38 +0000101 def test_close(self):
102 class Wrapfile(object):
103 def __init__(self, file):
104 self.file = open(file, 'rb')
105 self.closed = False
106 def close(self):
107 self.file.close()
108 self.closed = True
109 def __getattr__(self, attr): return getattr(self.file, attr)
110 testfile = Wrapfile(self.sndfilepath)
111 f = self.f = aifc.open(testfile)
112 self.assertEqual(testfile.closed, False)
113 f.close()
114 self.assertEqual(testfile.closed, True)
Serhiy Storchaka051722d2012-12-29 22:30:56 +0200115 testfile = open(TESTFN, 'wb')
116 fout = aifc.open(testfile, 'wb')
117 self.assertFalse(testfile.closed)
118 with self.assertRaises(aifc.Error):
119 fout.close()
120 self.assertTrue(testfile.closed)
121 fout.close() # do nothing
R. David Murray99352742009-05-07 18:24:38 +0000122
Sandro Tosibdd53542012-01-01 18:04:37 +0100123 def test_write_header_comptype_sampwidth(self):
124 for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'):
Ezio Melotti85769532012-03-12 23:52:40 +0200125 fout = aifc.open(io.BytesIO(), 'wb')
Sandro Tosibdd53542012-01-01 18:04:37 +0100126 fout.setnchannels(1)
127 fout.setframerate(1)
128 fout.setcomptype(comptype, b'')
129 fout.close()
130 self.assertEqual(fout.getsampwidth(), 2)
131 fout.initfp(None)
132
Sandro Tosi70efbef2012-01-01 22:53:08 +0100133 def test_write_markers_values(self):
Ezio Melotti85769532012-03-12 23:52:40 +0200134 fout = aifc.open(io.BytesIO(), 'wb')
Sandro Tosi70efbef2012-01-01 22:53:08 +0100135 self.assertEqual(fout.getmarkers(), None)
136 fout.setmark(1, 0, b'foo1')
137 fout.setmark(1, 1, b'foo2')
138 self.assertEqual(fout.getmark(1), (1, 1, b'foo2'))
139 self.assertEqual(fout.getmarkers(), [(1, 1, b'foo2')])
140 fout.initfp(None)
141
142 def test_read_markers(self):
143 fout = self.fout = aifc.open(TESTFN, 'wb')
144 fout.aiff()
145 fout.setparams((1, 1, 1, 1, b'NONE', b''))
146 fout.setmark(1, 0, b'odd')
147 fout.setmark(2, 0, b'even')
148 fout.writeframes(b'\x00')
149 fout.close()
150 f = self.f = aifc.open(TESTFN, 'rb')
151 self.assertEqual(f.getmarkers(), [(1, 0, b'odd'), (2, 0, b'even')])
152 self.assertEqual(f.getmark(1), (1, 0, b'odd'))
153 self.assertEqual(f.getmark(2), (2, 0, b'even'))
154 self.assertRaises(aifc.Error, f.getmark, 3)
155
R. David Murrayb507d2e2009-04-29 15:34:32 +0000156
Antoine Pitrou03757ec2012-01-17 17:13:04 +0100157class AIFCLowLevelTest(unittest.TestCase):
158
159 def test_read_written(self):
160 def read_written(self, what):
161 f = io.BytesIO()
162 getattr(aifc, '_write_' + what)(f, x)
163 f.seek(0)
164 return getattr(aifc, '_read_' + what)(f)
165 for x in (-1, 0, 0.1, 1):
166 self.assertEqual(read_written(x, 'float'), x)
167 for x in (float('NaN'), float('Inf')):
168 self.assertEqual(read_written(x, 'float'), aifc._HUGE_VAL)
169 for x in (b'', b'foo', b'a' * 255):
170 self.assertEqual(read_written(x, 'string'), x)
171 for x in (-0x7FFFFFFF, -1, 0, 1, 0x7FFFFFFF):
172 self.assertEqual(read_written(x, 'long'), x)
173 for x in (0, 1, 0xFFFFFFFF):
174 self.assertEqual(read_written(x, 'ulong'), x)
175 for x in (-0x7FFF, -1, 0, 1, 0x7FFF):
176 self.assertEqual(read_written(x, 'short'), x)
177 for x in (0, 1, 0xFFFF):
178 self.assertEqual(read_written(x, 'ushort'), x)
179
180 def test_read_raises(self):
181 f = io.BytesIO(b'\x00')
182 self.assertRaises(EOFError, aifc._read_ulong, f)
183 self.assertRaises(EOFError, aifc._read_long, f)
184 self.assertRaises(EOFError, aifc._read_ushort, f)
185 self.assertRaises(EOFError, aifc._read_short, f)
186
187 def test_write_long_string_raises(self):
188 f = io.BytesIO()
189 with self.assertRaises(ValueError):
190 aifc._write_string(f, b'too long' * 255)
191
Ezio Melotti85769532012-03-12 23:52:40 +0200192 def test_wrong_open_mode(self):
193 with self.assertRaises(aifc.Error):
194 aifc.open(TESTFN, 'wrong_mode')
195
196 def test_read_wrong_form(self):
197 b1 = io.BytesIO(b'WRNG' + struct.pack('>L', 0))
198 b2 = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'WRNG')
199 self.assertRaises(aifc.Error, aifc.open, b1)
200 self.assertRaises(aifc.Error, aifc.open, b2)
201
202 def test_read_no_comm_chunk(self):
203 b = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'AIFF')
204 self.assertRaises(aifc.Error, aifc.open, b)
205
206 def test_read_wrong_compression_type(self):
207 b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
208 b += b'COMM' + struct.pack('>LhlhhLL', 23, 0, 0, 0, 0, 0, 0)
209 b += b'WRNG' + struct.pack('B', 0)
210 self.assertRaises(aifc.Error, aifc.open, io.BytesIO(b))
211
212 def test_read_wrong_marks(self):
213 b = b'FORM' + struct.pack('>L', 4) + b'AIFF'
214 b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0)
215 b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
216 b += b'MARK' + struct.pack('>LhB', 3, 1, 1)
217 with captured_stdout() as s:
218 f = aifc.open(io.BytesIO(b))
219 self.assertEqual(
220 s.getvalue(),
221 'Warning: MARK chunk contains only 0 markers instead of 1\n')
222 self.assertEqual(f.getmarkers(), None)
223
224 def test_read_comm_kludge_compname_even(self):
225 b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
226 b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0)
227 b += b'NONE' + struct.pack('B', 4) + b'even' + b'\x00'
228 b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
229 with captured_stdout() as s:
230 f = aifc.open(io.BytesIO(b))
231 self.assertEqual(s.getvalue(), 'Warning: bad COMM chunk size\n')
232 self.assertEqual(f.getcompname(), b'even')
233
234 def test_read_comm_kludge_compname_odd(self):
235 b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
236 b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0)
237 b += b'NONE' + struct.pack('B', 3) + b'odd'
238 b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
239 with captured_stdout() as s:
240 f = aifc.open(io.BytesIO(b))
241 self.assertEqual(s.getvalue(), 'Warning: bad COMM chunk size\n')
242 self.assertEqual(f.getcompname(), b'odd')
243
244 def test_write_params_raises(self):
245 fout = aifc.open(io.BytesIO(), 'wb')
246 wrong_params = (0, 0, 0, 0, b'WRNG', '')
247 self.assertRaises(aifc.Error, fout.setparams, wrong_params)
248 self.assertRaises(aifc.Error, fout.getparams)
249 self.assertRaises(aifc.Error, fout.setnchannels, 0)
250 self.assertRaises(aifc.Error, fout.getnchannels)
251 self.assertRaises(aifc.Error, fout.setsampwidth, 0)
252 self.assertRaises(aifc.Error, fout.getsampwidth)
253 self.assertRaises(aifc.Error, fout.setframerate, 0)
254 self.assertRaises(aifc.Error, fout.getframerate)
255 self.assertRaises(aifc.Error, fout.setcomptype, b'WRNG', '')
256 fout.aiff()
257 fout.setnchannels(1)
258 fout.setsampwidth(1)
259 fout.setframerate(1)
260 fout.setnframes(1)
261 fout.writeframes(b'\x00')
262 self.assertRaises(aifc.Error, fout.setparams, (1, 1, 1, 1, 1, 1))
263 self.assertRaises(aifc.Error, fout.setnchannels, 1)
264 self.assertRaises(aifc.Error, fout.setsampwidth, 1)
265 self.assertRaises(aifc.Error, fout.setframerate, 1)
266 self.assertRaises(aifc.Error, fout.setnframes, 1)
267 self.assertRaises(aifc.Error, fout.setcomptype, b'NONE', '')
268 self.assertRaises(aifc.Error, fout.aiff)
269 self.assertRaises(aifc.Error, fout.aifc)
270
271 def test_write_params_singles(self):
272 fout = aifc.open(io.BytesIO(), 'wb')
273 fout.aifc()
274 fout.setnchannels(1)
275 fout.setsampwidth(2)
276 fout.setframerate(3)
277 fout.setnframes(4)
278 fout.setcomptype(b'NONE', b'name')
279 self.assertEqual(fout.getnchannels(), 1)
280 self.assertEqual(fout.getsampwidth(), 2)
281 self.assertEqual(fout.getframerate(), 3)
282 self.assertEqual(fout.getnframes(), 0)
283 self.assertEqual(fout.tell(), 0)
284 self.assertEqual(fout.getcomptype(), b'NONE')
285 self.assertEqual(fout.getcompname(), b'name')
286 fout.writeframes(b'\x00' * 4 * fout.getsampwidth() * fout.getnchannels())
287 self.assertEqual(fout.getnframes(), 4)
288 self.assertEqual(fout.tell(), 4)
289
290 def test_write_params_bunch(self):
291 fout = aifc.open(io.BytesIO(), 'wb')
292 fout.aifc()
293 p = (1, 2, 3, 4, b'NONE', b'name')
294 fout.setparams(p)
295 self.assertEqual(fout.getparams(), p)
296 fout.initfp(None)
297
298 def test_write_header_raises(self):
299 fout = aifc.open(io.BytesIO(), 'wb')
300 self.assertRaises(aifc.Error, fout.close)
Serhiy Storchaka051722d2012-12-29 22:30:56 +0200301 fout = aifc.open(io.BytesIO(), 'wb')
Ezio Melotti85769532012-03-12 23:52:40 +0200302 fout.setnchannels(1)
303 self.assertRaises(aifc.Error, fout.close)
Serhiy Storchaka051722d2012-12-29 22:30:56 +0200304 fout = aifc.open(io.BytesIO(), 'wb')
305 fout.setnchannels(1)
Ezio Melotti85769532012-03-12 23:52:40 +0200306 fout.setsampwidth(1)
307 self.assertRaises(aifc.Error, fout.close)
Ezio Melotti85769532012-03-12 23:52:40 +0200308
309 def test_write_header_comptype_raises(self):
310 for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'):
311 fout = aifc.open(io.BytesIO(), 'wb')
312 fout.setsampwidth(1)
313 fout.setcomptype(comptype, b'')
314 self.assertRaises(aifc.Error, fout.close)
315 fout.initfp(None)
316
317 def test_write_markers_raises(self):
318 fout = aifc.open(io.BytesIO(), 'wb')
319 self.assertRaises(aifc.Error, fout.setmark, 0, 0, b'')
320 self.assertRaises(aifc.Error, fout.setmark, 1, -1, b'')
321 self.assertRaises(aifc.Error, fout.setmark, 1, 0, None)
322 self.assertRaises(aifc.Error, fout.getmark, 1)
323 fout.initfp(None)
324
325 def test_write_aiff_by_extension(self):
326 sampwidth = 2
327 fout = self.fout = aifc.open(TESTFN + '.aiff', 'wb')
328 fout.setparams((1, sampwidth, 1, 1, b'ULAW', b''))
329 frames = b'\x00' * fout.getnchannels() * sampwidth
330 fout.writeframes(frames)
331 fout.close()
332 f = self.f = aifc.open(TESTFN + '.aiff', 'rb')
333 self.assertEqual(f.getcomptype(), b'NONE')
334 f.close()
335
Antoine Pitrou03757ec2012-01-17 17:13:04 +0100336
R. David Murrayb507d2e2009-04-29 15:34:32 +0000337def test_main():
338 run_unittest(AIFCTest)
Antoine Pitrou03757ec2012-01-17 17:13:04 +0100339 run_unittest(AIFCLowLevelTest)
R. David Murrayb507d2e2009-04-29 15:34:32 +0000340
341
342if __name__ == "__main__":
343 unittest.main()