blob: 05e4ca0a797f7c9af4ad2475d2d6d8c9c8385b01 [file] [log] [blame]
Ezio Melotti48d578c2012-03-12 23:57:18 +02001from test.support import findfile, run_unittest, TESTFN, 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 Murray4d35e752013-07-25 16:12:01 -04006import pickle
R. David Murrayb507d2e2009-04-29 15:34:32 +00007
8import aifc
9
10
11class AIFCTest(unittest.TestCase):
12
13 def setUp(self):
R. David Murrayeb01a6c2009-04-29 20:40:42 +000014 self.f = self.fout = None
R. David Murrayb507d2e2009-04-29 15:34:32 +000015 self.sndfilepath = findfile('Sine-1000Hz-300ms.aif')
16
R. David Murrayeb01a6c2009-04-29 20:40:42 +000017 def tearDown(self):
18 if self.f is not None:
19 self.f.close()
20 if self.fout is not None:
21 try:
22 self.fout.close()
23 except (aifc.Error, AttributeError):
24 pass
Ezio Melotti85769532012-03-12 23:52:40 +020025 unlink(TESTFN)
26 unlink(TESTFN + '.aiff')
R. David Murrayeb01a6c2009-04-29 20:40:42 +000027
R. David Murrayb507d2e2009-04-29 15:34:32 +000028 def test_skipunknown(self):
29 #Issue 2245
30 #This file contains chunk types aifc doesn't recognize.
Benjamin Peterson25c95f12009-05-08 20:42:26 +000031 self.f = aifc.open(self.sndfilepath)
R. David Murrayb507d2e2009-04-29 15:34:32 +000032
33 def test_params(self):
R. David Murrayeb01a6c2009-04-29 20:40:42 +000034 f = self.f = aifc.open(self.sndfilepath)
R David Murray4d35e752013-07-25 16:12:01 -040035 params = f.getparams()
Ezio Melotti85769532012-03-12 23:52:40 +020036 self.assertEqual(f.getfp().name, self.sndfilepath)
R. David Murrayb507d2e2009-04-29 15:34:32 +000037 self.assertEqual(f.getnchannels(), 2)
38 self.assertEqual(f.getsampwidth(), 2)
39 self.assertEqual(f.getframerate(), 48000)
40 self.assertEqual(f.getnframes(), 14400)
R. David Murrayb507d2e2009-04-29 15:34:32 +000041 self.assertEqual(f.getcomptype(), b'NONE')
42 self.assertEqual(f.getcompname(), b'not compressed')
43 self.assertEqual(
44 f.getparams(),
45 (2, 2, 48000, 14400, b'NONE', b'not compressed'),
46 )
R. David Murrayb507d2e2009-04-29 15:34:32 +000047
R David Murray4d35e752013-07-25 16:12:01 -040048 params = f.getparams()
49 self.assertEqual(params.nchannels, 2)
50 self.assertEqual(params.sampwidth, 2)
51 self.assertEqual(params.framerate, 48000)
52 self.assertEqual(params.nframes, 14400)
53 self.assertEqual(params.comptype, b'NONE')
54 self.assertEqual(params.compname, b'not compressed')
55
56 def test_params_added(self):
57 f = self.f = aifc.open(TESTFN, 'wb')
58 f.aiff()
59 f.setparams((1, 1, 1, 1, b'NONE', b''))
60 f.close()
61
62 f = self.f = aifc.open(TESTFN, 'rb')
63 params = f.getparams()
64 self.assertEqual(params.nchannels, f.getnchannels())
65 self.assertEqual(params.sampwidth, f.getsampwidth())
66 self.assertEqual(params.framerate, f.getframerate())
67 self.assertEqual(params.nframes, f.getnframes())
68 self.assertEqual(params.comptype, f.getcomptype())
69 self.assertEqual(params.compname, f.getcompname())
70
71 def test_getparams_picklable(self):
72 self.f = aifc.open(self.sndfilepath)
73 params = self.f.getparams()
74 dump = pickle.dumps(params)
75 self.assertEqual(pickle.loads(dump), params)
76 self.f.close()
77
Serhiy Storchaka44c66c72012-12-29 22:54:49 +020078 def test_context_manager(self):
79 with open(self.sndfilepath, 'rb') as testfile:
80 with aifc.open(testfile) as f:
81 pass
82 self.assertEqual(testfile.closed, True)
83 with open(TESTFN, 'wb') as testfile:
84 with self.assertRaises(aifc.Error):
85 with aifc.open(testfile, 'wb') as fout:
86 pass
87 self.assertEqual(testfile.closed, True)
88 fout.close() # do nothing
89
R. David Murrayb507d2e2009-04-29 15:34:32 +000090 def test_read(self):
R. David Murrayeb01a6c2009-04-29 20:40:42 +000091 f = self.f = aifc.open(self.sndfilepath)
Ezio Melotti85769532012-03-12 23:52:40 +020092 self.assertEqual(f.readframes(0), b'')
R. David Murrayb507d2e2009-04-29 15:34:32 +000093 self.assertEqual(f.tell(), 0)
94 self.assertEqual(f.readframes(2), b'\x00\x00\x00\x00\x0b\xd4\x0b\xd4')
95 f.rewind()
96 pos0 = f.tell()
97 self.assertEqual(pos0, 0)
98 self.assertEqual(f.readframes(2), b'\x00\x00\x00\x00\x0b\xd4\x0b\xd4')
99 pos2 = f.tell()
100 self.assertEqual(pos2, 2)
101 self.assertEqual(f.readframes(2), b'\x17t\x17t"\xad"\xad')
102 f.setpos(pos2)
103 self.assertEqual(f.readframes(2), b'\x17t\x17t"\xad"\xad')
104 f.setpos(pos0)
105 self.assertEqual(f.readframes(2), b'\x00\x00\x00\x00\x0b\xd4\x0b\xd4')
Ezio Melotti85769532012-03-12 23:52:40 +0200106 with self.assertRaises(aifc.Error):
107 f.setpos(-1)
108 with self.assertRaises(aifc.Error):
109 f.setpos(f.getnframes() + 1)
R. David Murrayb507d2e2009-04-29 15:34:32 +0000110
R. David Murrayeb01a6c2009-04-29 20:40:42 +0000111 def test_write(self):
112 f = self.f = aifc.open(self.sndfilepath)
113 fout = self.fout = aifc.open(TESTFN, 'wb')
114 fout.aifc()
115 fout.setparams(f.getparams())
116 for frame in range(f.getnframes()):
117 fout.writeframes(f.readframes(1))
118 fout.close()
119 fout = self.fout = aifc.open(TESTFN, 'rb')
120 f.rewind()
121 self.assertEqual(f.getparams(), fout.getparams())
122 self.assertEqual(f.readframes(5), fout.readframes(5))
123
124 def test_compress(self):
125 f = self.f = aifc.open(self.sndfilepath)
126 fout = self.fout = aifc.open(TESTFN, 'wb')
127 fout.aifc()
128 fout.setnchannels(f.getnchannels())
129 fout.setsampwidth(f.getsampwidth())
130 fout.setframerate(f.getframerate())
131 fout.setcomptype(b'ULAW', b'foo')
132 for frame in range(f.getnframes()):
133 fout.writeframes(f.readframes(1))
134 fout.close()
135 self.assertLess(
136 os.stat(TESTFN).st_size,
137 os.stat(self.sndfilepath).st_size*0.75,
138 )
139 fout = self.fout = aifc.open(TESTFN, 'rb')
140 f.rewind()
141 self.assertEqual(f.getparams()[0:3], fout.getparams()[0:3])
142 self.assertEqual(fout.getcomptype(), b'ULAW')
143 self.assertEqual(fout.getcompname(), b'foo')
R. David Murrayb507d2e2009-04-29 15:34:32 +0000144
R. David Murray99352742009-05-07 18:24:38 +0000145 def test_close(self):
146 class Wrapfile(object):
147 def __init__(self, file):
148 self.file = open(file, 'rb')
149 self.closed = False
150 def close(self):
151 self.file.close()
152 self.closed = True
153 def __getattr__(self, attr): return getattr(self.file, attr)
154 testfile = Wrapfile(self.sndfilepath)
155 f = self.f = aifc.open(testfile)
156 self.assertEqual(testfile.closed, False)
157 f.close()
158 self.assertEqual(testfile.closed, True)
Serhiy Storchaka051722d2012-12-29 22:30:56 +0200159 testfile = open(TESTFN, 'wb')
160 fout = aifc.open(testfile, 'wb')
161 self.assertFalse(testfile.closed)
162 with self.assertRaises(aifc.Error):
163 fout.close()
164 self.assertTrue(testfile.closed)
165 fout.close() # do nothing
R. David Murray99352742009-05-07 18:24:38 +0000166
Sandro Tosibdd53542012-01-01 18:04:37 +0100167 def test_write_header_comptype_sampwidth(self):
168 for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'):
Ezio Melotti85769532012-03-12 23:52:40 +0200169 fout = aifc.open(io.BytesIO(), 'wb')
Sandro Tosibdd53542012-01-01 18:04:37 +0100170 fout.setnchannels(1)
171 fout.setframerate(1)
172 fout.setcomptype(comptype, b'')
173 fout.close()
174 self.assertEqual(fout.getsampwidth(), 2)
175 fout.initfp(None)
176
Sandro Tosi70efbef2012-01-01 22:53:08 +0100177 def test_write_markers_values(self):
Ezio Melotti85769532012-03-12 23:52:40 +0200178 fout = aifc.open(io.BytesIO(), 'wb')
Sandro Tosi70efbef2012-01-01 22:53:08 +0100179 self.assertEqual(fout.getmarkers(), None)
180 fout.setmark(1, 0, b'foo1')
181 fout.setmark(1, 1, b'foo2')
182 self.assertEqual(fout.getmark(1), (1, 1, b'foo2'))
183 self.assertEqual(fout.getmarkers(), [(1, 1, b'foo2')])
184 fout.initfp(None)
185
186 def test_read_markers(self):
187 fout = self.fout = aifc.open(TESTFN, 'wb')
188 fout.aiff()
189 fout.setparams((1, 1, 1, 1, b'NONE', b''))
190 fout.setmark(1, 0, b'odd')
191 fout.setmark(2, 0, b'even')
192 fout.writeframes(b'\x00')
193 fout.close()
194 f = self.f = aifc.open(TESTFN, 'rb')
195 self.assertEqual(f.getmarkers(), [(1, 0, b'odd'), (2, 0, b'even')])
196 self.assertEqual(f.getmark(1), (1, 0, b'odd'))
197 self.assertEqual(f.getmark(2), (2, 0, b'even'))
198 self.assertRaises(aifc.Error, f.getmark, 3)
199
R. David Murrayb507d2e2009-04-29 15:34:32 +0000200
Antoine Pitrou03757ec2012-01-17 17:13:04 +0100201class AIFCLowLevelTest(unittest.TestCase):
202
203 def test_read_written(self):
204 def read_written(self, what):
205 f = io.BytesIO()
206 getattr(aifc, '_write_' + what)(f, x)
207 f.seek(0)
208 return getattr(aifc, '_read_' + what)(f)
209 for x in (-1, 0, 0.1, 1):
210 self.assertEqual(read_written(x, 'float'), x)
211 for x in (float('NaN'), float('Inf')):
212 self.assertEqual(read_written(x, 'float'), aifc._HUGE_VAL)
213 for x in (b'', b'foo', b'a' * 255):
214 self.assertEqual(read_written(x, 'string'), x)
215 for x in (-0x7FFFFFFF, -1, 0, 1, 0x7FFFFFFF):
216 self.assertEqual(read_written(x, 'long'), x)
217 for x in (0, 1, 0xFFFFFFFF):
218 self.assertEqual(read_written(x, 'ulong'), x)
219 for x in (-0x7FFF, -1, 0, 1, 0x7FFF):
220 self.assertEqual(read_written(x, 'short'), x)
221 for x in (0, 1, 0xFFFF):
222 self.assertEqual(read_written(x, 'ushort'), x)
223
224 def test_read_raises(self):
225 f = io.BytesIO(b'\x00')
226 self.assertRaises(EOFError, aifc._read_ulong, f)
227 self.assertRaises(EOFError, aifc._read_long, f)
228 self.assertRaises(EOFError, aifc._read_ushort, f)
229 self.assertRaises(EOFError, aifc._read_short, f)
230
231 def test_write_long_string_raises(self):
232 f = io.BytesIO()
233 with self.assertRaises(ValueError):
234 aifc._write_string(f, b'too long' * 255)
235
Ezio Melotti85769532012-03-12 23:52:40 +0200236 def test_wrong_open_mode(self):
237 with self.assertRaises(aifc.Error):
238 aifc.open(TESTFN, 'wrong_mode')
239
240 def test_read_wrong_form(self):
241 b1 = io.BytesIO(b'WRNG' + struct.pack('>L', 0))
242 b2 = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'WRNG')
243 self.assertRaises(aifc.Error, aifc.open, b1)
244 self.assertRaises(aifc.Error, aifc.open, b2)
245
246 def test_read_no_comm_chunk(self):
247 b = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'AIFF')
248 self.assertRaises(aifc.Error, aifc.open, b)
249
250 def test_read_wrong_compression_type(self):
251 b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
252 b += b'COMM' + struct.pack('>LhlhhLL', 23, 0, 0, 0, 0, 0, 0)
253 b += b'WRNG' + struct.pack('B', 0)
254 self.assertRaises(aifc.Error, aifc.open, io.BytesIO(b))
255
256 def test_read_wrong_marks(self):
257 b = b'FORM' + struct.pack('>L', 4) + b'AIFF'
258 b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0)
259 b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
260 b += b'MARK' + struct.pack('>LhB', 3, 1, 1)
Ezio Melotti48d578c2012-03-12 23:57:18 +0200261 with self.assertWarns(UserWarning):
Ezio Melotti85769532012-03-12 23:52:40 +0200262 f = aifc.open(io.BytesIO(b))
Ezio Melotti85769532012-03-12 23:52:40 +0200263 self.assertEqual(f.getmarkers(), None)
264
265 def test_read_comm_kludge_compname_even(self):
266 b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
267 b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0)
268 b += b'NONE' + struct.pack('B', 4) + b'even' + b'\x00'
269 b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
Ezio Melotti48d578c2012-03-12 23:57:18 +0200270 with self.assertWarns(UserWarning):
Ezio Melotti85769532012-03-12 23:52:40 +0200271 f = aifc.open(io.BytesIO(b))
Ezio Melotti85769532012-03-12 23:52:40 +0200272 self.assertEqual(f.getcompname(), b'even')
273
274 def test_read_comm_kludge_compname_odd(self):
275 b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
276 b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0)
277 b += b'NONE' + struct.pack('B', 3) + b'odd'
278 b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
Ezio Melotti48d578c2012-03-12 23:57:18 +0200279 with self.assertWarns(UserWarning):
Ezio Melotti85769532012-03-12 23:52:40 +0200280 f = aifc.open(io.BytesIO(b))
Ezio Melotti85769532012-03-12 23:52:40 +0200281 self.assertEqual(f.getcompname(), b'odd')
282
283 def test_write_params_raises(self):
284 fout = aifc.open(io.BytesIO(), 'wb')
285 wrong_params = (0, 0, 0, 0, b'WRNG', '')
286 self.assertRaises(aifc.Error, fout.setparams, wrong_params)
287 self.assertRaises(aifc.Error, fout.getparams)
288 self.assertRaises(aifc.Error, fout.setnchannels, 0)
289 self.assertRaises(aifc.Error, fout.getnchannels)
290 self.assertRaises(aifc.Error, fout.setsampwidth, 0)
291 self.assertRaises(aifc.Error, fout.getsampwidth)
292 self.assertRaises(aifc.Error, fout.setframerate, 0)
293 self.assertRaises(aifc.Error, fout.getframerate)
294 self.assertRaises(aifc.Error, fout.setcomptype, b'WRNG', '')
295 fout.aiff()
296 fout.setnchannels(1)
297 fout.setsampwidth(1)
298 fout.setframerate(1)
299 fout.setnframes(1)
300 fout.writeframes(b'\x00')
301 self.assertRaises(aifc.Error, fout.setparams, (1, 1, 1, 1, 1, 1))
302 self.assertRaises(aifc.Error, fout.setnchannels, 1)
303 self.assertRaises(aifc.Error, fout.setsampwidth, 1)
304 self.assertRaises(aifc.Error, fout.setframerate, 1)
305 self.assertRaises(aifc.Error, fout.setnframes, 1)
306 self.assertRaises(aifc.Error, fout.setcomptype, b'NONE', '')
307 self.assertRaises(aifc.Error, fout.aiff)
308 self.assertRaises(aifc.Error, fout.aifc)
309
310 def test_write_params_singles(self):
311 fout = aifc.open(io.BytesIO(), 'wb')
312 fout.aifc()
313 fout.setnchannels(1)
314 fout.setsampwidth(2)
315 fout.setframerate(3)
316 fout.setnframes(4)
317 fout.setcomptype(b'NONE', b'name')
318 self.assertEqual(fout.getnchannels(), 1)
319 self.assertEqual(fout.getsampwidth(), 2)
320 self.assertEqual(fout.getframerate(), 3)
321 self.assertEqual(fout.getnframes(), 0)
322 self.assertEqual(fout.tell(), 0)
323 self.assertEqual(fout.getcomptype(), b'NONE')
324 self.assertEqual(fout.getcompname(), b'name')
325 fout.writeframes(b'\x00' * 4 * fout.getsampwidth() * fout.getnchannels())
326 self.assertEqual(fout.getnframes(), 4)
327 self.assertEqual(fout.tell(), 4)
328
329 def test_write_params_bunch(self):
330 fout = aifc.open(io.BytesIO(), 'wb')
331 fout.aifc()
332 p = (1, 2, 3, 4, b'NONE', b'name')
333 fout.setparams(p)
334 self.assertEqual(fout.getparams(), p)
335 fout.initfp(None)
336
337 def test_write_header_raises(self):
338 fout = aifc.open(io.BytesIO(), 'wb')
339 self.assertRaises(aifc.Error, fout.close)
Serhiy Storchaka051722d2012-12-29 22:30:56 +0200340 fout = aifc.open(io.BytesIO(), 'wb')
Ezio Melotti85769532012-03-12 23:52:40 +0200341 fout.setnchannels(1)
342 self.assertRaises(aifc.Error, fout.close)
Serhiy Storchaka051722d2012-12-29 22:30:56 +0200343 fout = aifc.open(io.BytesIO(), 'wb')
344 fout.setnchannels(1)
Ezio Melotti85769532012-03-12 23:52:40 +0200345 fout.setsampwidth(1)
346 self.assertRaises(aifc.Error, fout.close)
Ezio Melotti85769532012-03-12 23:52:40 +0200347
348 def test_write_header_comptype_raises(self):
349 for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'):
350 fout = aifc.open(io.BytesIO(), 'wb')
351 fout.setsampwidth(1)
352 fout.setcomptype(comptype, b'')
353 self.assertRaises(aifc.Error, fout.close)
354 fout.initfp(None)
355
356 def test_write_markers_raises(self):
357 fout = aifc.open(io.BytesIO(), 'wb')
358 self.assertRaises(aifc.Error, fout.setmark, 0, 0, b'')
359 self.assertRaises(aifc.Error, fout.setmark, 1, -1, b'')
360 self.assertRaises(aifc.Error, fout.setmark, 1, 0, None)
361 self.assertRaises(aifc.Error, fout.getmark, 1)
362 fout.initfp(None)
363
364 def test_write_aiff_by_extension(self):
365 sampwidth = 2
Ezio Melotti4b843a72013-03-01 21:10:26 +0200366 filename = TESTFN + '.aiff'
367 fout = self.fout = aifc.open(filename, 'wb')
368 self.addCleanup(unlink, filename)
Ezio Melotti85769532012-03-12 23:52:40 +0200369 fout.setparams((1, sampwidth, 1, 1, b'ULAW', b''))
370 frames = b'\x00' * fout.getnchannels() * sampwidth
371 fout.writeframes(frames)
372 fout.close()
Ezio Melotti4b843a72013-03-01 21:10:26 +0200373 f = self.f = aifc.open(filename, 'rb')
Ezio Melotti85769532012-03-12 23:52:40 +0200374 self.assertEqual(f.getcomptype(), b'NONE')
375 f.close()
376
Antoine Pitrou03757ec2012-01-17 17:13:04 +0100377
R. David Murrayb507d2e2009-04-29 15:34:32 +0000378def test_main():
379 run_unittest(AIFCTest)
Antoine Pitrou03757ec2012-01-17 17:13:04 +0100380 run_unittest(AIFCLowLevelTest)
R. David Murrayb507d2e2009-04-29 15:34:32 +0000381
382
383if __name__ == "__main__":
384 unittest.main()