1# -*- coding: utf-8 -*-
2
3import sys
4import struct
5
6from tests import TestCase
7
8from mutagen._compat import PY2
9from mutagen.id3._util import BitPaddedInt, BitPaddedLong, unsynch
10
11
12class BitPaddedIntTest(TestCase):
13
14    def test_long(self):
15        if PY2:
16            data = BitPaddedInt.to_str(sys.maxint + 1, width=16)
17            val = BitPaddedInt(data)
18            self.assertEqual(val, sys.maxint + 1)
19            self.assertTrue(isinstance(val, BitPaddedLong))
20        else:
21            self.assertTrue(BitPaddedInt is BitPaddedLong)
22
23    def test_negative(self):
24        self.assertRaises(ValueError, BitPaddedInt, -1)
25
26    def test_zero(self):
27        self.assertEquals(BitPaddedInt(b'\x00\x00\x00\x00'), 0)
28
29    def test_1(self):
30        self.assertEquals(BitPaddedInt(b'\x00\x00\x00\x01'), 1)
31
32    def test_1l(self):
33        self.assertEquals(
34            BitPaddedInt(b'\x01\x00\x00\x00', bigendian=False), 1)
35
36    def test_129(self):
37        self.assertEquals(BitPaddedInt(b'\x00\x00\x01\x01'), 0x81)
38
39    def test_129b(self):
40        self.assertEquals(BitPaddedInt(b'\x00\x00\x01\x81'), 0x81)
41
42    def test_65(self):
43        self.assertEquals(BitPaddedInt(b'\x00\x00\x01\x81', 6), 0x41)
44
45    def test_32b(self):
46        self.assertEquals(BitPaddedInt(b'\xFF\xFF\xFF\xFF', bits=8),
47                          0xFFFFFFFF)
48
49    def test_32bi(self):
50        self.assertEquals(BitPaddedInt(0xFFFFFFFF, bits=8), 0xFFFFFFFF)
51
52    def test_s32b(self):
53        self.assertEquals(BitPaddedInt(b'\xFF\xFF\xFF\xFF', bits=8).as_str(),
54                          b'\xFF\xFF\xFF\xFF')
55
56    def test_s0(self):
57        self.assertEquals(BitPaddedInt.to_str(0), b'\x00\x00\x00\x00')
58
59    def test_s1(self):
60        self.assertEquals(BitPaddedInt.to_str(1), b'\x00\x00\x00\x01')
61
62    def test_s1l(self):
63        self.assertEquals(
64            BitPaddedInt.to_str(1, bigendian=False), b'\x01\x00\x00\x00')
65
66    def test_s129(self):
67        self.assertEquals(BitPaddedInt.to_str(129), b'\x00\x00\x01\x01')
68
69    def test_s65(self):
70        self.assertEquals(BitPaddedInt.to_str(0x41, 6), b'\x00\x00\x01\x01')
71
72    def test_w129(self):
73        self.assertEquals(BitPaddedInt.to_str(129, width=2), b'\x01\x01')
74
75    def test_w129l(self):
76        self.assertEquals(
77            BitPaddedInt.to_str(129, width=2, bigendian=False), b'\x01\x01')
78
79    def test_wsmall(self):
80        self.assertRaises(ValueError, BitPaddedInt.to_str, 129, width=1)
81
82    def test_str_int_init(self):
83        self.assertEquals(BitPaddedInt(238).as_str(),
84                          BitPaddedInt(struct.pack('>L', 238)).as_str())
85
86    def test_varwidth(self):
87        self.assertEquals(len(BitPaddedInt.to_str(100)), 4)
88        self.assertEquals(len(BitPaddedInt.to_str(100, width=-1)), 4)
89        self.assertEquals(len(BitPaddedInt.to_str(2 ** 32, width=-1)), 5)
90
91    def test_minwidth(self):
92        self.assertEquals(
93            len(BitPaddedInt.to_str(100, width=-1, minwidth=6)), 6)
94
95    def test_inval_input(self):
96        self.assertRaises(TypeError, BitPaddedInt, None)
97
98    if PY2:
99        def test_promote_long(self):
100            l = BitPaddedInt(sys.maxint ** 2)
101            self.assertTrue(isinstance(l, long))
102            self.assertEqual(BitPaddedInt(l.as_str(width=-1)), l)
103
104    def test_has_valid_padding(self):
105        self.failUnless(BitPaddedInt.has_valid_padding(b"\xff\xff", bits=8))
106        self.failIf(BitPaddedInt.has_valid_padding(b"\xff"))
107        self.failIf(BitPaddedInt.has_valid_padding(b"\x00\xff"))
108        self.failUnless(BitPaddedInt.has_valid_padding(b"\x7f\x7f"))
109        self.failIf(BitPaddedInt.has_valid_padding(b"\x7f", bits=6))
110        self.failIf(BitPaddedInt.has_valid_padding(b"\x9f", bits=6))
111        self.failUnless(BitPaddedInt.has_valid_padding(b"\x3f", bits=6))
112
113        self.failUnless(BitPaddedInt.has_valid_padding(0xff, bits=8))
114        self.failIf(BitPaddedInt.has_valid_padding(0xff))
115        self.failIf(BitPaddedInt.has_valid_padding(0xff << 8))
116        self.failUnless(BitPaddedInt.has_valid_padding(0x7f << 8))
117        self.failIf(BitPaddedInt.has_valid_padding(0x9f << 32, bits=6))
118        self.failUnless(BitPaddedInt.has_valid_padding(0x3f << 16, bits=6))
119
120
121class TestUnsynch(TestCase):
122
123    def test_unsync_encode_decode(self):
124        pairs = [
125            (b'', b''),
126            (b'\x00', b'\x00'),
127            (b'\x44', b'\x44'),
128            (b'\x44\xff', b'\x44\xff\x00'),
129            (b'\xe0', b'\xe0'),
130            (b'\xe0\xe0', b'\xe0\xe0'),
131            (b'\xe0\xff', b'\xe0\xff\x00'),
132            (b'\xff', b'\xff\x00'),
133            (b'\xff\x00', b'\xff\x00\x00'),
134            (b'\xff\x00\x00', b'\xff\x00\x00\x00'),
135            (b'\xff\x01', b'\xff\x01'),
136            (b'\xff\x44', b'\xff\x44'),
137            (b'\xff\xe0', b'\xff\x00\xe0'),
138            (b'\xff\xe0\xff', b'\xff\x00\xe0\xff\x00'),
139            (b'\xff\xf0\x0f\x00', b'\xff\x00\xf0\x0f\x00'),
140            (b'\xff\xff', b'\xff\x00\xff\x00'),
141            (b'\xff\xff\x01', b'\xff\x00\xff\x01'),
142            (b'\xff\xff\xff\xff', b'\xff\x00\xff\x00\xff\x00\xff\x00'),
143        ]
144
145        for d, e in pairs:
146            self.assertEqual(unsynch.encode(d), e)
147            self.assertEqual(unsynch.decode(e), d)
148            self.assertEqual(unsynch.decode(unsynch.encode(e)), e)
149            self.assertEqual(unsynch.decode(e + e), d + d)
150
151    def test_unsync_decode_invalid(self):
152        self.assertRaises(ValueError, unsynch.decode, b'\xff\xff\xff\xff')
153        self.assertRaises(ValueError, unsynch.decode, b'\xff\xf0\x0f\x00')
154        self.assertRaises(ValueError, unsynch.decode, b'\xff\xe0')
155        self.assertRaises(ValueError, unsynch.decode, b'\xff')
156