1from PyObjCTools.TestSupport import *
2import objc
3import types
4import sys
5
6from PyObjCTest.testhelper import PyObjC_TestClass3
7
8from Foundation import *
9
10
11class TestNSDictionarySubclassing(TestCase):
12    # These tests seem to be specific for MacOSX
13    def testExceptionInInit(self):
14        if objc.platform != 'MACOSX': return
15
16        class DictTestExceptionClass (NSDictionary):
17            pass
18
19        # Don't use self.assertRaises here, we once had a bug that
20        # causes this to fail, while the assertRaises version would
21        # (probably) have worked.
22        import warnings
23        warnings.filterwarnings('ignore',
24            category=objc.UninitializedDeallocWarning)
25
26        try:
27            try:
28                d = DictTestExceptionClass.alloc().initWithDictionary_({})
29                self.fail()
30            except ValueError:
31                pass
32        finally:
33            del warnings.filters[0]
34
35    def testAnotherExceptionInInit(self):
36        if objc.platform != 'MACOSX': return
37
38        class DictTestExceptionClass2 (NSDictionary):
39            def initWithObjects_forKeys_count_(self, o, k, c):
40                return super(DictTestExceptionClass2, self).initWithObjects_forKeys_count_(o, k, c)
41
42        import warnings
43        warnings.filterwarnings('ignore',
44            category=objc.UninitializedDeallocWarning)
45
46        try:
47            try:
48                d = DictTestExceptionClass2.alloc().initWithDictionary_({})
49                self.fail()
50            except ValueError:
51                pass
52        finally:
53            del warnings.filters[0]
54
55
56    def testExceptionInInitClsMeth(self):
57        if objc.platform != 'MACOSX': return
58
59        class DictTestExceptionClass3 (NSDictionary):
60            def initWithObjects_forKeys_count_(self, o, k, c):
61                return super(DictTestExceptionClass3, self).initWithObjects_forKeys_count_(o, k, c)
62
63        try:
64            d = DictTestExceptionClass3.dictionaryWithDictionary_({})
65            self.fail()
66        except ValueError:
67            pass
68
69
70class TestNSDictionaryInteraction(TestCase):
71    def testMethods(self):
72        for nm in dir(dict):
73            if nm.startswith('__'):
74                continue
75
76            if isinstance(getattr(dict, nm), (types.BuiltinFunctionType, types.FunctionType)):
77                # Skip class methods, that needs more work in the core
78                continue
79
80            self.assertTrue(hasattr(NSMutableDictionary, nm), "NSMutableDictionary has no method '%s'"%(nm,))
81
82    def testRepeatedAllocInit(self):
83        for i in range(1,1000):
84            d = NSDictionary.alloc().init()
85
86    def testBasicInteraction(self):
87        d = NSMutableDictionary.dictionary()
88        d[b'a'.decode('ascii')] = b"foo".decode('ascii')
89        d[b'b'.decode('ascii')] = b"bar".decode('ascii')
90
91        self.assertEqual(d[b'a'.decode('ascii')], b"foo".decode('ascii'), "Failed to retrieve the same thing that was put into the dict.")
92        try:
93            d[b'c'.decode('ascii')]
94            self.fail("Should have raised...")
95        except KeyError:
96            pass
97
98    def testPythonIteraction(self):
99        d = NSMutableDictionary.dictionary()
100        d[b'a'.decode('ascii')] = b"foo".decode('ascii')
101        d[b'b'.decode('ascii')] = b"bar".decode('ascii')
102
103        k = list(d.keys())
104        k.sort()
105        self.assertTrue(k == [b'a'.decode('ascii'), b'b'.decode('ascii')])
106
107        k = list(d.values())
108        k.sort()
109        self.assertTrue(k == [b'bar'.decode('ascii'), b'foo'.decode('ascii')])
110
111        k = list(d.items())
112        k.sort()
113        self.assertTrue(k == [(b'a'.decode('ascii'), b'foo'.decode('ascii')), (b'b'.decode('ascii'), b'bar'.decode('ascii')) ])
114
115
116    def testIn(self):
117        d = NSMutableDictionary.dictionary()
118        d[b'a'.decode('ascii')] = b"foo".decode('ascii')
119        d[b'b'.decode('ascii')] = b"bar".decode('ascii')
120        d[1] = b"baz".decode('ascii')
121        d[0] = b"bob".decode('ascii')
122        # d[-1] = None -- this fails because the bridge doesn't proxy py(None) to objc(NSNull)... not sure if it should
123
124        self.assertTrue( b'a'.decode('ascii') in d )
125        self.assertTrue( 1 in d )
126        # self.assertTrue( -1 in d )
127        # self.assertTrue( d[-1] is None )
128        self.assertTrue( b'q'.decode('ascii') not in d )
129
130        for k in d.allKeys():
131            self.assertEqual( d.objectForKey_( k ), d[k] )
132
133        for k in d:
134            self.assertEqual( d.objectForKey_( k ), d[k] )
135
136        del d[b'a'.decode('ascii')]
137        self.assertTrue( b'a'.decode('ascii') not in d )
138
139    def test_varargConstruction(self):
140        u = NSDictionary.dictionaryWithObjects_forKeys_([1,2,3,4], [b'one'.decode('ascii'), b'two'.decode('ascii'), b'three'.decode('ascii'), b'four'.decode('ascii')])
141        v = NSDictionary.alloc().initWithObjects_forKeys_([1,2,3,4], [b'one'.decode('ascii'), b'two'.decode('ascii'), b'three'.decode('ascii'), b'four'.decode('ascii')])
142        w = NSDictionary.dictionaryWithObjects_forKeys_count_([1,2,3,4,5], [b'one'.decode('ascii'), b'two'.decode('ascii'), b'three'.decode('ascii'), b'four'.decode('ascii'), b'five'.decode('ascii')], 4)
143        x = NSDictionary.alloc().initWithObjects_forKeys_count_([1,2,3,4,5], [b'one'.decode('ascii'), b'two'.decode('ascii'), b'three'.decode('ascii'), b'four'.decode('ascii'), b'five'.decode('ascii')], 4)
144        y = NSDictionary.dictionaryWithObjectsAndKeys_(1, b'one'.decode('ascii'), 2, b'two'.decode('ascii'), 3, b'three'.decode('ascii'), 4, b'four'.decode('ascii'), None)
145        z = NSDictionary.alloc().initWithObjectsAndKeys_(1, b'one'.decode('ascii'), 2, b'two'.decode('ascii'), 3, b'three'.decode('ascii'), 4, b'four'.decode('ascii'), None)
146
147        self.assertEqual(len(u), 4)
148        self.assertEqual(len(v), 4)
149        self.assertEqual(len(w), 4)
150        self.assertEqual(len(x), 4)
151        self.assertEqual(len(y), 4)
152        self.assertEqual(len(z), 4)
153
154        self.assertEqual(u[b'one'.decode('ascii')], 1)
155        self.assertEqual(v[b'two'.decode('ascii')], 2)
156        self.assertEqual(w[b'three'.decode('ascii')], 3)
157        self.assertEqual(x[b'one'.decode('ascii')], 1)
158        self.assertEqual(y[b'two'.decode('ascii')], 2)
159        self.assertEqual(z[b'four'.decode('ascii')], 4)
160
161    def test_varargConstruction2(self):
162        u = NSMutableDictionary.dictionaryWithObjects_forKeys_([1,2,3,4], [b'one'.decode('ascii'), b'two'.decode('ascii'), b'three'.decode('ascii'), b'four'.decode('ascii')])
163        v = NSMutableDictionary.alloc().initWithObjects_forKeys_([1,2,3,4], [b'one'.decode('ascii'), b'two'.decode('ascii'), b'three'.decode('ascii'), b'four'.decode('ascii')])
164        w = NSMutableDictionary.dictionaryWithObjects_forKeys_count_([1,2,3,4,5], [b'one'.decode('ascii'), b'two'.decode('ascii'), b'three'.decode('ascii'), b'four'.decode('ascii'), b'five'.decode('ascii')], 4)
165        x = NSMutableDictionary.alloc().initWithObjects_forKeys_count_([1,2,3,4,5], [b'one'.decode('ascii'), b'two'.decode('ascii'), b'three'.decode('ascii'), b'four'.decode('ascii'), b'five'.decode('ascii')], 4)
166
167        #self.assertRaises(TypeError, NSMutableDictionary.dictionaryWithObjectsAndKeys_, 1, 'one', 2, 'two', None)
168        y = NSMutableDictionary.dictionaryWithObjectsAndKeys_(1, b'one'.decode('ascii'), 2, b'two'.decode('ascii'), 3, b'three'.decode('ascii'), 4, b'four'.decode('ascii'), None)
169        z = NSMutableDictionary.alloc().initWithObjectsAndKeys_(1, b'one'.decode('ascii'), 2, b'two'.decode('ascii'), 3, b'three'.decode('ascii'), 4, b'four'.decode('ascii'), None)
170
171        self.assertEqual(len(u), 4)
172        self.assertEqual(len(v), 4)
173        self.assertEqual(len(w), 4)
174        self.assertEqual(len(x), 4)
175        #self.assertEqual(len(y), 4)
176        #self.assertEqual(len(z), 4)
177
178        self.assertEqual(u[b'one'.decode('ascii')], 1)
179        self.assertEqual(v[b'two'.decode('ascii')], 2)
180        self.assertEqual(w[b'three'.decode('ascii')], 3)
181        self.assertEqual(x[b'one'.decode('ascii')], 1)
182        #self.assertEqual(y[b'two'.decode('ascii')], 2)
183        #self.assertEqual(z[b'four'.decode('ascii')], 4)
184
185
186class MyDictionaryBase (NSDictionary):
187    def count(self):
188        if hasattr(self, '_count'):
189            return self._count
190        return -1
191
192    def keyEnumerator(self):
193        return None
194
195    def objectForKey_(self, key):
196        return None
197
198class MyDictionary1 (MyDictionaryBase):
199    def initWithObjects_forKeys_count_(self, objects, keys, count):
200        self._count = count
201        self._objects = objects
202        self._keys = keys
203        return self
204
205class MyDictionary2 (MyDictionaryBase):
206    def dictionaryWithObjects_forKeys_count_(self, objects, keys, count):
207        if not self is MyDictionary2: raise AssertionError(self)
208        return (objects, keys, count)
209
210class TestSubclassing (TestCase):
211    def testInitWithObjects(self):
212        o = PyObjC_TestClass3.makeDictFromClass_method_(MyDictionary1, 1)
213
214        self.assertIsInstance(o, MyDictionary1)
215        self.assertEqual(o._count, 4)
216        self.assertEqual(len(o._keys), 4)
217        self.assertEqual(len(o._objects), 4)
218
219    def testDictWithObjects(self):
220        o = PyObjC_TestClass3.makeDictFromClass_method_(MyDictionary2, 0)
221
222        self.assertIsInstance(o, tuple)
223        self.assertEqual(o[2], 4)
224        self.assertEqual(len(o[1]), 4)
225        self.assertEqual(len(o[0]), 4)
226
227class TestVariadic (TestCase):
228    def testDictionaryWithObjectsAndKeys(self):
229        o = NSDictionary.dictionaryWithObjectsAndKeys_(
230                42, 'a',
231                43, 'b')
232        self.assertEqual(o, {'a':42, 'b':43})
233        self.assertIsInstance(o, NSDictionary)
234
235        o = NSMutableDictionary.dictionaryWithObjectsAndKeys_(
236                42, 'a',
237                43, 'b')
238        self.assertEqual(o, {'a':42, 'b':43})
239        self.assertIsInstance(o, NSMutableDictionary)
240
241    def testInitWithObjectsAndKeys(self):
242        o = NSDictionary.alloc().initWithObjectsAndKeys_(
243                42, 'a',
244                43, 'b')
245        self.assertEqual(o, {'a':42, 'b':43})
246        self.assertIsInstance(o, NSDictionary)
247
248        o = NSMutableDictionary.alloc().initWithObjectsAndKeys_(
249                42, 'a',
250                43, 'b')
251        self.assertEqual(o, {'a':42, 'b':43})
252        self.assertIsInstance(o, NSMutableDictionary)
253
254
255class TestNSDictionary (TestCase):
256    def testMethods(self):
257        self.assertResultIsBOOL(NSDictionary.isEqualToDictionary_)
258        self.assertResultIsBOOL(NSDictionary.writeToFile_atomically_)
259        self.assertArgIsBOOL(NSDictionary.writeToFile_atomically_, 1)
260        self.assertResultIsBOOL(NSDictionary.writeToURL_atomically_)
261        self.assertArgIsBOOL(NSDictionary.writeToURL_atomically_, 1)
262
263        self.assertArgIsSEL(NSDictionary.keysSortedByValueUsingSelector_, 0, b'i@:@')
264
265        self.assertArgIsIn(NSDictionary.dictionaryWithObjects_forKeys_count_, 0)
266        self.assertArgSizeInArg(NSDictionary.dictionaryWithObjects_forKeys_count_, 0, 2)
267        self.assertArgIsIn(NSDictionary.dictionaryWithObjects_forKeys_count_, 1)
268        self.assertArgSizeInArg(NSDictionary.dictionaryWithObjects_forKeys_count_, 1, 2)
269
270        self.assertArgIsIn(NSDictionary.initWithObjects_forKeys_count_, 0)
271        self.assertArgSizeInArg(NSDictionary.initWithObjects_forKeys_count_, 0, 2)
272        self.assertArgIsIn(NSDictionary.initWithObjects_forKeys_count_, 1)
273        self.assertArgSizeInArg(NSDictionary.initWithObjects_forKeys_count_, 1, 2)
274
275        self.assertArgIsBOOL(NSDictionary.initWithDictionary_copyItems_, 1)
276
277        self.assertIsNullTerminated(NSDictionary.initWithObjectsAndKeys_)
278        self.assertIsNullTerminated(NSDictionary.dictionaryWithObjectsAndKeys_)
279
280    @min_os_level('10.6')
281    def testMethods10_6(self):
282        self.assertArgIsBlock(NSDictionary.enumerateKeysAndObjectsUsingBlock_, 0, b'v@@o^'+objc._C_NSBOOL)
283        self.assertArgIsBlock(NSDictionary.enumerateKeysAndObjectsWithOptions_usingBlock_, 1, b'v@@o^'+objc._C_NSBOOL)
284        self.assertArgIsBlock(NSDictionary.keysSortedByValueUsingComparator_, 0, b'i@@')
285        self.assertArgIsBlock(NSDictionary.keysSortedByValueWithOptions_usingComparator_, 1, objc._C_NSInteger + b'@@')
286
287        self.assertArgIsBlock(NSDictionary.keysOfEntriesPassingTest_, 0, objc._C_NSBOOL + b'@@o^' + objc._C_NSBOOL)
288        self.assertArgIsBlock(NSDictionary.keysOfEntriesWithOptions_passingTest_, 1, objc._C_NSBOOL + b'@@o^' + objc._C_NSBOOL)
289
290if __name__ == '__main__':
291    main( )
292