1from PyObjCTools.TestSupport import *
2import objc
3
4from Foundation import *
5
6import sys
7if sys.version_info[0] == 3:
8    def cmp(a, b):
9        if a < b:
10            return -1
11        elif b < a:
12            return 1
13        return 0
14
15class TestNSArrayInteraction(TestCase):
16    def testRepeatedAllocInit(self):
17        for i in range(1,1000):
18            a = NSArray.alloc().init()
19
20    def testIndices(self):
21        x = NSArray.arrayWithArray_( [b"foo".decode('ascii'), b"bar".decode('ascii'), b"baz".decode('ascii')] )
22
23        self.assertEqual( x.indexOfObject_(b"bar".decode('ascii')), 1 )
24
25        self.assertRaises( IndexError, x.objectAtIndex_, 100)
26
27    def testEnumeration(self):
28        x = NSArray.arrayWithArray_([1, 2, b"foo".decode('ascii'), b"bar".decode('ascii'), b"".decode('ascii'), b"baz".decode('ascii')])
29        y = []
30
31        for o in x:
32            y.append(o)
33
34        self.assertEqual(len(x), len(y))
35
36    def testContains(self):
37        x = NSArray.arrayWithArray_( [b"foo".decode('ascii'), b"bar".decode('ascii'), b"baz".decode('ascii')] )
38        self.assertEqual( x.count(), 3 )
39        self.assertEqual( len(x), 3 )
40
41        self.assertTrue( x.containsObject_(b"foo".decode('ascii')) )
42        self.assertTrue( not x.containsObject_(b"dumbledorf".decode('ascii')) )
43
44        self.assertTrue( b"foo".decode('ascii') in x )
45        self.assertTrue( not b"dumbledorf".decode('ascii') in x )
46
47    def testIn(self):
48        x = NSMutableArray.array()
49        for i in range(0, 100):
50            x.addObject_(i)
51
52        y = []
53        for i in x:
54            y.append( i )
55
56        z = []
57        for i in range(0, 100):
58            z.append( i )
59
60        self.assertEqual(x, y)
61        self.assertEqual(x, z)
62        self.assertEqual(y, z)
63
64        for i in range(0, 100):
65            self.assertTrue( i in x )
66
67        self.assertTrue( 101 not in x )
68        self.assertTrue( None not in x )
69        self.assertTrue( b"foo bar".decode('ascii') not in x )
70
71    def assertSlicesEqual(self,  x, y, z):
72        self.assertEqual( x, x[:] )
73        self.assertEqual( y, y[:] )
74        self.assertEqual( z, z[:] )
75
76        self.assertEqual( x[25:75], y[25:75] )
77        self.assertEqual( x[25:75], z[25:75] )
78        self.assertEqual( y[25:75], z[25:75] )
79
80        self.assertEqual( x[:15], y[:15] )
81        self.assertEqual( x[:15], z[:15] )
82        self.assertEqual( y[:15], z[:15] )
83
84        self.assertEqual( x[15:], y[15:] )
85        self.assertEqual( x[15:], z[15:] )
86        self.assertEqual( y[15:], z[15:] )
87
88        self.assertEqual( x[-15:], y[-15:] )
89        self.assertEqual( x[-15:], z[-15:] )
90        self.assertEqual( y[-15:], z[-15:] )
91
92        self.assertEqual( x[-15:30], y[-15:30] )
93        self.assertEqual( x[-15:30], z[-15:30] )
94        self.assertEqual( y[-15:30], z[-15:30] )
95
96        self.assertEqual( x[-15:-5], y[-15:-5] )
97        self.assertEqual( x[-15:-5], z[-15:-5] )
98        self.assertEqual( y[-15:-5], z[-15:-5] )
99
100    def testSlice(self):
101        x = NSMutableArray.array()
102        for i in range(0, 100):
103            x.addObject_(i)
104
105        y = []
106        for i in x:
107            y.append( i )
108
109        z = []
110        for i in range(0, 100):
111            z.append( i )
112
113        self.assertSlicesEqual(x, y, z)
114
115        k = range(300, 50)
116        x[20:30] = k
117        y[20:30] = k
118        z[20:30] = k
119
120        self.assertSlicesEqual(x, y, z)
121
122        # Note that x[1] = x works in python, but not for a bridged NS*Array*.
123        # Not sure if there is anything we can do about that.
124        x[1] = x[:]
125        y[1] = y[:]
126        z[1] = z[:]
127
128        self.assertSlicesEqual(x, y, z)
129
130        del x[-15:-5]
131        del y[-15:-5]
132        del z[-15:-5]
133
134        self.assertSlicesEqual(x, y, z)
135
136    def test_mixSliceNDice(self):
137        # This test failes on Python 2.2, that is expected.
138        x = list(range(0, 10))
139        y = NSMutableArray.arrayWithArray_( range(0, 10) )
140
141        y[2:4] = x[1:5]
142        x[2:8] = y[3:7]
143        y[2:4] = y[1:8]
144
145    def test_subScripts(self):
146        x = list(range(0, 10))
147        y = NSMutableArray.arrayWithArray_(x)
148
149        self.assertEqual( x[0], y[0] )
150        self.assertEqual( x[2], y[2] )
151
152        self.assertEqual( x[-1], y[-1] )
153        self.assertEqual( x[-5], y[-5] )
154
155        self.assertRaises( IndexError, x.__getitem__, 100)
156        self.assertRaises( IndexError, x.__getitem__, -100)
157
158    def test_varargConstruction(self):
159        w = NSArray.arrayWithObjects_(1,2,3,4)
160        x = NSArray.alloc().initWithObjects_(1,2,3,4)
161
162        y = NSArray.arrayWithObjects_count_([1,2,3,4,5,6], 4)
163        z = NSArray.alloc().initWithObjects_count_([1,2,3,4,5,6], 4)
164
165        self.assertEqual(len(w), 4)
166        self.assertEqual(len(x), 4)
167        self.assertEqual(len(y), 4)
168        self.assertEqual(len(z), 4)
169
170        self.assertEqual(w[0], 1)
171        self.assertEqual(x[1], 2)
172        self.assertEqual(y[2], 3)
173        self.assertEqual(z[3], 4)
174
175    def test_varargConstruction2(self):
176        w = NSMutableArray.arrayWithObjects_(1,2,3,4, None)
177        x = NSMutableArray.alloc().initWithObjects_(1,2,3,4, None)
178        y = NSMutableArray.arrayWithObjects_count_([1,2,3,4,5,6], 4)
179        z = NSMutableArray.alloc().initWithObjects_count_([1,2,3,4,5,6], 4)
180
181        self.assertEqual(len(w), 4)
182        self.assertEqual(len(x), 4)
183        self.assertEqual(len(y), 4)
184        self.assertEqual(len(z), 4)
185
186        self.assertEqual(w[0], 1)
187        self.assertEqual(x[1], 2)
188        self.assertEqual(y[2], 3)
189        self.assertEqual(z[3], 4)
190
191class TestNSArraySpecialMethods(TestCase):
192    #Test calling 'difficult' methods from Python
193
194    def test_initWithObjects_count_(self):
195        a = NSArray.alloc().initWithObjects_count_((b'a'.decode('ascii'),b'b'.decode('ascii'),b'c'.decode('ascii'),b'd'.decode('ascii')), 3)
196        self.assertEqual(a, [b'a'.decode('ascii'),b'b'.decode('ascii'),b'c'.decode('ascii')])
197
198        import warnings
199        warnings.filterwarnings('ignore',
200                category=objc.UninitializedDeallocWarning)
201
202        try:
203            self.assertRaises(ValueError, NSArray.alloc().initWithObjects_count_, (b'a'.decode('ascii'),b'b'.decode('ascii')), 3)
204
205        finally:
206            del warnings.filters[0]
207
208
209    def test_arrayWithObjects_count_(self):
210        a = NSArray.arrayWithObjects_count_((b'a'.decode('ascii'),b'b'.decode('ascii'),b'c'.decode('ascii'),b'd'.decode('ascii')), 3)
211        self.assertEqual(a, [b'a'.decode('ascii'),b'b'.decode('ascii'),b'c'.decode('ascii')])
212
213        self.assertRaises(ValueError, NSArray.arrayWithObjects_count_, (b'a'.decode('ascii'),b'b'.decode('ascii')), 3)
214
215    def test_arrayByAddingObjects_count_(self):
216        return
217
218        a = NSArray.arrayWithArray_((b'a'.decode('ascii'), b'b'.decode('ascii'), b'c'.decode('ascii')))
219        self.assertEqual(a, (b'a'.decode('ascii'), b'b'.decode('ascii'), b'c'.decode('ascii')))
220
221        b = a.arrayByAddingObjects_count_((b'd'.decode('ascii'), b'e'.decode('ascii'), b'f'.decode('ascii')), 3)
222        self.assertEqual(a, (b'a'.decode('ascii'), b'b'.decode('ascii'), b'c'.decode('ascii')))
223        self.assertEqual(b, (b'a'.decode('ascii'), b'b'.decode('ascii'), b'c'.decode('ascii'), b'd'.decode('ascii'), b'e'.decode('ascii'), b'f'.decode('ascii')))
224
225        self.assertRaises(ValueError, a.arrayByAddingObjects_count_, (b'a'.decode('ascii'),b'b'.decode('ascii')), 3)
226    def test_sortedArrayUsingFunction_context_(self):
227        a = NSArray.arrayWithArray_((b'a'.decode('ascii'), b'b'.decode('ascii'), b'c'.decode('ascii')))
228        self.assertEqual(a, (b'a'.decode('ascii'), b'b'.decode('ascii'), b'c'.decode('ascii')))
229
230        def cmpfunc(l, r, c):
231            return -cmp(l,r)
232
233        b = a.sortedArrayUsingFunction_context_(cmpfunc, b'hello'.decode('ascii'))
234        self.assertEqual(a, (b'a'.decode('ascii'), b'b'.decode('ascii'), b'c'.decode('ascii')))
235        self.assertEqual(b, (b'c'.decode('ascii'), b'b'.decode('ascii'), b'a'.decode('ascii')))
236
237    def test_sortedArrayUsingFunction_context_hint_(self):
238        a = NSArray.arrayWithArray_((b'a'.decode('ascii'), b'b'.decode('ascii'), b'c'.decode('ascii')))
239        self.assertEqual(a, (b'a'.decode('ascii'), b'b'.decode('ascii'), b'c'.decode('ascii')))
240
241        def cmpfunc(l, r, c):
242            return -cmp(l,r)
243
244        b = a.sortedArrayUsingFunction_context_hint_(cmpfunc, b'hello'.decode('ascii'), a.sortedArrayHint())
245        self.assertEqual(a, (b'a'.decode('ascii'), b'b'.decode('ascii'), b'c'.decode('ascii')))
246        self.assertEqual(b, (b'c'.decode('ascii'), b'b'.decode('ascii'), b'a'.decode('ascii')))
247
248class TestNSMutableArrayInteraction(TestCase):
249
250    def testRemoveObjects(self):
251        a = NSMutableArray.arrayWithArray_(range(10))
252
253        self.assertEqual(len(a), 10)
254        self.assertEqual(a[0], 0)
255        self.assertEqual(a[1], 1)
256        self.assertEqual(a[2], 2)
257
258        a.removeObjectsFromIndices_numIndices_([2, 4, 6, 8], 3)
259
260        self.assertEqual(len(a), 7)
261        self.assertEqual(a, (0, 1, 3, 5, 7, 8, 9))
262
263
264    def testReplaceObjects(self):
265        if objc.platform == 'MACOSX' or hasattr(NSMutableArray, 'replaceObjectsInRange_withObjects_count_'):
266
267            a = NSMutableArray.arrayWithArray_(range(4))
268            self.assertEqual(a, (0, 1, 2, 3))
269
270            a.replaceObjectsInRange_withObjects_count_(
271                (1,2), [b"a".decode('ascii'), b"b".decode('ascii'), b"c".decode('ascii'), b"d".decode('ascii')], 3)
272
273            self.assertEqual(a, (0, b"a".decode('ascii'), b"b".decode('ascii'), b"c".decode('ascii'), 3))
274
275    def testSortInvalid(self):
276        # Invalid calls to sortUsingFunction:context:
277        def cmp(a, b):
278            return -1
279
280        a = NSMutableArray.arrayWithArray_(range(4))
281        self.assertEqual(a, (0, 1, 2, 3))
282
283        t = objc.getVerbose()
284        objc.setVerbose(0)
285        try:
286            self.assertRaises(TypeError, a.sortUsingFunction_context_, dir)
287            self.assertRaises(TypeError, a.sortUsingFunction_context_, dir, 1, 2)
288            self.assertRaises(TypeError, a.sortUsingFunction_context_, lambda *args: cmp(*args), b'a'.decode('ascii'))
289        finally:
290            objc.setVerbose(t)
291
292    def dont_testSort2(self):
293        # sortUsingFunction:context:range: isn't documented an hence shouldn't be tested
294        a = NSMutableArray.arrayWithArray_(range(10))
295        self.assertEqual(a, (0, 1, 2, 3, 4, 5, 6, 7, 8, 9))
296
297        if objc.platform == 'MACOSX' or hasattr(a, 'sortUsingFunction_context_range_'):
298            def cmpfunc(l, r, c):
299                return -cmp(l,r)
300
301            a.sortUsingFunction_context_range_(cmpfunc, b"a".decode('ascii'), (4, 4))
302
303            self.assertEqual(a, (0, 1, 2, 3, 7, 6, 5, 4, 8, 9))
304
305    def testSort3(self):
306        # check the sort method, list interface compatibility
307
308        a = NSMutableArray.arrayWithArray_(range(4))
309        self.assertEqual(a, (0, 1, 2, 3))
310
311        def cmpfunc(l, r):
312            return -cmp(l,r)
313
314        a.sort(cmpfunc)
315
316        self.assertEqual(a, (3, 2, 1, 0))
317
318        a.sort()
319        self.assertEqual(a, (0, 1, 2, 3))
320
321    def testSort1(self):
322        a = NSMutableArray.arrayWithArray_(range(4))
323        self.assertEqual(a, (0, 1, 2, 3))
324
325        def cmpfunc(l, r, c):
326            return -cmp(l,r)
327
328        a.sortUsingFunction_context_(cmpfunc, b"a".decode('ascii'))
329
330        self.assertEqual(a, (3, 2, 1, 0))
331
332    def dont_testSort2(self):
333        a = NSMutableArray.arrayWithArray_(range(10))
334        self.assertEqual(a, (0, 1, 2, 3, 4, 5, 6, 7, 8, 9))
335
336        if objc.platform == 'MACOSX' or hasattr(a, 'sortUsingFunction_context_range_'):
337            def cmpfunc(l, r, c):
338                return -cmp(l,r)
339
340            a.sortUsingFunction_context_range_(cmpfunc, b"a".decode('ascii'), (4, 4))
341
342            self.assertEqual(a, (0, 1, 2, 3, 7, 6, 5, 4, 8, 9))
343
344    def testSort3(self):
345        # check the sort method, list interface compatibility
346
347        a = NSMutableArray.arrayWithArray_(range(4))
348        self.assertEqual(a, (0, 1, 2, 3))
349
350
351        def cmpfunc(l, r):
352            return -cmp(l,r)
353
354        a.sort(cmpfunc=cmpfunc)
355
356        self.assertEqual(a, (3, 2, 1, 0))
357
358        a.sort()
359
360        self.assertEqual(a, (0, 1, 2, 3))
361
362        map={
363            0: "nul",
364            1: "een",
365            2: "twee",
366            3: "drie",
367        }
368
369
370        def keyfunc(l):
371            return  map[l]
372
373        a.sort(key=keyfunc)
374        self.assertEqual(a, (3, 1, 0, 2))
375
376        a.sort(key=keyfunc, reverse=True)
377        self.assertEqual(a, (2, 0, 1, 3))
378
379        a.sort(reverse=True)
380        self.assertEqual(a, (3, 2, 1, 0))
381
382    def getObjectsRange(self):
383        o = NSArray.arrayWithArray_(range(4, 8))
384        v =  o.getObjects_range_((1,2))
385        self.assertEqual(v, (5,6))
386
387    def test_unsupportedMethods(self):
388        #
389        # Check that calling unsupported methods results in a TypeError
390        #
391        # NOTE: Some of these don't even exist on GNUstep
392        o = NSArray.arrayWithArray_(range(4))
393        self.assertRaises(TypeError, o.getObjects_)
394
395        #
396        #if objc.platform == 'MACOSX' or hasattr(o, 'apply_context_'):
397        #    self.assertRaises(TypeError, o.apply_context_, lambda x, y:None, 0)
398
399
400    def testInsert(self):
401        o = NSMutableArray.arrayWithArray_(range(4))
402        self.assertEqual(list(o), list(range(4)))
403
404        self.assertEqual(o[0], 0)
405        o.insert(0, "foo")
406        self.assertEqual(o[0], "foo")
407        self.assertEqual(o[1], 0)
408        self.assertEqual(len(o), 5)
409
410        # FIXME: test the entire interface of list.insert
411
412class TestVariadic (TestCase):
413    def testArrayWithObjects(self):
414        a = NSArray.arrayWithObjects_(b"foo".decode('ascii'), b"bar".decode('ascii'), None)
415        self.assertEqual(a, (b"foo".decode('ascii'), b"bar".decode('ascii')))
416        self.assertIsInstance(a, NSArray)
417
418        a = NSMutableArray.arrayWithObjects_(b"foo".decode('ascii'), b"bar".decode('ascii'), None)
419        self.assertEqual(a, [b"foo".decode('ascii'), b"bar".decode('ascii')])
420        self.assertIsInstance(a, NSMutableArray)
421
422    def testInitWithObjecs(self):
423        a = NSArray.alloc().initWithObjects_(b"foo".decode('ascii'), b"bar".decode('ascii'), None)
424        self.assertEqual(a, (b"foo".decode('ascii'), b"bar".decode('ascii')))
425        self.assertIsInstance(a, NSArray)
426
427        a = NSMutableArray.alloc().initWithObjects_(b"foo".decode('ascii'), b"bar".decode('ascii'), None)
428        self.assertEqual(a, [b"foo".decode('ascii'), b"bar".decode('ascii')])
429        self.assertIsInstance(a, NSMutableArray)
430
431class TestNSArray (TestCase):
432    def testMethods(self):
433        self.assertResultIsBOOL(NSArray.isEqualToArray_)
434        self.assertResultIsBOOL(NSArray.containsObject_)
435        self.assertResultIsBOOL(NSArray.writeToFile_atomically_)
436        self.assertArgIsBOOL(NSArray.writeToFile_atomically_, 1)
437        self.assertResultIsBOOL(NSArray.writeToURL_atomically_)
438        self.assertArgIsBOOL(NSArray.writeToURL_atomically_, 1)
439
440        self.assertArgIsSEL(NSArray.makeObjectsPerformSelector_, 0, b'v@:')
441        self.assertArgIsSEL(NSArray.makeObjectsPerformSelector_withObject_, 0, b'v@:@')
442
443        self.assertArgIsBOOL(NSArray.initWithArray_copyItems_, 1)
444
445        self.assertArgIsIn(NSArray.arrayWithObjects_count_, 0)
446        self.assertArgSizeInArg(NSArray.arrayWithObjects_count_, 0, 1)
447        self.assertArgIsIn(NSArray.initWithObjects_count_, 0)
448        self.assertArgSizeInArg(NSArray.initWithObjects_count_, 0, 1)
449
450        self.assertArgIsIn(NSMutableArray.removeObjectsFromIndices_numIndices_, 0)
451        self.assertArgSizeInArg(NSMutableArray.removeObjectsFromIndices_numIndices_, 0, 1)
452
453        self.assertArgIsFunction(NSArray.sortedArrayUsingFunction_context_, 0, b'l@@@', False)
454        self.assertArgHasType(NSArray.sortedArrayUsingFunction_context_, 1, b'@')
455        self.assertArgIsFunction(NSArray.sortedArrayUsingFunction_context_hint_, 0, b'l@@@', False)
456        self.assertArgHasType(NSArray.sortedArrayUsingFunction_context_hint_, 1, b'@')
457        self.assertArgIsSEL(NSArray.sortedArrayUsingSelector_, 0, b'i@:@')
458
459        self.assertArgIsFunction(NSMutableArray.sortUsingFunction_context_, 0, b'l@@@', False)
460        self.assertArgHasType(NSMutableArray.sortUsingFunction_context_, 1, b'@')
461
462        self.assertArgIsSEL(NSMutableArray.sortUsingSelector_, 0, b'i@:@')
463
464        self.assertIsNullTerminated(NSArray.arrayWithObjects_)
465        self.assertIsNullTerminated(NSArray.initWithObjects_)
466
467    @min_os_level('10.6')
468    def testMethods10_6(self):
469        self.assertArgIsBlock(NSArray.enumerateObjectsUsingBlock_, 0,
470                b'v@'+objc._C_NSUInteger+b'o^'+objc._C_NSBOOL)
471        self.assertArgIsBlock(NSArray.enumerateObjectsWithOptions_usingBlock_, 1,
472                b'v@'+objc._C_NSUInteger+b'o^'+objc._C_NSBOOL)
473        self.assertArgIsBlock(NSArray.enumerateObjectsAtIndexes_options_usingBlock_, 2,
474                b'v@'+objc._C_NSUInteger+b'o^'+objc._C_NSBOOL)
475
476        self.assertArgIsBlock(NSArray.indexOfObjectPassingTest_, 0,
477                objc._C_NSBOOL + b'@'+objc._C_NSUInteger+b'o^'+objc._C_NSBOOL)
478        self.assertArgIsBlock(NSArray.indexOfObjectWithOptions_passingTest_, 1,
479                objc._C_NSBOOL + b'@'+objc._C_NSUInteger+b'o^'+objc._C_NSBOOL)
480        self.assertArgIsBlock(NSArray.indexOfObjectAtIndexes_options_passingTest_, 2,
481                objc._C_NSBOOL + b'@'+objc._C_NSUInteger+b'o^'+objc._C_NSBOOL)
482
483        self.assertArgIsBlock(NSArray.indexesOfObjectsPassingTest_, 0,
484                objc._C_NSBOOL + b'@'+objc._C_NSUInteger+b'o^'+objc._C_NSBOOL)
485        self.assertArgIsBlock(NSArray.indexesOfObjectsWithOptions_passingTest_, 1,
486                objc._C_NSBOOL + b'@'+objc._C_NSUInteger+b'o^'+objc._C_NSBOOL)
487        self.assertArgIsBlock(NSArray.indexesOfObjectsAtIndexes_options_passingTest_, 2,
488                objc._C_NSBOOL + b'@'+objc._C_NSUInteger+b'o^'+objc._C_NSBOOL)
489
490        self.assertArgIsBlock(NSArray.sortedArrayUsingComparator_,
491                0, b'l@@')
492        self.assertArgIsBlock(NSArray.sortedArrayWithOptions_usingComparator_,
493                1, b'l@@')
494        self.assertArgIsBlock(NSArray.indexOfObject_inSortedRange_options_usingComparator_,
495                3, b'l@@')
496        self.assertArgHasType(NSArray.indexOfObject_inSortedRange_options_usingComparator_, 1, NSRange.__typestr__)
497
498
499
500        self.assertArgIsBlock(NSMutableArray.sortUsingComparator_,
501                0, objc._C_NSInteger + b'@@')
502        self.assertArgIsBlock(NSMutableArray.sortWithOptions_usingComparator_,
503                1, objc._C_NSInteger + b'@@')
504
505
506
507    @min_os_level('10.6')
508    def testConstants10_6(self):
509        self.assertEqual(NSBinarySearchingFirstEqual, 1 << 8)
510        self.assertEqual(NSBinarySearchingLastEqual, 1 << 9)
511        self.assertEqual(NSBinarySearchingInsertionIndex, 1 << 10)
512
513if __name__ == '__main__':
514    main()
515