blob: 98d43e42c08844ff680452d74280d291fe1c59e7 [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 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
Serhiy Storchaka44c66c72012-12-29 22:54:49 +020046 def test_context_manager(self):
47 with open(self.sndfilepath, 'rb') as testfile:
48 with aifc.open(testfile) as f:
49 pass
50 self.assertEqual(testfile.closed, True)
51 with open(TESTFN, 'wb') as testfile:
52 with self.assertRaises(aifc.Error):
53 with aifc.open(testfile, 'wb') as fout:
54 pass
55 self.assertEqual(testfile.closed, True)
56 fout.close() # do nothing
57
R. David Murrayb507d2e2009-04-29 15:34:32 +000058 def test_read(self):
R. David Murrayeb01a6c2009-04-29 20:40:42 +000059 f = self.f = aifc.open(self.sndfilepath)
Ezio Melotti85769532012-03-12 23:52:40 +020060 self.assertEqual(f.readframes(0), b'')
R. David Murrayb507d2e2009-04-29 15:34:32 +000061 self.assertEqual(f.tell(), 0)
62 self.assertEqual(f.readframes(2), b'\x00\x00\x00\x00\x0b\xd4\x0b\xd4')
63 f.rewind()
64 pos0 = f.tell()
65 self.assertEqual(pos0, 0)
66 self.assertEqual(f.readframes(2), b'\x00\x00\x00\x00\x0b\xd4\x0b\xd4')
67 pos2 = f.tell()
68 self.assertEqual(pos2, 2)
69 self.assertEqual(f.readframes(2), b'\x17t\x17t"\xad"\xad')
70 f.setpos(pos2)
71 self.assertEqual(f.readframes(2), b'\x17t\x17t"\xad"\xad')
72 f.setpos(pos0)
73 self.assertEqual(f.readframes(2), b'\x00\x00\x00\x00\x0b\xd4\x0b\xd4')
Ezio Melotti85769532012-03-12 23:52:40 +020074 with self.assertRaises(aifc.Error):
75 f.setpos(-1)
76 with self.assertRaises(aifc.Error):
77 f.setpos(f.getnframes() + 1)
R. David Murrayb507d2e2009-04-29 15:34:32 +000078
R. David Murrayeb01a6c2009-04-29 20:40:42 +000079 def test_write(self):
80 f = self.f = aifc.open(self.sndfilepath)
81 fout = self.fout = aifc.open(TESTFN, 'wb')
82 fout.aifc()
83 fout.setparams(f.getparams())
84 for frame in range(f.getnframes()):
85 fout.writeframes(f.readframes(1))
86 fout.close()
87 fout = self.fout = aifc.open(TESTFN, 'rb')
88 f.rewind()
89 self.assertEqual(f.getparams(), fout.getparams())
90 self.assertEqual(f.readframes(5), fout.readframes(5))
91
92 def test_compress(self):
93 f = self.f = aifc.open(self.sndfilepath)
94 fout = self.fout = aifc.open(TESTFN, 'wb')
95 fout.aifc()
96 fout.setnchannels(f.getnchannels())
97 fout.setsampwidth(f.getsampwidth())
98 fout.setframerate(f.getframerate())
99 fout.setcomptype(b'ULAW', b'foo')
100 for frame in range(f.getnframes()):
101 fout.writeframes(f.readframes(1))
102 fout.close()
103 self.assertLess(
104 os.stat(TESTFN).st_size,
105 os.stat(self.sndfilepath).st_size*0.75,
106 )
107 fout = self.fout = aifc.open(TESTFN, 'rb')
108 f.rewind()
109 self.assertEqual(f.getparams()[0:3], fout.getparams()[0:3])
110 self.assertEqual(fout.getcomptype(), b'ULAW')
111 self.assertEqual(fout.getcompname(), b'foo')
R. David Murrayb507d2e2009-04-29 15:34:32 +0000112
R. David Murray99352742009-05-07 18:24:38 +0000113 def test_close(self):
114 class Wrapfile(object):
115 def __init__(self, file):
116 self.file = open(file, 'rb')
117 self.closed = False
118 def close(self):
119 self.file.close()
120 self.closed = True
121 def __getattr__(self, attr): return getattr(self.file, attr)
122 testfile = Wrapfile(self.sndfilepath)
123 f = self.f = aifc.open(testfile)
124 self.assertEqual(testfile.closed, False)
125 f.close()
126 self.assertEqual(testfile.closed, True)
Serhiy Storchaka051722d2012-12-29 22:30:56 +0200127 testfile = open(TESTFN, 'wb')
128 fout = aifc.open(testfile, 'wb')
129 self.assertFalse(testfile.closed)
130 with self.assertRaises(aifc.Error):
131 fout.close()
132 self.assertTrue(testfile.closed)
133 fout.close() # do nothing
R. David Murray99352742009-05-07 18:24:38 +0000134
Sandro Tosibdd53542012-01-01 18:04:37 +0100135 def test_write_header_comptype_sampwidth(self):
136 for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'):
Ezio Melotti85769532012-03-12 23:52:40 +0200137 fout = aifc.open(io.BytesIO(), 'wb')
Sandro Tosibdd53542012-01-01 18:04:37 +0100138 fout.setnchannels(1)
139 fout.setframerate(1)
140 fout.setcomptype(comptype, b'')
141 fout.close()
142 self.assertEqual(fout.getsampwidth(), 2)
143 fout.initfp(None)
144
Sandro Tosi70efbef2012-01-01 22:53:08 +0100145 def test_write_markers_values(self):
Ezio Melotti85769532012-03-12 23:52:40 +0200146 fout = aifc.open(io.BytesIO(), 'wb')
Sandro Tosi70efbef2012-01-01 22:53:08 +0100147 self.assertEqual(fout.getmarkers(), None)
148 fout.setmark(1, 0, b'foo1')
149 fout.setmark(1, 1, b'foo2')
150 self.assertEqual(fout.getmark(1), (1, 1, b'foo2'))
151 self.assertEqual(fout.getmarkers(), [(1, 1, b'foo2')])
152 fout.initfp(None)
153
154 def test_read_markers(self):
155 fout = self.fout = aifc.open(TESTFN, 'wb')
156 fout.aiff()
157 fout.setparams((1, 1, 1, 1, b'NONE', b''))
158 fout.setmark(1, 0, b'odd')
159 fout.setmark(2, 0, b'even')
160 fout.writeframes(b'\x00')
161 fout.close()
162 f = self.f = aifc.open(TESTFN, 'rb')
163 self.assertEqual(f.getmarkers(), [(1, 0, b'odd'), (2, 0, b'even')])
164 self.assertEqual(f.getmark(1), (1, 0, b'odd'))
165 self.assertEqual(f.getmark(2), (2, 0, b'even'))
166 self.assertRaises(aifc.Error, f.getmark, 3)
167
R. David Murrayb507d2e2009-04-29 15:34:32 +0000168
Antoine Pitrou03757ec2012-01-17 17:13:04 +0100169class AIFCLowLevelTest(unittest.TestCase):
170
171 def test_read_written(self):
172 def read_written(self, what):
173 f = io.BytesIO()
174 getattr(aifc, '_write_' + what)(f, x)
175 f.seek(0)
176 return getattr(aifc, '_read_' + what)(f)
177 for x in (-1, 0, 0.1, 1):
178 self.assertEqual(read_written(x, 'float'), x)
179 for x in (float('NaN'), float('Inf')):
180 self.assertEqual(read_written(x, 'float'), aifc._HUGE_VAL)
181 for x in (b'', b'foo', b'a' * 255):
182 self.assertEqual(read_written(x, 'string'), x)
183 for x in (-0x7FFFFFFF, -1, 0, 1, 0x7FFFFFFF):
184 self.assertEqual(read_written(x, 'long'), x)
185 for x in (0, 1, 0xFFFFFFFF):
186 self.assertEqual(read_written(x, 'ulong'), x)
187 for x in (-0x7FFF, -1, 0, 1, 0x7FFF):
188 self.assertEqual(read_written(x, 'short'), x)
189 for x in (0, 1, 0xFFFF):
190 self.assertEqual(read_written(x, 'ushort'), x)
191
192 def test_read_raises(self):
193 f = io.BytesIO(b'\x00')
194 self.assertRaises(EOFError, aifc._read_ulong, f)
195 self.assertRaises(EOFError, aifc._read_long, f)
196 self.assertRaises(EOFError, aifc._read_ushort, f)
197 self.assertRaises(EOFError, aifc._read_short, f)
198
199 def test_write_long_string_raises(self):
200 f = io.BytesIO()
201 with self.assertRaises(ValueError):
202 aifc._write_string(f, b'too long' * 255)
203
Ezio Melotti85769532012-03-12 23:52:40 +0200204 def test_wrong_open_mode(self):
205 with self.assertRaises(aifc.Error):
206 aifc.open(TESTFN, 'wrong_mode')
207
208 def test_read_wrong_form(self):
209 b1 = io.BytesIO(b'WRNG' + struct.pack('>L', 0))
210 b2 = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'WRNG')
211 self.assertRaises(aifc.Error, aifc.open, b1)
212 self.assertRaises(aifc.Error, aifc.open, b2)
213
214 def test_read_no_comm_chunk(self):
215 b = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'AIFF')
216 self.assertRaises(aifc.Error, aifc.open, b)
217
218 def test_read_wrong_compression_type(self):
219 b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
220 b += b'COMM' + struct.pack('>LhlhhLL', 23, 0, 0, 0, 0, 0, 0)
221 b += b'WRNG' + struct.pack('B', 0)
222 self.assertRaises(aifc.Error, aifc.open, io.BytesIO(b))
223
224 def test_read_wrong_marks(self):
225 b = b'FORM' + struct.pack('>L', 4) + b'AIFF'
226 b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0)
227 b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
228 b += b'MARK' + struct.pack('>LhB', 3, 1, 1)
Ezio Melotti48d578c2012-03-12 23:57:18 +0200229 with self.assertWarns(UserWarning):
Ezio Melotti85769532012-03-12 23:52:40 +0200230 f = aifc.open(io.BytesIO(b))
Ezio Melotti85769532012-03-12 23:52:40 +0200231 self.assertEqual(f.getmarkers(), None)
232
233 def test_read_comm_kludge_compname_even(self):
234 b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
235 b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0)
236 b += b'NONE' + struct.pack('B', 4) + b'even' + b'\x00'
237 b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
Ezio Melotti48d578c2012-03-12 23:57:18 +0200238 with self.assertWarns(UserWarning):
Ezio Melotti85769532012-03-12 23:52:40 +0200239 f = aifc.open(io.BytesIO(b))
Ezio Melotti85769532012-03-12 23:52:40 +0200240 self.assertEqual(f.getcompname(), b'even')
241
242 def test_read_comm_kludge_compname_odd(self):
243 b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
244 b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0)
245 b += b'NONE' + struct.pack('B', 3) + b'odd'
246 b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
Ezio Melotti48d578c2012-03-12 23:57:18 +0200247 with self.assertWarns(UserWarning):
Ezio Melotti85769532012-03-12 23:52:40 +0200248 f = aifc.open(io.BytesIO(b))
Ezio Melotti85769532012-03-12 23:52:40 +0200249 self.assertEqual(f.getcompname(), b'odd')
250
251 def test_write_params_raises(self):
252 fout = aifc.open(io.BytesIO(), 'wb')
253 wrong_params = (0, 0, 0, 0, b'WRNG', '')
254 self.assertRaises(aifc.Error, fout.setparams, wrong_params)
255 self.assertRaises(aifc.Error, fout.getparams)
256 self.assertRaises(aifc.Error, fout.setnchannels, 0)
257 self.assertRaises(aifc.Error, fout.getnchannels)
258 self.assertRaises(aifc.Error, fout.setsampwidth, 0)
259 self.assertRaises(aifc.Error, fout.getsampwidth)
260 self.assertRaises(aifc.Error, fout.setframerate, 0)
261 self.assertRaises(aifc.Error, fout.getframerate)
262 self.assertRaises(aifc.Error, fout.setcomptype, b'WRNG', '')
263 fout.aiff()
264 fout.setnchannels(1)
265 fout.setsampwidth(1)
266 fout.setframerate(1)
267 fout.setnframes(1)
268 fout.writeframes(b'\x00')
269 self.assertRaises(aifc.Error, fout.setparams, (1, 1, 1, 1, 1, 1))
270 self.assertRaises(aifc.Error, fout.setnchannels, 1)
271 self.assertRaises(aifc.Error, fout.setsampwidth, 1)
272 self.assertRaises(aifc.Error, fout.setframerate, 1)
273 self.assertRaises(aifc.Error, fout.setnframes, 1)
274 self.assertRaises(aifc.Error, fout.setcomptype, b'NONE', '')
275 self.assertRaises(aifc.Error, fout.aiff)
276 self.assertRaises(aifc.Error, fout.aifc)
277
278 def test_write_params_singles(self):
279 fout = aifc.open(io.BytesIO(), 'wb')
280 fout.aifc()
281 fout.setnchannels(1)
282 fout.setsampwidth(2)
283 fout.setframerate(3)
284 fout.setnframes(4)
285 fout.setcomptype(b'NONE', b'name')
286 self.assertEqual(fout.getnchannels(), 1)
287 self.assertEqual(fout.getsampwidth(), 2)
288 self.assertEqual(fout.getframerate(), 3)
289 self.assertEqual(fout.getnframes(), 0)
290 self.assertEqual(fout.tell(), 0)
291 self.assertEqual(fout.getcomptype(), b'NONE')
292 self.assertEqual(fout.getcompname(), b'name')
293 fout.writeframes(b'\x00' * 4 * fout.getsampwidth() * fout.getnchannels())
294 self.assertEqual(fout.getnframes(), 4)
295 self.assertEqual(fout.tell(), 4)
296
297 def test_write_params_bunch(self):
298 fout = aifc.open(io.BytesIO(), 'wb')
299 fout.aifc()
300 p = (1, 2, 3, 4, b'NONE', b'name')
301 fout.setparams(p)
302 self.assertEqual(fout.getparams(), p)
303 fout.initfp(None)
304
305 def test_write_header_raises(self):
306 fout = aifc.open(io.BytesIO(), 'wb')
307 self.assertRaises(aifc.Error, fout.close)
Serhiy Storchaka051722d2012-12-29 22:30:56 +0200308 fout = aifc.open(io.BytesIO(), 'wb')
Ezio Melotti85769532012-03-12 23:52:40 +0200309 fout.setnchannels(1)
310 self.assertRaises(aifc.Error, fout.close)
Serhiy Storchaka051722d2012-12-29 22:30:56 +0200311 fout = aifc.open(io.BytesIO(), 'wb')
312 fout.setnchannels(1)
Ezio Melotti85769532012-03-12 23:52:40 +0200313 fout.setsampwidth(1)
314 self.assertRaises(aifc.Error, fout.close)
Ezio Melotti85769532012-03-12 23:52:40 +0200315
316 def test_write_header_comptype_raises(self):
317 for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'):
318 fout = aifc.open(io.BytesIO(), 'wb')
319 fout.setsampwidth(1)
320 fout.setcomptype(comptype, b'')
321 self.assertRaises(aifc.Error, fout.close)
322 fout.initfp(None)
323
324 def test_write_markers_raises(self):
325 fout = aifc.open(io.BytesIO(), 'wb')
326 self.assertRaises(aifc.Error, fout.setmark, 0, 0, b'')
327 self.assertRaises(aifc.Error, fout.setmark, 1, -1, b'')
328 self.assertRaises(aifc.Error, fout.setmark, 1, 0, None)
329 self.assertRaises(aifc.Error, fout.getmark, 1)
330 fout.initfp(None)
331
332 def test_write_aiff_by_extension(self):
333 sampwidth = 2
Ezio Melotti4b843a72013-03-01 21:10:26 +0200334 filename = TESTFN + '.aiff'
335 fout = self.fout = aifc.open(filename, 'wb')
336 self.addCleanup(unlink, filename)
Ezio Melotti85769532012-03-12 23:52:40 +0200337 fout.setparams((1, sampwidth, 1, 1, b'ULAW', b''))
338 frames = b'\x00' * fout.getnchannels() * sampwidth
339 fout.writeframes(frames)
340 fout.close()
Ezio Melotti4b843a72013-03-01 21:10:26 +0200341 f = self.f = aifc.open(filename, 'rb')
Ezio Melotti85769532012-03-12 23:52:40 +0200342 self.assertEqual(f.getcomptype(), b'NONE')
343 f.close()
344
Antoine Pitrou03757ec2012-01-17 17:13:04 +0100345
R. David Murrayb507d2e2009-04-29 15:34:32 +0000346def test_main():
347 run_unittest(AIFCTest)
Antoine Pitrou03757ec2012-01-17 17:13:04 +0100348 run_unittest(AIFCLowLevelTest)
R. David Murrayb507d2e2009-04-29 15:34:32 +0000349
350
351if __name__ == "__main__":
352 unittest.main()