1from PyObjCTools.TestSupport import *
2import objc
3import array
4
5from Foundation import *
6from PyObjCTest.testhelper import PyObjC_TestClass3
7
8rawBytes = "a\x13b\x00cd\xFFef\xEFgh"
9otherBytes = array.array('c')
10otherBytes.fromstring('12345678901234567890' * 5)
11
12class TestNSData(TestCase):
13    def testMethods(self):
14        self.failUnlessResultIsBOOL(NSData.writeToFile_atomically_)
15        self.failUnlessArgIsBOOL(NSData.writeToFile_atomically_, 1)
16        self.failUnlessResultIsBOOL(NSData.writeToURL_atomically_)
17        self.failUnlessArgIsBOOL(NSData.writeToURL_atomically_, 1)
18        self.failUnlessResultIsBOOL(NSData.writeToFile_options_error_)
19        self.failUnlessArgIsOut(NSData.writeToFile_options_error_, 2)
20        self.failUnlessResultIsBOOL(NSData.writeToURL_options_error_)
21        self.failUnlessArgIsOut(NSData.writeToURL_options_error_, 2)
22        self.failUnlessArgIsOut(NSData.dataWithContentsOfFile_options_error_, 2)
23        self.failUnlessArgIsOut(NSData.dataWithContentsOfURL_options_error_, 2)
24        self.failUnlessArgIsOut(NSData.initWithContentsOfFile_options_error_, 2)
25        self.failUnlessArgIsOut(NSData.initWithContentsOfURL_options_error_, 2)
26
27    def testConstants(self):
28        self.assertEquals(NSMappedRead, 1)
29        self.assertEquals(NSUncachedRead, 2)
30
31        self.assertEquals(NSAtomicWrite, 1)
32
33    def assertDataContents(self, d1, d2, rawData):
34        self.assertEquals(len(d1), d1.length(), "d1: len() and -length didn't match.")
35        self.assertEquals(len(d1), len(rawData), "d1: len(<data>) and len(<input>) didn't match. %d vs %d"%(len(d1), len(rawData)))
36        self.assertEquals(len(d2), d2.length(), "d2: len() and -length didn't match.")
37        self.assertEquals(len(d2), len(rawData), "d2: len(<data>) and len(<input>) didn't match. %d vs %d"%(len(d2), len(rawData)))
38
39    def testDataWithBytes_length_(self):
40        """Test +dataWithBytes:length:"""
41        data = NSData.dataWithBytes_length_(rawBytes, len(rawBytes))
42        mutableData = NSMutableData.dataWithBytes_length_(rawBytes, len(rawBytes))
43        self.assertDataContents(data, mutableData, rawBytes)
44
45    def testAppendBytes_length_(self):
46        self.failUnlessArgIsIn(NSMutableData.appendBytes_length_, 0)
47        self.failUnlessArgSizeInArg(NSMutableData.appendBytes_length_, 0, 1)
48
49    def testreplaceBytesInRange_withBytes_(self):
50        self.failUnlessArgIsIn(NSMutableData.replaceBytesInRange_withBytes_, 1)
51        self.failUnlessArgSizeInArg(NSMutableData.replaceBytesInRange_withBytes_, 1, 0)
52
53    def testreplaceBytesInRange_withBytes_length_(self):
54        self.failUnlessArgIsIn(NSMutableData.replaceBytesInRange_withBytes_length_, 1)
55        self.failUnlessArgSizeInArg(NSMutableData.replaceBytesInRange_withBytes_length_, 1, 2)
56
57    def testDataWithBytesNoCopy_length_freeWhenDone_(self):
58        data = NSData.dataWithBytesNoCopy_length_freeWhenDone_(rawBytes, len(rawBytes), False)
59        mutableData = NSMutableData.dataWithBytesNoCopy_length_freeWhenDone_(rawBytes, len(rawBytes), False)
60        self.assertDataContents(data, mutableData, rawBytes)
61
62    def testInitWithBytes_length_(self):
63        """Test -initWithBytes:length:"""
64        data = NSData.alloc().initWithBytes_length_(rawBytes, len(rawBytes))
65        mutableData = NSMutableData.alloc().initWithBytes_length_(rawBytes, len(rawBytes))
66        self.assertDataContents(data, mutableData, rawBytes)
67
68    def testInitWithBytesNoCopy_length_freeWhenDone_(self):
69        """Test -initWithBytesNoCopy:length:"""
70        data = NSData.alloc().initWithBytesNoCopy_length_freeWhenDone_(rawBytes, len(rawBytes), False)
71        mutableData = NSMutableData.alloc().initWithBytesNoCopy_length_freeWhenDone_(rawBytes, len(rawBytes), False)
72        self.assertDataContents(data, mutableData, rawBytes)
73
74    def testBytes(self):
75        """Test -bytes"""
76        data = NSData.alloc().initWithBytes_length_(rawBytes, len(rawBytes))
77        bytes = data.bytes()
78        self.assertEquals(len(bytes), len(rawBytes), "bytes() and rawBytes not equal length.")
79        for i in range(0,len(bytes)):
80            self.assertEquals(rawBytes[i], bytes[i], "byte %s of bytes and rawBytes are not equal." % i)
81
82        try:
83            bytes[3] = 0xAE
84        except TypeError, r:
85            if str(r).find('buffer is read-only') is not 0:
86                raise
87
88    def testMutableBytes(self):
89        """Test -mutableBytes"""
90        mutableData = NSMutableData.dataWithBytes_length_(rawBytes, len(rawBytes))
91        mutableBytes = mutableData.mutableBytes()
92        for i in range(0, len(mutableBytes)):
93            mutableBytes[i] = otherBytes[i]
94        mutableBytes[1:8] = otherBytes[1:8]
95
96        try:
97            mutableBytes[2:10] = otherBytes[1:5]
98        except TypeError, r:
99            if str(r).find('right operand length must match slice length') is not 0:
100                raise
101
102    def testVariousDataLengths(self):
103        """Test data of different lengths.
104
105        Data of different lengths may be stored in different subclasses within the class cluster.
106        """
107        testFactor = range(1, 64) + [ 1000, 10000, 1000000]
108        for aFactor in testFactor:
109            bigRawBytes = "1234567890" * aFactor
110
111            mutableData = NSMutableData.dataWithBytes_length_(bigRawBytes, len(bigRawBytes))
112            data = NSData.dataWithBytes_length_(bigRawBytes, len(bigRawBytes))
113
114            self.assertDataContents(data, mutableData, bigRawBytes)
115
116            mutableBytes = mutableData.mutableBytes()
117            bytes = data.bytes()
118
119            self.assertEquals(len(bytes), data.length())
120            self.assertEquals(len(mutableBytes), mutableData.length())
121            self.assertEquals(bytes, mutableBytes)
122
123            mutableBytes[0:len(mutableBytes)] = bytes[0:len(bytes)]
124
125    def testInitWithContents(self):
126        b, err = NSData.alloc().initWithContentsOfFile_options_error_(
127                "/etc/hosts", 0, None)
128        self.failUnless(isinstance(b, NSData))
129        self.failUnless(err is None)
130
131        b2, err = NSData.alloc().initWithContentsOfFile_options_error_(
132                "/etc/hosts.nosuchfile", 0, None)
133        self.failUnless(b2 is None)
134        self.failUnless(isinstance(err, NSError))
135
136        url = NSURL.fileURLWithPath_isDirectory_('/etc/hosts', False)
137        b, err = NSData.alloc().initWithContentsOfURL_options_error_(
138                url, 0, None)
139        self.failUnless(isinstance(b, NSData))
140        self.failUnless(err is None)
141
142        url = NSURL.fileURLWithPath_isDirectory_('/etc/hosts.nosuchfile', False)
143        b2, err = NSData.alloc().initWithContentsOfURL_options_error_(
144                url, 0, None)
145        self.failUnless(b2 is None)
146        self.failUnless(isinstance(err, NSError))
147
148
149class MyData (NSData):
150    def dataWithBytes_length_(self, bytes, length):
151        return ("data", bytes, length)
152
153BYTES="dummy bytes"
154class MyData2 (NSData):
155    def initWithBytes_length_(self, bytes, length):
156        return ("init", bytes, length)
157
158    def length(self):
159        return 42
160
161    def bytes(self):
162        return BYTES
163
164
165class MyData3 (NSData):
166    def initWithBytes_length_(self, bytes, length):
167        self._bytes = bytes
168        self._length = length
169        return self
170
171    def bytes(self):
172        return self._bytes
173
174    def length(self):
175        if hasattr(self, '_length'):
176            return self._length
177        return -1
178
179class MyData4 (NSData):
180    def initWithBytes_length_(self, bytes, length):
181        return self
182
183    def bytes(self):
184        return None
185
186    def length(self):
187        return -1
188
189class MyData5(NSData):
190    def initWithBytes_length_(self, bytes, length):
191        return self
192
193    def bytes(self):
194        raise ValueError, "No bytes available"
195
196    def length(self):
197        return -1
198
199
200
201class TestMyData (TestCase):
202    # 'initWithBytes:length:' and 'dataWithBytes:length:' have custom IMP's
203    def testData(self):
204        r = PyObjC_TestClass3.makeDataWithBytes_method_(MyData, 0)
205        self.assertEquals(r, ('data', 'hello world', 11))
206
207    def testInit(self):
208        r = PyObjC_TestClass3.makeDataWithBytes_method_(MyData2, 1)
209        self.assertEquals(r, ('init', 'hello world', 11))
210
211    def testBytes(self):
212        r = PyObjC_TestClass3.makeDataWithBytes_method_(MyData3, 1)
213        b = PyObjC_TestClass3.getBytes_(r)
214        self.assertEquals(str(b.bytes()), 'hello world')
215
216        self.assertEquals(b.getBytes_length_(None, 4), 'hell')
217        self.assertEquals(b.getBytes_range_(None, NSRange(2, 4)), 'llo ')
218
219
220    def testBytesNone(self):
221        b = PyObjC_TestClass3.makeDataWithBytes_method_(MyData4, 1)
222        self.assertEquals(b.bytes(), None)
223
224    def testBytesRaises(self):
225        b = PyObjC_TestClass3.makeDataWithBytes_method_(MyData5, 1)
226        self.assertRaises(ValueError, b.bytes)
227
228
229
230import array
231class TestBuffer(TestCase):
232    def testArray(self):
233        a = array.array('c', 'foo')
234        m = NSMutableData.dataWithData_(a)
235        self.assertEquals(a.tostring(), m[:])
236        self.assert_(objc.repythonify(a) is a)
237        a.fromstring(m)
238        self.assertEquals(a.tostring(), 'foofoo')
239        m.appendData_(a)
240        self.assertEquals(m[:], 'foofoofoo')
241        m[3:6] = 'bar'
242        self.assertEquals(m[:], 'foobarfoo')
243
244    def testBuffer(self):
245        b = buffer('foo')
246        m = NSMutableData.dataWithData_(b)
247        self.assertEquals(b[:], m[:])
248        self.assert_(objc.repythonify(b) is b)
249        self.assertEquals(buffer(m)[:], m[:])
250
251
252
253
254
255if __name__ == '__main__':
256    main( )
257