Ezio Melotti | 48d578c | 2012-03-12 23:57:18 +0200 | [diff] [blame] | 1 | from test.support import findfile, run_unittest, TESTFN, unlink |
R. David Murray | b507d2e | 2009-04-29 15:34:32 +0000 | [diff] [blame] | 2 | import unittest |
R. David Murray | eb01a6c | 2009-04-29 20:40:42 +0000 | [diff] [blame] | 3 | import os |
Sandro Tosi | bdd5354 | 2012-01-01 18:04:37 +0100 | [diff] [blame] | 4 | import io |
Ezio Melotti | 8576953 | 2012-03-12 23:52:40 +0200 | [diff] [blame] | 5 | import struct |
R. David Murray | b507d2e | 2009-04-29 15:34:32 +0000 | [diff] [blame] | 6 | |
| 7 | import aifc |
| 8 | |
| 9 | |
| 10 | class AIFCTest(unittest.TestCase): |
| 11 | |
| 12 | def setUp(self): |
R. David Murray | eb01a6c | 2009-04-29 20:40:42 +0000 | [diff] [blame] | 13 | self.f = self.fout = None |
R. David Murray | b507d2e | 2009-04-29 15:34:32 +0000 | [diff] [blame] | 14 | self.sndfilepath = findfile('Sine-1000Hz-300ms.aif') |
| 15 | |
R. David Murray | eb01a6c | 2009-04-29 20:40:42 +0000 | [diff] [blame] | 16 | 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 Melotti | 8576953 | 2012-03-12 23:52:40 +0200 | [diff] [blame] | 24 | unlink(TESTFN) |
| 25 | unlink(TESTFN + '.aiff') |
R. David Murray | eb01a6c | 2009-04-29 20:40:42 +0000 | [diff] [blame] | 26 | |
R. David Murray | b507d2e | 2009-04-29 15:34:32 +0000 | [diff] [blame] | 27 | def test_skipunknown(self): |
| 28 | #Issue 2245 |
| 29 | #This file contains chunk types aifc doesn't recognize. |
Benjamin Peterson | 25c95f1 | 2009-05-08 20:42:26 +0000 | [diff] [blame] | 30 | self.f = aifc.open(self.sndfilepath) |
R. David Murray | b507d2e | 2009-04-29 15:34:32 +0000 | [diff] [blame] | 31 | |
| 32 | def test_params(self): |
R. David Murray | eb01a6c | 2009-04-29 20:40:42 +0000 | [diff] [blame] | 33 | f = self.f = aifc.open(self.sndfilepath) |
Ezio Melotti | 8576953 | 2012-03-12 23:52:40 +0200 | [diff] [blame] | 34 | self.assertEqual(f.getfp().name, self.sndfilepath) |
R. David Murray | b507d2e | 2009-04-29 15:34:32 +0000 | [diff] [blame] | 35 | 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 Murray | b507d2e | 2009-04-29 15:34:32 +0000 | [diff] [blame] | 39 | 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 Murray | b507d2e | 2009-04-29 15:34:32 +0000 | [diff] [blame] | 45 | |
| 46 | def test_read(self): |
R. David Murray | eb01a6c | 2009-04-29 20:40:42 +0000 | [diff] [blame] | 47 | f = self.f = aifc.open(self.sndfilepath) |
Ezio Melotti | 8576953 | 2012-03-12 23:52:40 +0200 | [diff] [blame] | 48 | self.assertEqual(f.readframes(0), b'') |
R. David Murray | b507d2e | 2009-04-29 15:34:32 +0000 | [diff] [blame] | 49 | 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 Melotti | 8576953 | 2012-03-12 23:52:40 +0200 | [diff] [blame] | 62 | with self.assertRaises(aifc.Error): |
| 63 | f.setpos(-1) |
| 64 | with self.assertRaises(aifc.Error): |
| 65 | f.setpos(f.getnframes() + 1) |
R. David Murray | b507d2e | 2009-04-29 15:34:32 +0000 | [diff] [blame] | 66 | |
R. David Murray | eb01a6c | 2009-04-29 20:40:42 +0000 | [diff] [blame] | 67 | 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 Murray | b507d2e | 2009-04-29 15:34:32 +0000 | [diff] [blame] | 100 | |
R. David Murray | 9935274 | 2009-05-07 18:24:38 +0000 | [diff] [blame] | 101 | 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) |
| 115 | |
Sandro Tosi | bdd5354 | 2012-01-01 18:04:37 +0100 | [diff] [blame] | 116 | def test_write_header_comptype_sampwidth(self): |
| 117 | for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'): |
Ezio Melotti | 8576953 | 2012-03-12 23:52:40 +0200 | [diff] [blame] | 118 | fout = aifc.open(io.BytesIO(), 'wb') |
Sandro Tosi | bdd5354 | 2012-01-01 18:04:37 +0100 | [diff] [blame] | 119 | fout.setnchannels(1) |
| 120 | fout.setframerate(1) |
| 121 | fout.setcomptype(comptype, b'') |
| 122 | fout.close() |
| 123 | self.assertEqual(fout.getsampwidth(), 2) |
| 124 | fout.initfp(None) |
| 125 | |
Sandro Tosi | 70efbef | 2012-01-01 22:53:08 +0100 | [diff] [blame] | 126 | def test_write_markers_values(self): |
Ezio Melotti | 8576953 | 2012-03-12 23:52:40 +0200 | [diff] [blame] | 127 | fout = aifc.open(io.BytesIO(), 'wb') |
Sandro Tosi | 70efbef | 2012-01-01 22:53:08 +0100 | [diff] [blame] | 128 | self.assertEqual(fout.getmarkers(), None) |
| 129 | fout.setmark(1, 0, b'foo1') |
| 130 | fout.setmark(1, 1, b'foo2') |
| 131 | self.assertEqual(fout.getmark(1), (1, 1, b'foo2')) |
| 132 | self.assertEqual(fout.getmarkers(), [(1, 1, b'foo2')]) |
| 133 | fout.initfp(None) |
| 134 | |
| 135 | def test_read_markers(self): |
| 136 | fout = self.fout = aifc.open(TESTFN, 'wb') |
| 137 | fout.aiff() |
| 138 | fout.setparams((1, 1, 1, 1, b'NONE', b'')) |
| 139 | fout.setmark(1, 0, b'odd') |
| 140 | fout.setmark(2, 0, b'even') |
| 141 | fout.writeframes(b'\x00') |
| 142 | fout.close() |
| 143 | f = self.f = aifc.open(TESTFN, 'rb') |
| 144 | self.assertEqual(f.getmarkers(), [(1, 0, b'odd'), (2, 0, b'even')]) |
| 145 | self.assertEqual(f.getmark(1), (1, 0, b'odd')) |
| 146 | self.assertEqual(f.getmark(2), (2, 0, b'even')) |
| 147 | self.assertRaises(aifc.Error, f.getmark, 3) |
| 148 | |
R. David Murray | b507d2e | 2009-04-29 15:34:32 +0000 | [diff] [blame] | 149 | |
Antoine Pitrou | 03757ec | 2012-01-17 17:13:04 +0100 | [diff] [blame] | 150 | class AIFCLowLevelTest(unittest.TestCase): |
| 151 | |
| 152 | def test_read_written(self): |
| 153 | def read_written(self, what): |
| 154 | f = io.BytesIO() |
| 155 | getattr(aifc, '_write_' + what)(f, x) |
| 156 | f.seek(0) |
| 157 | return getattr(aifc, '_read_' + what)(f) |
| 158 | for x in (-1, 0, 0.1, 1): |
| 159 | self.assertEqual(read_written(x, 'float'), x) |
| 160 | for x in (float('NaN'), float('Inf')): |
| 161 | self.assertEqual(read_written(x, 'float'), aifc._HUGE_VAL) |
| 162 | for x in (b'', b'foo', b'a' * 255): |
| 163 | self.assertEqual(read_written(x, 'string'), x) |
| 164 | for x in (-0x7FFFFFFF, -1, 0, 1, 0x7FFFFFFF): |
| 165 | self.assertEqual(read_written(x, 'long'), x) |
| 166 | for x in (0, 1, 0xFFFFFFFF): |
| 167 | self.assertEqual(read_written(x, 'ulong'), x) |
| 168 | for x in (-0x7FFF, -1, 0, 1, 0x7FFF): |
| 169 | self.assertEqual(read_written(x, 'short'), x) |
| 170 | for x in (0, 1, 0xFFFF): |
| 171 | self.assertEqual(read_written(x, 'ushort'), x) |
| 172 | |
| 173 | def test_read_raises(self): |
| 174 | f = io.BytesIO(b'\x00') |
| 175 | self.assertRaises(EOFError, aifc._read_ulong, f) |
| 176 | self.assertRaises(EOFError, aifc._read_long, f) |
| 177 | self.assertRaises(EOFError, aifc._read_ushort, f) |
| 178 | self.assertRaises(EOFError, aifc._read_short, f) |
| 179 | |
| 180 | def test_write_long_string_raises(self): |
| 181 | f = io.BytesIO() |
| 182 | with self.assertRaises(ValueError): |
| 183 | aifc._write_string(f, b'too long' * 255) |
| 184 | |
Ezio Melotti | 8576953 | 2012-03-12 23:52:40 +0200 | [diff] [blame] | 185 | def test_wrong_open_mode(self): |
| 186 | with self.assertRaises(aifc.Error): |
| 187 | aifc.open(TESTFN, 'wrong_mode') |
| 188 | |
| 189 | def test_read_wrong_form(self): |
| 190 | b1 = io.BytesIO(b'WRNG' + struct.pack('>L', 0)) |
| 191 | b2 = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'WRNG') |
| 192 | self.assertRaises(aifc.Error, aifc.open, b1) |
| 193 | self.assertRaises(aifc.Error, aifc.open, b2) |
| 194 | |
| 195 | def test_read_no_comm_chunk(self): |
| 196 | b = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'AIFF') |
| 197 | self.assertRaises(aifc.Error, aifc.open, b) |
| 198 | |
| 199 | def test_read_wrong_compression_type(self): |
| 200 | b = b'FORM' + struct.pack('>L', 4) + b'AIFC' |
| 201 | b += b'COMM' + struct.pack('>LhlhhLL', 23, 0, 0, 0, 0, 0, 0) |
| 202 | b += b'WRNG' + struct.pack('B', 0) |
| 203 | self.assertRaises(aifc.Error, aifc.open, io.BytesIO(b)) |
| 204 | |
| 205 | def test_read_wrong_marks(self): |
| 206 | b = b'FORM' + struct.pack('>L', 4) + b'AIFF' |
| 207 | b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0) |
| 208 | b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8 |
| 209 | b += b'MARK' + struct.pack('>LhB', 3, 1, 1) |
Ezio Melotti | 48d578c | 2012-03-12 23:57:18 +0200 | [diff] [blame] | 210 | with self.assertWarns(UserWarning): |
Ezio Melotti | 8576953 | 2012-03-12 23:52:40 +0200 | [diff] [blame] | 211 | f = aifc.open(io.BytesIO(b)) |
Ezio Melotti | 8576953 | 2012-03-12 23:52:40 +0200 | [diff] [blame] | 212 | self.assertEqual(f.getmarkers(), None) |
| 213 | |
| 214 | def test_read_comm_kludge_compname_even(self): |
| 215 | b = b'FORM' + struct.pack('>L', 4) + b'AIFC' |
| 216 | b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0) |
| 217 | b += b'NONE' + struct.pack('B', 4) + b'even' + b'\x00' |
| 218 | b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8 |
Ezio Melotti | 48d578c | 2012-03-12 23:57:18 +0200 | [diff] [blame] | 219 | with self.assertWarns(UserWarning): |
Ezio Melotti | 8576953 | 2012-03-12 23:52:40 +0200 | [diff] [blame] | 220 | f = aifc.open(io.BytesIO(b)) |
Ezio Melotti | 8576953 | 2012-03-12 23:52:40 +0200 | [diff] [blame] | 221 | self.assertEqual(f.getcompname(), b'even') |
| 222 | |
| 223 | def test_read_comm_kludge_compname_odd(self): |
| 224 | b = b'FORM' + struct.pack('>L', 4) + b'AIFC' |
| 225 | b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0) |
| 226 | b += b'NONE' + struct.pack('B', 3) + b'odd' |
| 227 | b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8 |
Ezio Melotti | 48d578c | 2012-03-12 23:57:18 +0200 | [diff] [blame] | 228 | with self.assertWarns(UserWarning): |
Ezio Melotti | 8576953 | 2012-03-12 23:52:40 +0200 | [diff] [blame] | 229 | f = aifc.open(io.BytesIO(b)) |
Ezio Melotti | 8576953 | 2012-03-12 23:52:40 +0200 | [diff] [blame] | 230 | self.assertEqual(f.getcompname(), b'odd') |
| 231 | |
| 232 | def test_write_params_raises(self): |
| 233 | fout = aifc.open(io.BytesIO(), 'wb') |
| 234 | wrong_params = (0, 0, 0, 0, b'WRNG', '') |
| 235 | self.assertRaises(aifc.Error, fout.setparams, wrong_params) |
| 236 | self.assertRaises(aifc.Error, fout.getparams) |
| 237 | self.assertRaises(aifc.Error, fout.setnchannels, 0) |
| 238 | self.assertRaises(aifc.Error, fout.getnchannels) |
| 239 | self.assertRaises(aifc.Error, fout.setsampwidth, 0) |
| 240 | self.assertRaises(aifc.Error, fout.getsampwidth) |
| 241 | self.assertRaises(aifc.Error, fout.setframerate, 0) |
| 242 | self.assertRaises(aifc.Error, fout.getframerate) |
| 243 | self.assertRaises(aifc.Error, fout.setcomptype, b'WRNG', '') |
| 244 | fout.aiff() |
| 245 | fout.setnchannels(1) |
| 246 | fout.setsampwidth(1) |
| 247 | fout.setframerate(1) |
| 248 | fout.setnframes(1) |
| 249 | fout.writeframes(b'\x00') |
| 250 | self.assertRaises(aifc.Error, fout.setparams, (1, 1, 1, 1, 1, 1)) |
| 251 | self.assertRaises(aifc.Error, fout.setnchannels, 1) |
| 252 | self.assertRaises(aifc.Error, fout.setsampwidth, 1) |
| 253 | self.assertRaises(aifc.Error, fout.setframerate, 1) |
| 254 | self.assertRaises(aifc.Error, fout.setnframes, 1) |
| 255 | self.assertRaises(aifc.Error, fout.setcomptype, b'NONE', '') |
| 256 | self.assertRaises(aifc.Error, fout.aiff) |
| 257 | self.assertRaises(aifc.Error, fout.aifc) |
| 258 | |
| 259 | def test_write_params_singles(self): |
| 260 | fout = aifc.open(io.BytesIO(), 'wb') |
| 261 | fout.aifc() |
| 262 | fout.setnchannels(1) |
| 263 | fout.setsampwidth(2) |
| 264 | fout.setframerate(3) |
| 265 | fout.setnframes(4) |
| 266 | fout.setcomptype(b'NONE', b'name') |
| 267 | self.assertEqual(fout.getnchannels(), 1) |
| 268 | self.assertEqual(fout.getsampwidth(), 2) |
| 269 | self.assertEqual(fout.getframerate(), 3) |
| 270 | self.assertEqual(fout.getnframes(), 0) |
| 271 | self.assertEqual(fout.tell(), 0) |
| 272 | self.assertEqual(fout.getcomptype(), b'NONE') |
| 273 | self.assertEqual(fout.getcompname(), b'name') |
| 274 | fout.writeframes(b'\x00' * 4 * fout.getsampwidth() * fout.getnchannels()) |
| 275 | self.assertEqual(fout.getnframes(), 4) |
| 276 | self.assertEqual(fout.tell(), 4) |
| 277 | |
| 278 | def test_write_params_bunch(self): |
| 279 | fout = aifc.open(io.BytesIO(), 'wb') |
| 280 | fout.aifc() |
| 281 | p = (1, 2, 3, 4, b'NONE', b'name') |
| 282 | fout.setparams(p) |
| 283 | self.assertEqual(fout.getparams(), p) |
| 284 | fout.initfp(None) |
| 285 | |
| 286 | def test_write_header_raises(self): |
| 287 | fout = aifc.open(io.BytesIO(), 'wb') |
| 288 | self.assertRaises(aifc.Error, fout.close) |
| 289 | fout.setnchannels(1) |
| 290 | self.assertRaises(aifc.Error, fout.close) |
| 291 | fout.setsampwidth(1) |
| 292 | self.assertRaises(aifc.Error, fout.close) |
| 293 | fout.initfp(None) |
| 294 | |
| 295 | def test_write_header_comptype_raises(self): |
| 296 | for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'): |
| 297 | fout = aifc.open(io.BytesIO(), 'wb') |
| 298 | fout.setsampwidth(1) |
| 299 | fout.setcomptype(comptype, b'') |
| 300 | self.assertRaises(aifc.Error, fout.close) |
| 301 | fout.initfp(None) |
| 302 | |
| 303 | def test_write_markers_raises(self): |
| 304 | fout = aifc.open(io.BytesIO(), 'wb') |
| 305 | self.assertRaises(aifc.Error, fout.setmark, 0, 0, b'') |
| 306 | self.assertRaises(aifc.Error, fout.setmark, 1, -1, b'') |
| 307 | self.assertRaises(aifc.Error, fout.setmark, 1, 0, None) |
| 308 | self.assertRaises(aifc.Error, fout.getmark, 1) |
| 309 | fout.initfp(None) |
| 310 | |
| 311 | def test_write_aiff_by_extension(self): |
| 312 | sampwidth = 2 |
| 313 | fout = self.fout = aifc.open(TESTFN + '.aiff', 'wb') |
| 314 | fout.setparams((1, sampwidth, 1, 1, b'ULAW', b'')) |
| 315 | frames = b'\x00' * fout.getnchannels() * sampwidth |
| 316 | fout.writeframes(frames) |
| 317 | fout.close() |
| 318 | f = self.f = aifc.open(TESTFN + '.aiff', 'rb') |
| 319 | self.assertEqual(f.getcomptype(), b'NONE') |
| 320 | f.close() |
| 321 | |
Antoine Pitrou | 03757ec | 2012-01-17 17:13:04 +0100 | [diff] [blame] | 322 | |
R. David Murray | b507d2e | 2009-04-29 15:34:32 +0000 | [diff] [blame] | 323 | def test_main(): |
| 324 | run_unittest(AIFCTest) |
Antoine Pitrou | 03757ec | 2012-01-17 17:13:04 +0100 | [diff] [blame] | 325 | run_unittest(AIFCLowLevelTest) |
R. David Murray | b507d2e | 2009-04-29 15:34:32 +0000 | [diff] [blame] | 326 | |
| 327 | |
| 328 | if __name__ == "__main__": |
| 329 | unittest.main() |